nielsm-metric_fu 1.1.1 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/HISTORY +46 -0
  2. data/Rakefile +4 -7
  3. data/TODO +0 -4
  4. data/lib/base/base_template.rb +1 -2
  5. data/lib/base/configuration.rb +9 -35
  6. data/lib/base/generator.rb +9 -1
  7. data/lib/base/graph.rb +5 -3
  8. data/lib/base/report.rb +3 -3
  9. data/lib/generators/churn.rb +15 -72
  10. data/lib/generators/flay.rb +3 -2
  11. data/lib/generators/flog.rb +33 -6
  12. data/lib/generators/rcov.rb +32 -37
  13. data/lib/generators/reek.rb +28 -1
  14. data/lib/generators/roodi.rb +2 -1
  15. data/lib/generators/saikuro.rb +53 -40
  16. data/lib/generators/stats.rb +29 -13
  17. data/lib/graphs/engines/bluff.rb +86 -0
  18. data/lib/graphs/engines/gchart.rb +118 -0
  19. data/lib/graphs/flay_grapher.rb +6 -20
  20. data/lib/graphs/flog_grapher.rb +25 -22
  21. data/lib/graphs/grapher.rb +11 -0
  22. data/lib/graphs/rcov_grapher.rb +2 -16
  23. data/lib/graphs/reek_grapher.rb +12 -24
  24. data/lib/graphs/roodi_grapher.rb +6 -20
  25. data/lib/metric_fu.rb +13 -6
  26. data/lib/templates/awesome/awesome_template.rb +7 -0
  27. data/lib/templates/awesome/churn.html.erb +39 -0
  28. data/lib/templates/awesome/css/buttons.css +82 -0
  29. data/lib/templates/awesome/{default.css → css/default.css} +16 -0
  30. data/lib/templates/awesome/css/integrity.css +335 -0
  31. data/lib/templates/awesome/css/reset.css +7 -0
  32. data/lib/templates/awesome/flay.html.erb +8 -1
  33. data/lib/templates/awesome/flog.html.erb +8 -1
  34. data/lib/templates/awesome/layout.html.erb +7 -4
  35. data/lib/templates/awesome/rcov.html.erb +7 -1
  36. data/lib/templates/awesome/reek.html.erb +7 -1
  37. data/lib/templates/awesome/roodi.html.erb +7 -1
  38. data/lib/templates/javascripts/bluff-min.js +1 -0
  39. data/lib/templates/javascripts/excanvas.js +35 -0
  40. data/lib/templates/javascripts/js-class.js +1 -0
  41. data/spec/base/configuration_spec.rb +21 -54
  42. data/spec/base/generator_spec.rb +63 -0
  43. data/spec/base/graph_spec.rb +24 -0
  44. data/spec/generators/churn_spec.rb +16 -125
  45. data/spec/generators/flay_spec.rb +11 -5
  46. data/spec/generators/flog_spec.rb +19 -0
  47. data/spec/generators/reek_spec.rb +65 -0
  48. data/spec/graphs/engines/bluff_spec.rb +16 -0
  49. data/spec/graphs/engines/gchart_spec.rb +108 -0
  50. data/spec/graphs/flay_grapher_spec.rb +37 -0
  51. data/spec/graphs/flog_grapher_spec.rb +40 -10
  52. data/spec/graphs/rcov_grapher_spec.rb +37 -0
  53. data/spec/graphs/reek_grapher_spec.rb +46 -0
  54. data/spec/graphs/roodi_grapher_spec.rb +37 -0
  55. data/spec/resources/saikuro/app/controllers/sessions_controller.rb_cyclo.html +0 -0
  56. data/spec/resources/saikuro/app/controllers/users_controller.rb_cyclo.html +0 -0
  57. data/spec/resources/saikuro/index_cyclo.html +0 -0
  58. data/spec/resources/saikuro_sfiles/thing.rb_cyclo.html +1 -0
  59. data/spec/resources/yml/20090630.yml +7844 -0
  60. data/spec/spec.opts +2 -4
  61. data/spec/spec_helper.rb +2 -23
  62. data/tasks/metric_fu.rake +1 -1
  63. metadata +72 -14
  64. data/vendor/_fonts/monaco.ttf +0 -0
  65. data/vendor/saikuro/saikuro.rb +0 -1214
data/HISTORY CHANGED
@@ -1,3 +1,49 @@
1
+ === MetricFu 1.3.0 / 2010-01-26
2
+
3
+ * Flay can be configured to ignore scores below a threshold (by default it ignores scores less than 100)
4
+ * When running Rcov you can configure the RAILS_ENV (defaults to 'test') so running metric_fu doesn't interfere with other environments
5
+ * Changed devver-construct (a gem hosted by GitHub) development dependency to test-construct dependency (on Gemcutter) - Dan Mayer
6
+ * Upgrade Bluff to 0.3.6 and added tooltips to graphs - Édouard Brière
7
+ * Removed Saikuro from vendor and added it as a gem dependency - Édouard Brière
8
+ * Churn has moved outside metric_fu and is now a gem and a dependency - Dan Mayer
9
+ * Fix 'activesupport' deprecation (it should be 'active_support') - Bryan Helmkamp
10
+ * Declared development dependencies
11
+ * Cleaned and sped up specs
12
+
13
+ === MetricFu 1.2.0 / 2010-01-09
14
+
15
+ * ftools isn't supported by 1.9 so moved to fileutils.
16
+ * Overhauled the graphing to use Gruff or Google Charts so we no longer depend on ImageMagick/rmagick -- thanks to Carl Youngblood.
17
+ * Stopped relying on Github gems as they will be going away.
18
+
19
+ === MetricFu 1.1.6 / 2009-12-14
20
+
21
+ * Now compatible with Reek 1.2x thanks to Kevin Rutherford
22
+ * Fixed problem with deleted files still showing up in Flog reports thanks to Dan Mayer
23
+
24
+ === MetricFu 1.1.5 / 2009-8-13
25
+
26
+ * Previous Ruby 1.9 fix was not quite fix-y enough
27
+
28
+ === MetricFu 1.1.4 / 2009-7-13
29
+
30
+ * Fixed another Ruby 1.9x bug
31
+
32
+ === MetricFu 1.1.3 / 2009-7-10
33
+
34
+ * MetricFu is now Ruby 1.9x compatible
35
+ * Removed the check for deprecated ways of configuring metric_fu as the tests were causing Ruby 1.9x problems and it's been forever since they were supported.
36
+ * Removed total flog score from graph (which will always go up and so doesn't mean much) and replacing it with top_five_percent_average which is an average of the worst 5 percent of your methods.
37
+ * Sort Flog by highest score in the class which I feel is more important than the total flog flog score.
38
+
39
+ === MetricFu 1.1.2 / 2009-7-09
40
+
41
+ * Removed dependency on gruff and rmagick (unless the user wants graphs, of course).
42
+ * New look for styling -- Edouard Brière
43
+ * Extra param in rcov call was causing problems -- Stewart Welbourne
44
+ * Preventing rake task from being run multiple times when other rake tasks switch the environment -- Matthew Van Horn
45
+ * Typo in Rcov dependency verification and fixing parsing Saikuro nested information -- Mark Wilden
46
+
1
47
  === MetricFu 1.1.1 / 2009-6-29
2
48
 
3
49
  * Fix for empty flog files
data/Rakefile CHANGED
@@ -2,17 +2,14 @@ require 'rake'
2
2
  require 'rake/rdoctask'
3
3
  require 'spec/rake/spectask'
4
4
  require 'lib/metric_fu'
5
-
5
+
6
6
  desc "Run all specs in spec directory"
7
7
  Spec::Rake::SpecTask.new(:spec) do |t|
8
8
  t.spec_files = FileList['spec/**/*_spec.rb']
9
- t.rcov = true
10
- t.rcov_opts = ['--exclude', 'spec,config,Library,usr/lib/ruby']
11
- t.rcov_dir = File.join(File.dirname(__FILE__), "tmp")
12
9
  end
13
-
10
+
14
11
  MetricFu::Configuration.run do |config|
15
12
  config.template_class = AwesomeTemplate
16
13
  end
17
-
18
- task :default => [:"metrics:all"]
14
+
15
+ task :default => :spec
data/TODO CHANGED
@@ -2,10 +2,6 @@
2
2
 
3
3
  * Color code flog results with scale from: http://jakescruggs.blogspot.com/2008/08/whats-good-flog-score.html
4
4
  * Integrate Flog, Saikuro, and Coverage into one report so you can see methods that have high complexity and low coverage (this is a big one)
5
- * Move HTML out of code and into templates/
6
- * Replace #generate_report with #new on each metric class
7
- * Make each class descend from MetricFu::CodeMetric
8
- * Generate metrics:* rake tasks for each of CodeMetric's descendants
9
5
  * Update flog specs so that they actually run flog
10
6
  * Add flay specs that run flay
11
7
  * Convert readme to markdown and rename to README.mkdn so github will render it
@@ -139,8 +139,7 @@ module MetricFu
139
139
  def cycle(first_value, second_value, iteration)
140
140
  return first_value if iteration % 2 == 0
141
141
  return second_value
142
- end
143
-
142
+ end
144
143
 
145
144
  end
146
145
  end
@@ -9,6 +9,7 @@ module MetricFu
9
9
  :roodi, :saikuro, :rcov]
10
10
 
11
11
  AVAILABLE_GRAPHS = [:flog, :flay, :reek, :roodi, :rcov]
12
+ AVAILABLE_GRAPH_ENGINES = [:gchart, :bluff]
12
13
 
13
14
  # The @@configuration class variable holds a global type configuration
14
15
  # object for any parts of the system to use.
@@ -51,7 +52,6 @@ module MetricFu
51
52
  class Configuration
52
53
 
53
54
  def initialize #:nodoc:#
54
- warn_about_deprecated_config_options
55
55
  reset
56
56
  add_attr_accessors_to_self
57
57
  add_class_methods_to_metric_fu
@@ -82,25 +82,6 @@ module MetricFu
82
82
  end
83
83
  end
84
84
 
85
- # Check if certain constants that are deprecated have been
86
- # assigned. If so, warn the user about them, and the
87
- # fact that they will have no effect.
88
- def warn_about_deprecated_config_options
89
- if defined?(::MetricFu::CHURN_OPTIONS)
90
- raise("Use config.churn instead of MetricFu::CHURN_OPTIONS")
91
- end
92
- if defined?(::MetricFu::DIRECTORIES_TO_FLOG)
93
- raise("Use config.flog[:dirs_to_flog] "+
94
- "instead of MetricFu::DIRECTORIES_TO_FLOG")
95
- end
96
- if defined?(::MetricFu::SAIKURO_OPTIONS)
97
- raise("Use config.saikuro instead of MetricFu::SAIKURO_OPTIONS")
98
- end
99
- if defined?(SAIKURO_OPTIONS)
100
- raise("Use config.saikuro instead of SAIKURO_OPTIONS")
101
- end
102
- end
103
-
104
85
  # This allows us to have a nice syntax like:
105
86
  #
106
87
  # MetricFu.run do |config|
@@ -128,7 +109,8 @@ module MetricFu
128
109
  set_metrics
129
110
  set_graphs
130
111
  set_code_dirs
131
- @flay = { :dirs_to_flay => @code_dirs }
112
+ @flay = { :dirs_to_flay => @code_dirs,
113
+ :minimum_score => 100 }
132
114
  @flog = { :dirs_to_flog => @code_dirs }
133
115
  @reek = { :dirs_to_reek => @code_dirs }
134
116
  @roodi = { :dirs_to_roodi => @code_dirs }
@@ -141,7 +123,8 @@ module MetricFu
141
123
  :formater => "text"}
142
124
  @churn = {}
143
125
  @stats = {}
144
- @rcov = { :test_files => ['test/**/*_test.rb',
126
+ @rcov = { :environment => 'test',
127
+ :test_files => ['test/**/*_test.rb',
145
128
  'spec/**/*_spec.rb'],
146
129
  :rcov_opts => ["--sort coverage",
147
130
  "--no-html",
@@ -150,19 +133,10 @@ module MetricFu
150
133
  "--profile",
151
134
  "--rails",
152
135
  "--exclude /gems/,/Library/,/usr/,spec"]}
136
+
137
+ @file_globs_to_ignore = []
153
138
 
154
- @graph_theme = { :colors => %w(orange purple green white red blue pink yellow),
155
- :marker_color => 'blue',
156
- :background_colors => %w(white white)}
157
-
158
- relative_font_path = [File.dirname(__FILE__), '..', '..', 'vendor', '_fonts', 'monaco.ttf']
159
- @graph_font = File.expand_path(File.join(relative_font_path))
160
- @graph_size = "1000x400"
161
- @graph_title_font_size = 12
162
- @graph_legend_box_size = 12
163
- @graph_legend_font_size = 10
164
- @graph_marker_font_size = 10
165
-
139
+ @graph_engine = :bluff # can be :bluff or :gchart
166
140
  end
167
141
 
168
142
  # Perform a simple check to try and guess if we're running
@@ -197,7 +171,7 @@ module MetricFu
197
171
  end
198
172
 
199
173
  def platform #:nodoc:
200
- return PLATFORM
174
+ return RUBY_PLATFORM
201
175
  end
202
176
 
203
177
  def is_cruise_control_rb?
@@ -97,6 +97,13 @@ module MetricFu
97
97
  self.class.metric_directory
98
98
  end
99
99
 
100
+ def remove_excluded_files(paths, globs_to_remove = MetricFu.file_globs_to_ignore)
101
+ files_to_remove = []
102
+ globs_to_remove.each do |glob|
103
+ files_to_remove.concat(Dir[glob])
104
+ end
105
+ paths - files_to_remove
106
+ end
100
107
 
101
108
  # Defines some hook methods for the concrete classes to hook into.
102
109
  %w[emit analyze].each do |meth|
@@ -125,7 +132,8 @@ module MetricFu
125
132
  end
126
133
 
127
134
  def round_to_tenths(decimal)
128
- (decimal * 10).round / 10.0
135
+ decimal=0.0 if decimal.to_s.eql?('NaN')
136
+ (decimal.to_i * 10).round / 10.0
129
137
  end
130
138
 
131
139
  # Allows subclasses to check for required gems
@@ -12,21 +12,23 @@ module MetricFu
12
12
  self.clazz = []
13
13
  end
14
14
 
15
- def add(graph_type)
16
- grapher_name = graph_type.to_s.capitalize + "Grapher"
15
+ def add(graph_type, graph_engine)
16
+ grapher_name = graph_type.to_s.capitalize + graph_engine.to_s.capitalize + "Grapher"
17
17
  self.clazz.push MetricFu.const_get(grapher_name).new
18
18
  end
19
19
 
20
20
 
21
21
  def generate
22
+ return if self.clazz.empty?
22
23
  puts "Generating graphs"
23
24
  Dir[File.join(MetricFu.data_directory, '*.yml')].sort.each do |metric_file|
24
25
  puts "Generating graphs for #{metric_file}"
25
26
  date = metric_file.split('/')[3].split('.')[0]
27
+ y, m, d = date[0..3].to_i, date[4..5].to_i, date[6..7].to_i
26
28
  metrics = YAML::load(File.open(metric_file))
27
29
 
28
30
  self.clazz.each do |grapher|
29
- grapher.get_metrics(metrics, date)
31
+ grapher.get_metrics(metrics, "#{m}/#{d}")
30
32
  end
31
33
  end
32
34
  self.clazz.each do |grapher|
@@ -35,9 +35,9 @@ module MetricFu
35
35
 
36
36
  # Instantiates a new template class based on the configuration set
37
37
  # in MetricFu::Configuration, or through the MetricFu.config block
38
- # in your rake file (defaults to the included StandardTemplate) and
39
- # assigns the report_hash to the report_hash to the template and
40
- # asks itself to write itself out.
38
+ # in your rake file (defaults to the included AwesomeTemplate),
39
+ # assigns the report_hash to the report_hash in the template, and
40
+ # tells the template to to write itself out.
41
41
  def save_templatized_report
42
42
  @template = MetricFu.template_class.new
43
43
  @template.report = report_hash
@@ -1,91 +1,34 @@
1
- require 'chronic'
2
- require 'generator'
3
1
  module MetricFu
4
-
2
+
5
3
  class Churn < Generator
6
4
 
7
-
8
5
  def initialize(options={})
9
6
  super
10
- if self.class.git?
11
- @source_control = Git.new(MetricFu.churn[:start_date])
12
- elsif File.exist?(".svn")
13
- @source_control = Svn.new(MetricFu.churn[:start_date])
14
- else
15
- raise "Churning requires a subversion or git repo"
16
- end
17
- @minimum_churn_count = MetricFu.churn[:minimum_churn_count] || 5
18
7
  end
19
8
 
20
- def self.git?
21
- system("git branch")
9
+ def self.verify_dependencies!
10
+ result = `churn --help`
11
+ raise 'sudo gem install churn # if you want the churn tasks' unless result.match(/churn/)
22
12
  end
13
+
23
14
 
24
15
  def emit
25
- @changes = parse_log_for_changes.reject {|file, change_count| change_count < @minimum_churn_count}
16
+ @output = `churn --yaml`
17
+ yaml_start = @output.index("---")
18
+ @output = @output[yaml_start...@output.length] if yaml_start
26
19
  end
27
20
 
28
21
  def analyze
29
- @changes = @changes.to_a.sort {|x,y| y[1] <=> x[1]}
30
- @changes = @changes.map {|change| {:file_path => change[0], :times_changed => change[1] }}
31
- end
32
-
33
- def to_h
34
- {:churn => {:changes => @changes}}
35
- end
36
-
37
- private
38
-
39
- def parse_log_for_changes
40
- changes = {}
41
-
42
- logs = @source_control.get_logs
43
- logs.each do |line|
44
- changes[line] ? changes[line] += 1 : changes[line] = 1
45
- end
46
- changes
47
- end
48
-
49
-
50
- class SourceControl
51
- def initialize(start_date=nil)
52
- @start_date = start_date
53
- end
54
- end
55
-
56
- class Git < SourceControl
57
- def get_logs
58
- `git log #{date_range} --name-only --pretty=format:`.split(/\n/).reject{|line| line == ""}
59
- end
60
-
61
- private
62
- def date_range
63
- if @start_date
64
- date = Chronic.parse(@start_date)
65
- "--after=#{date.strftime('%Y-%m-%d')}"
66
- end
22
+ if @output.match(/fatal: Not a git repository/)
23
+ @churn = [:churn => {}]
24
+ else
25
+ @churn = YAML::load(@output)
67
26
  end
68
-
69
27
  end
70
28
 
71
- class Svn < SourceControl
72
- def get_logs
73
- `svn log #{date_range} --verbose`.split(/\n/).map { |line| clean_up_svn_line(line) }.compact
74
- end
75
-
76
- private
77
- def date_range
78
- if @start_date
79
- date = Chronic.parse(@start_date)
80
- "--revision {#{date.strftime('%Y-%m-%d')}}:{#{Time.now.strftime('%Y-%m-%d')}}"
81
- end
82
- end
83
-
84
- def clean_up_svn_line(line)
85
- m = line.match(/\W*[A,M]\W+(\/.*)\b/)
86
- m ? m[1] : nil
87
- end
29
+ def to_h
30
+ {:churn => @churn[:churn]}
88
31
  end
89
-
90
32
  end
33
+
91
34
  end
@@ -1,4 +1,3 @@
1
- require 'generator'
2
1
  module MetricFu
3
2
 
4
3
  class Flay < Generator
@@ -10,7 +9,9 @@ module MetricFu
10
9
 
11
10
  def emit
12
11
  files_to_flay = MetricFu.flay[:dirs_to_flay].map{|dir| Dir[File.join(dir, "**/*.rb")] }
13
- @output = `flay #{files_to_flay.join(" ")}`
12
+ files = remove_excluded_files(files_to_flay.flatten)
13
+ mimimum_score_parameter = MetricFu.flay[:minimum_score] ? "--mass #{MetricFu.flay[:minimum_score]} " : ""
14
+ @output = `flay #{mimimum_score_parameter}#{files.join(" ")}`
14
15
  end
15
16
 
16
17
  def analyze
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+
1
3
  module MetricFu
2
4
 
3
5
  class Flog < Generator
@@ -15,11 +17,17 @@ module MetricFu
15
17
  def emit
16
18
  metric_dir = MetricFu::Flog.metric_directory
17
19
  MetricFu.flog[:dirs_to_flog].each do |directory|
18
- Dir.glob("#{directory}/**/*.rb").each do |filename|
20
+ directory = "." if directory=='./'
21
+ files = Dir.glob("#{directory}/**/*.rb")
22
+ files = remove_excluded_files(files)
23
+ files.each do |filename|
19
24
  output_dir = "#{metric_dir}/#{filename.split("/")[0..-2].join("/")}"
20
25
  mkdir_p(output_dir, :verbose => false) unless File.directory?(output_dir)
21
- if MetricFu::MD5Tracker.file_changed?(filename, metric_dir)
22
- `flog -ad #{filename} > #{metric_dir}/#{filename.split('.')[0]}.txt`
26
+ pathname = Pathname.new(filename)
27
+ if MetricFu::MD5Tracker.file_changed?(filename, metric_dir)
28
+ base_name = pathname.basename.to_s.gsub(/\..*$/,'.txt')
29
+ editted_filename = File.join(pathname.dirname.to_s, base_name)
30
+ `flog -ad #{filename} > #{metric_dir}/#{editted_filename}`
23
31
  end
24
32
  end
25
33
  end
@@ -54,7 +62,10 @@ module MetricFu
54
62
  page = parse(open(path, "r") { |f| f.read })
55
63
  if page
56
64
  page.path = path.sub(metric_directory, "").sub(".txt", ".rb")
57
- @pages << page
65
+ #don't include old cached flog results for files that no longer exist.
66
+ if is_file_current?(page.path.to_s)
67
+ @pages << page
68
+ end
58
69
  end
59
70
  end
60
71
  end
@@ -62,14 +73,30 @@ module MetricFu
62
73
  def to_h
63
74
  number_of_methods = @pages.inject(0) {|count, page| count += page.scanned_methods.size}
64
75
  total_flog_score = @pages.inject(0) {|total, page| total += page.score}
65
- sorted_pages = @pages.sort_by {|page| page.score }.reverse
76
+ sorted_pages = @pages.sort_by {|page| page.highest_score }.reverse
66
77
  {:flog => { :total => total_flog_score,
67
78
  :average => average_score(total_flog_score, number_of_methods),
68
79
  :pages => sorted_pages.map {|page| page.to_h}}}
69
80
  end
70
81
 
71
82
  private
72
-
83
+
84
+ def is_file_current?(pathname)
85
+ pathname = pathname.gsub(/^\//,'')
86
+ local_pathname = "./#{pathname}"
87
+ exists = false
88
+
89
+ MetricFu.flog[:dirs_to_flog].each do |directory|
90
+ directory = "." if directory=='./'
91
+ files = Dir.glob("#{directory}/**/*.rb")
92
+ if files.include?(pathname) || files.include?(local_pathname)
93
+ exists = true
94
+ break
95
+ end
96
+ end
97
+ exists
98
+ end
99
+
73
100
  def average_score(total_flog_score, number_of_methods)
74
101
  return 0 if total_flog_score == 0
75
102
  round_to_tenths(total_flog_score/number_of_methods)
@@ -5,17 +5,6 @@ module MetricFu
5
5
  class Rcov < Generator
6
6
  NEW_FILE_MARKER = ("=" * 80) + "\n"
7
7
 
8
- def self.verify_dependencies!
9
- `flay --help`
10
- unless $?.success?
11
- if RUBY_PLATFORM =~ /java/
12
- raise 'running in jruby - rcov tasks not available'
13
- else
14
- raise 'sudo gem install rcov # if you want the rcov tasks'
15
- end
16
- end
17
- end
18
-
19
8
  class Line
20
9
  attr_accessor :content, :was_run
21
10
 
@@ -30,28 +19,38 @@ module MetricFu
30
19
  end
31
20
 
32
21
  def emit
33
- begin
34
- FileUtils.rm_rf(MetricFu::Rcov.metric_directory, :verbose => false)
35
- Dir.mkdir(MetricFu::Rcov.metric_directory)
36
- test_files = FileList[*MetricFu.rcov[:test_files]].join(' ')
37
- rcov_opts = MetricFu.rcov[:rcov_opts].join(' ')
38
- output = ">> #{MetricFu::Rcov.metric_directory}/rcov.txt"
39
- `rcov --include-file #{test_files} #{rcov_opts} #{output}`
40
- rescue LoadError
41
- if RUBY_PLATFORM =~ /java/
42
- puts 'running in jruby - rcov tasks not available'
43
- else
44
- puts 'sudo gem install rcov # if you want the rcov tasks'
45
- end
46
- end
22
+ FileUtils.rm_rf(MetricFu::Rcov.metric_directory, :verbose => false)
23
+ Dir.mkdir(MetricFu::Rcov.metric_directory)
24
+ test_files = FileList[*MetricFu.rcov[:test_files]].join(' ')
25
+ rcov_opts = MetricFu.rcov[:rcov_opts].join(' ')
26
+ output = ">> #{MetricFu::Rcov.metric_directory}/rcov.txt"
27
+ puts "** Running the specs/tests in the [#{MetricFu.rcov[:environment]}] environment"
28
+ `RAILS_ENV=#{MetricFu.rcov[:environment]} rcov #{test_files} #{rcov_opts} #{output}`
47
29
  end
48
30
 
49
31
 
50
32
  def analyze
51
33
  output = File.open(MetricFu::Rcov.metric_directory + '/rcov.txt').read
52
34
  output = output.split(NEW_FILE_MARKER)
53
- # Throw away the first entry - it's the execution time etc.
54
- output.shift
35
+
36
+ output.shift # Throw away the first entry - it's the execution time etc.
37
+
38
+ files = assemble_files(output)
39
+
40
+ @global_total_lines = 0
41
+ @global_total_lines_run = 0
42
+
43
+ @rcov = add_coverage_percentage(files)
44
+ end
45
+
46
+ def to_h
47
+ global_percent_run = ((@global_total_lines_run.to_f / @global_total_lines.to_f) * 100)
48
+ {:rcov => @rcov.merge({:global_percent_run => round_to_tenths(global_percent_run) })}
49
+ end
50
+
51
+ private
52
+
53
+ def assemble_files(output)
55
54
  files = {}
56
55
  output.each_slice(2) {|out| files[out.first.strip] = out.last}
57
56
  files.each_pair {|fname, content| files[fname] = content.split("\n") }
@@ -63,12 +62,13 @@ module MetricFu
63
62
  line = Line.new(raw_line, true).to_h
64
63
  end
65
64
  end
65
+ content.reject! {|line| line[:content].blank? }
66
66
  files[fname] = {:lines => content}
67
67
  end
68
-
69
- # Calculate the percentage of lines run in each file
70
- @global_total_lines = 0
71
- @global_total_lines_run = 0
68
+ files
69
+ end
70
+
71
+ def add_coverage_percentage(files)
72
72
  files.each_pair do |fname, content|
73
73
  lines = content[:lines]
74
74
  @global_total_lines_run += lines_run = lines.find_all {|line| line[:was_run] == true }.length
@@ -76,12 +76,7 @@ module MetricFu
76
76
  percent_run = ((lines_run.to_f / total_lines.to_f) * 100).round
77
77
  files[fname][:percent_run] = percent_run
78
78
  end
79
- @rcov = files
80
- end
81
-
82
- def to_h
83
- global_percent_run = ((@global_total_lines_run.to_f / @global_total_lines.to_f) * 100)
84
- {:rcov => @rcov.merge({:global_percent_run => round_to_tenths(global_percent_run) })}
85
79
  end
80
+
86
81
  end
87
82
  end