metric_fu 3.0.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -17,4 +17,5 @@ spec/reports
17
17
  test/tmp
18
18
  test/version_tmp
19
19
  tmp
20
-
20
+ *.swp
21
+ tags
data/.metrics CHANGED
@@ -8,6 +8,7 @@ mf_debug "Metrics config loaded"
8
8
  # config.add_metric(:rcov)
9
9
  # config.add_graph(:rcov)
10
10
  # config.configure_metric(:rcov, {:external => coverage_file})
11
+ # config.cane = {:abc_max => 15, :line_length => 80, :no_doc => 'y'}
11
12
  # end
12
13
  # or
13
14
  # MetricFu::Configuration.run do |config|
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.0.0
3
4
  - 1.9.3
4
5
  - 1.9.2
5
- - 1.8.7
6
6
  - jruby-19mode # JRuby in 1.9 mode
7
7
  - rbx-19mode
8
8
  matrix:
data/HISTORY.md CHANGED
@@ -1,7 +1,12 @@
1
1
  === master ===
2
2
 
3
+ == MetricFu 3.0.2 / 2013-03-02
4
+
5
+ * Adding cane metrics (Sathish, pull request #49)
6
+ * Not yet included in hotspots
7
+
3
8
  == MetricFu 3.0.1 / 2013-03-01
4
-
9
+
5
10
  * Fixed typo in Flay generator (Sathish, pull request #47)
6
11
 
7
12
  === MetricFu 3.0.0 / 2013-02-07
data/README.md CHANGED
@@ -16,14 +16,17 @@ See `metric_fu --help` for more options
16
16
 
17
17
  ## Compatibility
18
18
 
19
- It is currently testing on MRI 1.8.7, 1.9.2, and 1.9.3
19
+ * It is currently testing on MRI 1.9.2, 1.9.3 and 2.0.0. Ruby 1.8 is no longer supported due to the cane library.
20
+
21
+ * For 1.8.7 support, see version 3.0.0 for partial support, or 2.1.3.7.18.1 (where [Semantic Versioning](http://semver.org/) goes to die)
20
22
 
21
23
  * The `japgolly-Saikuro` fork and `metric_fu-roodi` fork are a part of an attempt to get metric_fu working in a modern Ruby environment, specifically compatibility with Ruby 1.9 and Bundler.
22
- * rails_best_practices is disabled in ruby 1.8
23
24
  * metric_fu no longer runs rcov itself. You may still use rcov metrics as documented below
24
25
 
25
26
  ## Documentation
26
27
 
28
+ * Cane code quality threshold checking is not included in the hotspots report
29
+
27
30
  ### Configuration
28
31
 
29
32
  see the .metrics file
@@ -49,7 +52,7 @@ To generate the same metrics metric_fu has been generating run from the root of
49
52
 
50
53
  RAILS_ENV=test rcov $(ruby -e "puts Dir['{spec,test}/**/*_{spec,test}.rb'].join(' ')") --sort coverage --no-html --text-coverage --no-color --profile --exclude-only '.*' --include-file "\Aapp,\Alib" -Ispec >> coverage/rcov/rcov.txt
51
54
 
52
- #### Simplecov metrics with Ruby 1.9
55
+ #### Simplecov metrics with Ruby 1.9 and 2.0
53
56
 
54
57
  Add to your Gemfile or otherwise install
55
58
 
data/bin/mf-cane ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby_noexec_wrapper
2
+ require 'rubygems'
3
+
4
+ require 'metric_fu_requires'
5
+
6
+ gem 'parallel', MetricFu::MetricVersion.parallel
7
+ version = MetricFu::MetricVersion.cane
8
+ gem 'cane', version
9
+ load Gem.bin_path('cane', 'cane', version)
@@ -0,0 +1,72 @@
1
+ require 'cane'
2
+
3
+ module MetricFu
4
+ class Cane < Generator
5
+ attr_reader :violations, :total_violations
6
+
7
+ def emit
8
+ command = %Q{mf-cane#{abc_max_param}#{style_measure_param}#{no_doc_param}}
9
+ mf_debug = "** #{command}"
10
+ @output = `#{command}`
11
+ end
12
+
13
+ def analyze
14
+ @violations = violations_by_category
15
+ extract_total_violations
16
+ end
17
+
18
+ def to_h
19
+ {:cane => {:total_violations => @total_violations, :violations => @violations}}
20
+ end
21
+ private
22
+
23
+ def abc_max_param
24
+ MetricFu.cane[:abc_max] ? " --abc-max #{MetricFu.cane[:abc_max]}" : ""
25
+ end
26
+
27
+ def style_measure_param
28
+ MetricFu.cane[:line_length] ? " --style-measure #{MetricFu.cane[:line_length]}" : ""
29
+ end
30
+
31
+ def no_doc_param
32
+ MetricFu.cane[:no_doc] == 'y' ? " --no-doc" : ""
33
+ end
34
+
35
+ def violations_by_category
36
+ violations_output = @output.scan(/(.*?)\n\n(.*?)\n\n/m)
37
+ violations_output.each_with_object({}) do |(category_desc, violation_list), violations|
38
+ category = category_from(category_desc)
39
+ violations[category] = violations_for(category, violation_list)
40
+ end
41
+ end
42
+
43
+ def category_from(description)
44
+ category_descriptions = {
45
+ :abc_complexity => /ABC complexity/,
46
+ :line_style => /style requirements/,
47
+ :comment => /comment/
48
+ }
49
+ category_descriptions.find {|k,v| description =~ v}[0]
50
+ end
51
+
52
+ def violations_for(category, violation_list)
53
+ violation_type_for(category).parse(violation_list)
54
+ end
55
+
56
+ def violation_type_for(category)
57
+ case category
58
+ when :abc_complexity
59
+ CaneViolations::AbcComplexity
60
+ when :line_style
61
+ CaneViolations::LineStyle
62
+ when :comment
63
+ CaneViolations::Comment
64
+ end
65
+ end
66
+
67
+ def extract_total_violations
68
+ total = @output.match(/Total Violations: (\d+)/)[1]
69
+ @total_violations = total.to_i if total
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ module MetricFu
2
+ class CaneGrapher < Grapher
3
+ attr_accessor :cane_violations, :labels
4
+
5
+ def initialize
6
+ super
7
+ @cane_violations = []
8
+ @labels = {}
9
+ end
10
+
11
+ def get_metrics(metrics, date)
12
+ if metrics && metrics[:cane]
13
+ @cane_violations.push(metrics[:cane][:total_violations].to_i)
14
+ @labels.update( { @labels.size => date })
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,12 @@
1
+ MetricFu::Configuration.run do |config|
2
+ config.add_metric(:cane)
3
+ config.add_graph(:cane)
4
+ config.configure_metric(:cane, {
5
+ :dirs_to_cane => MetricFu.code_dirs,
6
+ :abc_max => 15,
7
+ :line_length => 80,
8
+ :no_doc => 'n',
9
+ :filetypes => ['rb']
10
+ })
11
+ end
12
+
@@ -0,0 +1,78 @@
1
+ <html>
2
+ <head>
3
+ <title>Cane Results</title>
4
+ <style>
5
+ <%= inline_css("css/default.css") %>
6
+ </style>
7
+ </head>
8
+
9
+ <body>
10
+ <h1>Cane Results</h1>
11
+ <a href="index.html">back to menu</a>
12
+ <h2>Total Violations: <%= @cane[:total_violations] %></h2>
13
+ <p><a href='https://github.com/square/cane'>Cane</a> reports code quality threshold violations.</p>
14
+
15
+ <% graph_name = 'cane' %>
16
+ <% if MetricFu.configuration.graph_engine == :gchart %>
17
+ <img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
18
+ <% else %>
19
+ <canvas id="graph"></canvas>
20
+ <script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
21
+ <% end %>
22
+
23
+ <% if @cane[:violations][:abc_complexity] && @cane[:violations][:abc_complexity].size > 0 %>
24
+ <h3>Methods exceeding allowed Abc complexity (<%= @cane[:violations][:abc_complexity].size %>)</h3>
25
+ <table>
26
+ <tr>
27
+ <th>File</th>
28
+ <th>Method</th>
29
+ <th>Complexity</th>
30
+ </tr>
31
+ <% count = 0 %>
32
+ <% @cane[:violations][:abc_complexity].each do |violation| %>
33
+ <tr class='<%= cycle("light", "dark", count) %>'>
34
+ <td><%=violation[:file]%></td>
35
+ <td><%=violation[:method]%></td>
36
+ <td><%=violation[:complexity]%></td>
37
+ </tr>
38
+ <% count += 1 %>
39
+ <% end %>
40
+ </table>
41
+ <% end %>
42
+ <% if @cane[:violations][:line_style] && @cane[:violations][:line_style].size > 0 %>
43
+ <h3>Lines violating style requirements (<%= @cane[:violations][:line_style].size %>)</h3>
44
+ <table>
45
+ <tr>
46
+ <th>File</th>
47
+ <th>Description</th>
48
+ </tr>
49
+ <% count = 0 %>
50
+ <% @cane[:violations][:line_style].each do |violation| %>
51
+ <tr class='<%= cycle("light", "dark", count) %>'>
52
+ <td><%=violation[:line]%></td>
53
+ <td><%=violation[:description]%></td>
54
+ </tr>
55
+ <% count += 1 %>
56
+ <% end %>
57
+ </table>
58
+ <% end %>
59
+ <% if @cane[:violations][:comment] && @cane[:violations][:comment].size > 0 %>
60
+ <h3>Class definitions requiring comments (<%= @cane[:violations][:comment].size %>)</h3>
61
+ <table>
62
+ <tr>
63
+ <th>File</th>
64
+ <th>Class</th>
65
+ </tr>
66
+ <% count = 0 %>
67
+ <% @cane[:violations][:comment].each do |violation| %>
68
+ <tr class='<%= cycle("light", "dark", count) %>'>
69
+ <td><%=violation[:line]%></td>
70
+ <td><%=violation[:class_name]%></td>
71
+ </tr>
72
+ <% count += 1 %>
73
+ <% end %>
74
+ </table>
75
+ <% end %>
76
+ <p>Generated on <%= Time.now.localtime %></p>
77
+ </body>
78
+ </html>
@@ -0,0 +1,69 @@
1
+ <html>
2
+ <head>
3
+ <title>Cane Results</title>
4
+ <style>
5
+ <%= inline_css("default.css") %>
6
+ </style>
7
+ </head>
8
+
9
+ <body>
10
+ <h1>Cane Results</h1>
11
+ <a href="index.html">back to menu</a>
12
+ <h2>Total Violations: <%= @cane[:total_violations] %></h2>
13
+ <p><a href='https://github.com/square/cane'>Cane</a> reports code quality threshold violations.</p>
14
+ <% if @cane[:violations][:abc_complexity] && @cane[:violations][:abc_complexity].size > 0 %>
15
+ <h3>Methods exceeding allowed Abc complexity (<%= @cane[:violations][:abc_complexity].size %>)</h3>
16
+ <table>
17
+ <tr>
18
+ <th>File</th>
19
+ <th>Method</th>
20
+ <th>Complexity</th>
21
+ </tr>
22
+ <% count = 0 %>
23
+ <% @cane[:violations][:abc_complexity].each do |violation| %>
24
+ <tr class='<%= cycle("light", "dark", count) %>'>
25
+ <td><%=violation[:file]%></td>
26
+ <td><%=violation[:method]%></td>
27
+ <td><%=violation[:complexity]%></td>
28
+ </tr>
29
+ <% count += 1 %>
30
+ <% end %>
31
+ </table>
32
+ <% end %>
33
+ <% if @cane[:violations][:line_style] && @cane[:violations][:line_style].size > 0 %>
34
+ <h3>Lines violating style requirements (<%= @cane[:violations][:line_style].size %>)</h3>
35
+ <table>
36
+ <tr>
37
+ <th>File</th>
38
+ <th>Description</th>
39
+ </tr>
40
+ <% count = 0 %>
41
+ <% @cane[:violations][:line_style].each do |violation| %>
42
+ <tr class='<%= cycle("light", "dark", count) %>'>
43
+ <td><%=violation[:line]%></td>
44
+ <td><%=violation[:description]%></td>
45
+ </tr>
46
+ <% count += 1 %>
47
+ <% end %>
48
+ </table>
49
+ <% end %>
50
+ <% if @cane[:violations][:comment] && @cane[:violations][:comment].size > 0 %>
51
+ <h3>Class definitions requiring comments (<%= @cane[:violations][:comment].size %>)</h3>
52
+ <table>
53
+ <tr>
54
+ <th>File</th>
55
+ <th>Description</th>
56
+ </tr>
57
+ <% count = 0 %>
58
+ <% @cane[:violations][:comment].each do |violation| %>
59
+ <tr class='<%= cycle("light", "dark", count) %>'>
60
+ <td><%=violation[:line]%></td>
61
+ <td><%=violation[:class_name]%></td>
62
+ </tr>
63
+ <% count += 1 %>
64
+ <% end %>
65
+ </table>
66
+ <% end %>
67
+ <p>Generated on <%= Time.now.localtime %></p>
68
+ </body>
69
+ </html>
@@ -0,0 +1,30 @@
1
+ module MetricFu
2
+ module CaneViolations
3
+ class AbcComplexity
4
+ def self.parse(violation_list)
5
+ violation_list.split(/\n/).map do |violation|
6
+ file, method, complexity = violation.split
7
+ {:file => file, :method => method, :complexity => complexity}
8
+ end
9
+ end
10
+ end
11
+
12
+ class LineStyle
13
+ def self.parse(violation_list)
14
+ violation_list.split(/\n/).map do |violation|
15
+ line, description = violation.split(/\s{2,}/).reject{|x|x.strip==''}
16
+ {:line => line, :description => description}
17
+ end
18
+ end
19
+ end
20
+
21
+ class Comment
22
+ def self.parse(violation_list)
23
+ violation_list.split(/\n/).map do |violation|
24
+ line, class_name = violation.split
25
+ {:line => line, :class_name => class_name}
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,7 +1,5 @@
1
1
  MetricFu::Configuration.run do |config|
2
- if RUBY_VERSION < '1.9'
3
- config.mf_debug "rails_best_practices is not compatible with #{RUBY_VERSION}"
4
- elsif config.rails?
2
+ if config.rails?
5
3
  config.add_metric(:rails_best_practices)
6
4
  config.add_graph(:rails_best_practices)
7
5
  config.configure_metric(:rails_best_practices, {})
@@ -110,4 +110,18 @@ module MetricFu
110
110
  File.open(File.join(MetricFu.output_directory, 'rails_best_practices.js'), 'w') {|f| f << content }
111
111
  end
112
112
  end
113
+
114
+ class CaneBluffGrapher < CaneGrapher
115
+ def graph!
116
+ content = <<-EOS
117
+ #{BLUFF_DEFAULT_OPTIONS}
118
+ g.title = 'Cane: code quality threshold violations';
119
+ g.data('cane', [#{@cane_violations.join(',')}]);
120
+ g.labels = #{@labels.to_json};
121
+ g.draw();
122
+ EOS
123
+ File.open(File.join(MetricFu.output_directory, 'cane.js'), 'w') {|f| f << content }
124
+ end
125
+ end
126
+
113
127
  end
@@ -21,6 +21,9 @@
21
21
  <% if @saikuro %>
22
22
  <li class='even failure'><a href="saikuro.html">Saikuro</a></li>
23
23
  <% end %>
24
+ <% if @cane %>
25
+ <li class='even failure'><a href="cane.html">Cane</a></li>
26
+ <% end %>
24
27
  <% if @stats %>
25
28
  <li class='even failure'><a href="stats.html">Stats</a></li>
26
29
  <% end %>
@@ -29,6 +29,9 @@
29
29
  <% if @saikuro %>
30
30
  <p><a href="saikuro.html">Saikuro report</a></p>
31
31
  <% end %>
32
+ <% if @cane %>
33
+ <p><a href="cane.html">Cane report</a></p>
34
+ <% end %>
32
35
  <% if @stats %>
33
36
  <p><a href="stats.html">Stats report</a></p>
34
37
  <% end %>
@@ -1,3 +1,3 @@
1
1
  module MetricFu
2
- VERSION = "3.0.1"
2
+ VERSION = "4.0.0"
3
3
  end
@@ -29,6 +29,9 @@ module MetricFu
29
29
  def sexp_processor
30
30
  '~> 4.0'
31
31
  end
32
+ def parallel
33
+ '0.6.2'
34
+ end
32
35
 
33
36
  def rcov
34
37
  '~> 0.8'
@@ -36,5 +39,8 @@ module MetricFu
36
39
  def saikuro
37
40
  '>= 1.1.1.0'
38
41
  end
42
+ def cane
43
+ '2.5.2'
44
+ end
39
45
  end
40
46
  end
data/metric_fu.gemspec CHANGED
@@ -29,10 +29,12 @@ Gem::Specification.new do |s|
29
29
  "flog" => ["= #{MetricFu::MetricVersion.flog}"],
30
30
  "reek" => ["= #{MetricFu::MetricVersion.reek}"],
31
31
  "churn" => ["= #{MetricFu::MetricVersion.churn}"],
32
- # specifying dependencies for flay, reek, churn, and flog
32
+ "cane" => ["= #{MetricFu::MetricVersion.cane}"],
33
+ # specifying dependencies for flay, reek, churn, flog, and cane
33
34
  "ruby_parser" => ["~> 3.0", ">= #{MetricFu::MetricVersion.ruby_parser}"],
34
35
  "sexp_processor" => ["#{MetricFu::MetricVersion.sexp_processor}"],
35
36
  "ruby2ruby" => ["= #{MetricFu::MetricVersion.ruby2ruby}"],
37
+ "parallel" => ["= #{MetricFu::MetricVersion.parallel}"],
36
38
  "activesupport" => [">= 2.0.0"], # ok
37
39
  "coderay" => [],
38
40
  "fattr" => ["= 2.2.1"],
@@ -39,6 +39,10 @@ describe MetricFu::Cli::Helper do
39
39
  defaults[:saikuro].should be_true
40
40
  end
41
41
 
42
+ it "enables Cane" do
43
+ defaults[:cane].should be_true
44
+ end
45
+
42
46
  it "enables RCov" do
43
47
  defaults[:rcov].should be_true
44
48
  end
@@ -142,6 +146,13 @@ describe MetricFu::Cli::Helper do
142
146
  helper.process_options(["--roodi"])[:roodi].should be_true
143
147
  end
144
148
 
149
+ it "turns cane off" do
150
+ helper.process_options(["--no-cane"])[:cane].should be_false
151
+ end
152
+
153
+ it "turns cane on" do
154
+ helper.process_options(["--cane"])[:cane].should be_true
155
+ end
145
156
  end
146
157
 
147
158
  end
@@ -126,6 +126,17 @@ describe MetricFu::Configuration do
126
126
  should == { :start_date => %q("1 year ago"), :minimum_churn_count => 10}
127
127
  end
128
128
 
129
+ it 'should set @cane to ' +
130
+ %q(:dirs_to_cane => @code_dirs, :abc_max => 15, :line_length => 80, :no_doc => 'n') do
131
+ load_metric 'cane'
132
+ @config.send(:cane).
133
+ should == {
134
+ :dirs_to_cane => MetricFu.code_dirs,
135
+ :filetypes => ["rb"],
136
+ :abc_max => 15,
137
+ :line_length => 80,
138
+ :no_doc => "n"}
139
+ end
129
140
 
130
141
  it 'should set @rcov to ' +
131
142
  %q(:test_files => Dir['{spec,test}/**/*_{spec,test}.rb'],
@@ -194,14 +205,8 @@ describe MetricFu::Configuration do
194
205
  end
195
206
 
196
207
  describe '#set_graphs ' do
197
- if RUBY_VERSION < '1.9'
198
- it 'should not set the graphs to include rails_best_practices for ruby 1.8' do
199
- @config.graphs.should_not include(:rails_best_practices)
200
- end
201
- else
202
- it 'should set the graphs to include rails_best_practices' do
203
- @config.graphs.should include(:rails_best_practices)
204
- end
208
+ it 'should set the graphs to include rails_best_practices' do
209
+ @config.graphs.should include(:rails_best_practices)
205
210
  end
206
211
  end
207
212
 
@@ -217,12 +222,10 @@ describe MetricFu::Configuration do
217
222
  should == {}
218
223
  end
219
224
 
220
- unless RUBY_VERSION < '1.9'
221
- it 'should set @rails_best_practices to {}' do
222
- load_metric 'rails_best_practices'
223
- @config.send(:rails_best_practices).
224
- should == {}
225
- end
225
+ it 'should set @rails_best_practices to {}' do
226
+ load_metric 'rails_best_practices'
227
+ @config.send(:rails_best_practices).
228
+ should == {}
226
229
  end
227
230
  end
228
231
 
@@ -236,7 +239,7 @@ describe MetricFu::Configuration do
236
239
  end
237
240
 
238
241
  it 'should set the available metrics' do
239
- @config.metrics.should =~ [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro]
242
+ @config.metrics.should =~ [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro, :cane]
240
243
  end
241
244
 
242
245
  it 'should set the @code_dirs instance var to ["lib"]' do
@@ -268,13 +271,13 @@ describe MetricFu::Configuration do
268
271
 
269
272
  before(:each) { get_new_config }
270
273
 
271
- [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro].each do |metric|
274
+ [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro, :cane].each do |metric|
272
275
  it "should add a #{metric} class method to the MetricFu module " do
273
276
  MetricFu.should respond_to(metric)
274
277
  end
275
278
  end
276
279
 
277
- [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro].each do |graph|
280
+ [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro, :cane].each do |graph|
278
281
  it "should add a #{graph} class metrhod to the MetricFu module" do
279
282
  MetricFu.should respond_to(graph)
280
283
  end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cane do
4
+ describe "emit method" do
5
+ def configure_cane_with(options={})
6
+ MetricFu::Configuration.run {|config|
7
+ config.add_metric(:cane)
8
+ config.configure_metric(:cane, options)
9
+ }
10
+ end
11
+
12
+ it "should execute cane command" do
13
+ configure_cane_with({})
14
+ @cane = MetricFu::Cane.new('base_dir')
15
+ @cane.should_receive(:`).with("mf-cane")
16
+ output = @cane.emit
17
+ end
18
+
19
+ it "should use abc max option" do
20
+ configure_cane_with({abc_max: 20})
21
+ @cane = MetricFu::Cane.new('base_dir')
22
+ @cane.should_receive(:`).with("mf-cane --abc-max 20")
23
+ output = @cane.emit
24
+ end
25
+
26
+ it "should use style max line length option" do
27
+ configure_cane_with({line_length: 100})
28
+ @cane = MetricFu::Cane.new('base_dir')
29
+ @cane.should_receive(:`).with("mf-cane --style-measure 100")
30
+ output = @cane.emit
31
+ end
32
+
33
+ it "should use no-doc if specified" do
34
+ configure_cane_with({no_doc: 'y'})
35
+ @cane = MetricFu::Cane.new('base_dir')
36
+ @cane.should_receive(:`).with("mf-cane --no-doc")
37
+ output = @cane.emit
38
+ end
39
+
40
+ it "should include doc violations if no_doc != 'y'" do
41
+ configure_cane_with({no_doc: 'n'})
42
+ @cane = MetricFu::Cane.new('base_dir')
43
+ @cane.should_receive(:`).with("mf-cane")
44
+ output = @cane.emit
45
+ end
46
+ end
47
+
48
+ describe "parse cane output" do
49
+ before :each do
50
+ lines = sample_cane_output
51
+ MetricFu::Configuration.run {}
52
+ File.stub!(:directory?).and_return(true)
53
+ @cane = MetricFu::Cane.new('base_dir')
54
+ @cane.instance_variable_set(:@output, lines)
55
+ end
56
+
57
+ describe "analyze method" do
58
+
59
+ it "should find total violations" do
60
+ @cane.analyze
61
+ @cane.total_violations.should == 6
62
+ end
63
+
64
+ it "should extract abc complexity violations" do
65
+ @cane.analyze
66
+ @cane.violations[:abc_complexity].should == [
67
+ {file: 'lib/abc/foo.rb', method: 'Abc::Foo#method', complexity: '11'},
68
+ {file: 'lib/abc/bar.rb', method: 'Abc::Bar#method', complexity: '22'}
69
+ ]
70
+ end
71
+
72
+ it "should extract line style violations" do
73
+ @cane.analyze
74
+ @cane.violations[:line_style].should == [
75
+ {line: 'lib/line/foo.rb:1', description: 'Line is >80 characters (135)'},
76
+ {line: 'lib/line/bar.rb:2', description: 'Line contains trailing whitespace'}
77
+ ]
78
+ end
79
+
80
+ it "should extract comment violations" do
81
+ @cane.analyze
82
+ @cane.violations[:comment].should == [
83
+ {line: 'lib/comments/foo.rb:1', class_name: 'Foo'},
84
+ {line: 'lib/comments/bar.rb:2', class_name: 'Bar'}
85
+ ]
86
+ end
87
+ end
88
+
89
+ describe "to_h method" do
90
+ it "should have total violations" do
91
+ @cane.analyze
92
+ @cane.to_h[:cane][:total_violations].should == 6
93
+ end
94
+
95
+ it "should have violations by category" do
96
+ @cane.analyze
97
+ @cane.to_h[:cane][:violations][:abc_complexity].should == [
98
+ {file: 'lib/abc/foo.rb', method: 'Abc::Foo#method', complexity: '11'},
99
+ {file: 'lib/abc/bar.rb', method: 'Abc::Bar#method', complexity: '22'}
100
+ ]
101
+ @cane.to_h[:cane][:violations][:line_style].should == [
102
+ {line: 'lib/line/foo.rb:1', description: 'Line is >80 characters (135)'},
103
+ {line: 'lib/line/bar.rb:2', description: 'Line contains trailing whitespace'}
104
+ ]
105
+ @cane.to_h[:cane][:violations][:comment].should == [
106
+ {line: 'lib/comments/foo.rb:1', class_name: 'Foo'},
107
+ {line: 'lib/comments/bar.rb:2', class_name: 'Bar'}
108
+ ]
109
+ end
110
+ end
111
+ end
112
+
113
+ def sample_cane_output
114
+ <<-OUTPUT
115
+ Methods exceeded maximum allowed ABC complexity (33):
116
+
117
+ lib/abc/foo.rb Abc::Foo#method 11
118
+ lib/abc/bar.rb Abc::Bar#method 22
119
+
120
+ Lines violated style requirements (340):
121
+
122
+ lib/line/foo.rb:1 Line is >80 characters (135)
123
+ lib/line/bar.rb:2 Line contains trailing whitespace
124
+
125
+ Class definitions require explanatory comments on preceding line (2):
126
+
127
+ lib/comments/foo.rb:1 Foo
128
+ lib/comments/bar.rb:2 Bar
129
+
130
+ Total Violations: 6
131
+ OUTPUT
132
+ end
133
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metric_fu
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 4.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -19,7 +19,7 @@ authors:
19
19
  autorequire:
20
20
  bindir: bin
21
21
  cert_chain: []
22
- date: 2013-03-01 00:00:00.000000000 Z
22
+ date: 2013-03-05 00:00:00.000000000 Z
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
25
25
  name: rails_best_practices
@@ -133,6 +133,22 @@ dependencies:
133
133
  - - '='
134
134
  - !ruby/object:Gem::Version
135
135
  version: 0.0.28
136
+ - !ruby/object:Gem::Dependency
137
+ name: cane
138
+ requirement: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - '='
142
+ - !ruby/object:Gem::Version
143
+ version: 2.5.2
144
+ type: :runtime
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - '='
150
+ - !ruby/object:Gem::Version
151
+ version: 2.5.2
136
152
  - !ruby/object:Gem::Dependency
137
153
  name: ruby_parser
138
154
  requirement: !ruby/object:Gem::Requirement
@@ -187,6 +203,22 @@ dependencies:
187
203
  - - '='
188
204
  - !ruby/object:Gem::Version
189
205
  version: 2.0.2
206
+ - !ruby/object:Gem::Dependency
207
+ name: parallel
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - '='
212
+ - !ruby/object:Gem::Version
213
+ version: 0.6.2
214
+ type: :runtime
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - '='
220
+ - !ruby/object:Gem::Version
221
+ version: 0.6.2
190
222
  - !ruby/object:Gem::Dependency
191
223
  name: activesupport
192
224
  requirement: !ruby/object:Gem::Requirement
@@ -304,6 +336,7 @@ description: Code metrics from Flog, Flay, Saikuro, Churn, Reek, Roodi, Rails' s
304
336
  email: github@benjaminfleischer.com
305
337
  executables:
306
338
  - metric_fu
339
+ - mf-cane
307
340
  - mf-churn
308
341
  - mf-flay
309
342
  - mf-rails_best_practices
@@ -326,6 +359,7 @@ files:
326
359
  - Rakefile
327
360
  - TODO.md
328
361
  - bin/metric_fu
362
+ - bin/mf-cane
329
363
  - bin/mf-churn
330
364
  - bin/mf-flay
331
365
  - bin/mf-rails_best_practices
@@ -368,6 +402,12 @@ files:
368
402
  - lib/metric_fu/load_files.rb
369
403
  - lib/metric_fu/logging/mf_debugger.rb
370
404
  - lib/metric_fu/metrics/base_template.rb
405
+ - lib/metric_fu/metrics/cane/cane.rb
406
+ - lib/metric_fu/metrics/cane/cane_grapher.rb
407
+ - lib/metric_fu/metrics/cane/init.rb
408
+ - lib/metric_fu/metrics/cane/template_awesome/cane.html.erb
409
+ - lib/metric_fu/metrics/cane/template_standard/cane.html.erb
410
+ - lib/metric_fu/metrics/cane/violations.rb
371
411
  - lib/metric_fu/metrics/churn/churn.rb
372
412
  - lib/metric_fu/metrics/churn/churn_hotspot.rb
373
413
  - lib/metric_fu/metrics/churn/init.rb
@@ -461,6 +501,7 @@ files:
461
501
  - spec/metric_fu/data_structures/line_numbers_spec.rb
462
502
  - spec/metric_fu/data_structures/location_spec.rb
463
503
  - spec/metric_fu/metrics/base_template_spec.rb
504
+ - spec/metric_fu/metrics/cane/cane_spec.rb
464
505
  - spec/metric_fu/metrics/churn/churn_spec.rb
465
506
  - spec/metric_fu/metrics/flay/flay_grapher_spec.rb
466
507
  - spec/metric_fu/metrics/flay/flay_spec.rb
@@ -521,7 +562,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
521
562
  version: 1.3.6
522
563
  requirements: []
523
564
  rubyforge_project: metric_fu
524
- rubygems_version: 1.8.25
565
+ rubygems_version: 1.8.24
525
566
  signing_key:
526
567
  specification_version: 3
527
568
  summary: A fistful of code metrics, with awesome templates and graphs
@@ -531,6 +572,7 @@ test_files:
531
572
  - spec/metric_fu/data_structures/line_numbers_spec.rb
532
573
  - spec/metric_fu/data_structures/location_spec.rb
533
574
  - spec/metric_fu/metrics/base_template_spec.rb
575
+ - spec/metric_fu/metrics/cane/cane_spec.rb
534
576
  - spec/metric_fu/metrics/churn/churn_spec.rb
535
577
  - spec/metric_fu/metrics/flay/flay_grapher_spec.rb
536
578
  - spec/metric_fu/metrics/flay/flay_spec.rb