metric_fu 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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