metric_fu 2.1.1 → 2.1.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/.gitignore +20 -0
  2. data/.travis.yml +5 -0
  3. data/Gemfile +5 -0
  4. data/HISTORY +21 -1
  5. data/Manifest.txt +25 -0
  6. data/README.md +61 -0
  7. data/Rakefile +15 -9
  8. data/TODO +2 -0
  9. data/bin/metric_fu +4 -0
  10. data/config/roodi_config.yml +22 -0
  11. data/home_page/back_all.jpg +0 -0
  12. data/home_page/churn.gif +0 -0
  13. data/home_page/flay.gif +0 -0
  14. data/home_page/flog.gif +0 -0
  15. data/home_page/footer.gif +0 -0
  16. data/home_page/header.jpg +0 -0
  17. data/home_page/hotspot.gif +0 -0
  18. data/home_page/img09.gif +0 -0
  19. data/home_page/index.html +305 -0
  20. data/home_page/rcov.gif +0 -0
  21. data/home_page/reek.gif +0 -0
  22. data/home_page/roodi.gif +0 -0
  23. data/home_page/saikuro.gif +0 -0
  24. data/home_page/stats.gif +0 -0
  25. data/home_page/styles.css +245 -0
  26. data/home_page/title.gif +0 -0
  27. data/home_page/title_back.gif +0 -0
  28. data/lib/{base/configuration.rb → configuration.rb} +45 -17
  29. data/lib/data_structures/careful_array.rb +9 -0
  30. data/lib/{base → data_structures}/code_issue.rb +17 -16
  31. data/lib/data_structures/grouping.rb +40 -0
  32. data/lib/{base → data_structures}/line_numbers.rb +23 -14
  33. data/lib/{base → data_structures}/location.rb +3 -1
  34. data/lib/{base → data_structures}/ranking.rb +0 -0
  35. data/lib/data_structures/record.rb +43 -0
  36. data/lib/{base → data_structures}/table.rb +6 -2
  37. data/lib/errors/analysis_error.rb +1 -0
  38. data/lib/initial_requires.rb +25 -0
  39. data/lib/load_files.rb +39 -0
  40. data/lib/logging/mf_debugger.rb +24 -0
  41. data/lib/{base/md5_tracker.rb → md5_tracker.rb} +0 -0
  42. data/lib/metric_fu.rb +55 -37
  43. data/lib/{base → metrics}/base_template.rb +47 -16
  44. data/lib/{generators → metrics/churn}/churn.rb +0 -0
  45. data/lib/{base → metrics/churn}/churn_analyzer.rb +0 -0
  46. data/lib/{templates/awesome → metrics/churn/template_awesome}/churn.html.erb +0 -0
  47. data/lib/{templates/standard → metrics/churn/template_standard}/churn.html.erb +0 -0
  48. data/lib/{generators → metrics/flay}/flay.rb +0 -0
  49. data/lib/{base → metrics/flay}/flay_analyzer.rb +0 -0
  50. data/lib/{graphs → metrics/flay}/flay_grapher.rb +0 -0
  51. data/lib/{templates/awesome → metrics/flay/template_awesome}/flay.html.erb +0 -0
  52. data/lib/{templates/standard → metrics/flay/template_standard}/flay.html.erb +0 -0
  53. data/lib/{generators → metrics/flog}/flog.rb +2 -0
  54. data/lib/{base → metrics/flog}/flog_analyzer.rb +0 -0
  55. data/lib/{graphs → metrics/flog}/flog_grapher.rb +0 -0
  56. data/lib/{templates/awesome → metrics/flog/template_awesome}/flog.html.erb +0 -0
  57. data/lib/{templates/standard → metrics/flog/template_standard}/flog.html.erb +0 -0
  58. data/lib/{base → metrics}/generator.rb +0 -0
  59. data/lib/{base → metrics}/graph.rb +0 -0
  60. data/lib/{generators → metrics/hotspots}/hotspots.rb +0 -0
  61. data/lib/{templates/awesome → metrics/hotspots/template_awesome}/hotspots.html.erb +0 -0
  62. data/lib/{templates/standard → metrics/hotspots/template_standard}/hotspots.html.erb +0 -0
  63. data/lib/{base → metrics}/metric_analyzer.rb +4 -80
  64. data/lib/{generators → metrics/rails_best_practices}/rails_best_practices.rb +0 -0
  65. data/lib/{graphs → metrics/rails_best_practices}/rails_best_practices_grapher.rb +0 -0
  66. data/lib/{templates/awesome → metrics/rails_best_practices/template_awesome}/rails_best_practices.html.erb +1 -1
  67. data/lib/{templates/standard → metrics/rails_best_practices/template_standard}/rails_best_practices.html.erb +1 -1
  68. data/lib/{generators → metrics/rcov}/rcov.rb +5 -3
  69. data/lib/{base → metrics/rcov}/rcov_analyzer.rb +1 -1
  70. data/lib/{graphs → metrics/rcov}/rcov_grapher.rb +0 -0
  71. data/lib/{templates/awesome → metrics/rcov/template_awesome}/rcov.html.erb +0 -0
  72. data/lib/{templates/standard → metrics/rcov/template_standard}/rcov.html.erb +0 -0
  73. data/lib/{generators → metrics/reek}/reek.rb +3 -2
  74. data/lib/{base → metrics/reek}/reek_analyzer.rb +1 -0
  75. data/lib/{graphs → metrics/reek}/reek_grapher.rb +0 -0
  76. data/lib/{templates/awesome → metrics/reek/template_awesome}/reek.html.erb +0 -0
  77. data/lib/{templates/standard → metrics/reek/template_standard}/reek.html.erb +0 -0
  78. data/lib/{generators → metrics/roodi}/roodi.rb +0 -0
  79. data/lib/{base → metrics/roodi}/roodi_analyzer.rb +0 -0
  80. data/lib/{graphs → metrics/roodi}/roodi_grapher.rb +0 -0
  81. data/lib/{templates/awesome → metrics/roodi/template_awesome}/roodi.html.erb +0 -0
  82. data/lib/{templates/standard → metrics/roodi/template_standard}/roodi.html.erb +0 -0
  83. data/lib/{generators → metrics/saikuro}/saikuro.rb +4 -2
  84. data/lib/{base → metrics/saikuro}/saikuro_analyzer.rb +0 -0
  85. data/lib/{templates/awesome → metrics/saikuro/template_awesome}/saikuro.html.erb +0 -0
  86. data/lib/{templates/standard → metrics/saikuro/template_standard}/saikuro.html.erb +0 -0
  87. data/lib/{generators → metrics/stats}/stats.rb +0 -0
  88. data/lib/{base → metrics/stats}/stats_analyzer.rb +0 -0
  89. data/lib/{graphs → metrics/stats}/stats_grapher.rb +0 -0
  90. data/lib/{templates/awesome → metrics/stats/template_awesome}/stats.html.erb +0 -0
  91. data/lib/{templates/standard → metrics/stats/template_standard}/stats.html.erb +0 -0
  92. data/lib/{graphs → reporting/graphs}/engines/bluff.rb +0 -0
  93. data/lib/{graphs → reporting/graphs}/engines/gchart.rb +0 -0
  94. data/lib/{graphs → reporting/graphs}/grapher.rb +0 -0
  95. data/lib/{base → reporting}/report.rb +2 -0
  96. data/lib/{templates → reporting/templates}/awesome/awesome_template.rb +28 -7
  97. data/lib/{templates → reporting/templates}/awesome/css/buttons.css +0 -0
  98. data/lib/{templates → reporting/templates}/awesome/css/default.css +0 -0
  99. data/lib/{templates → reporting/templates}/awesome/css/integrity.css +0 -0
  100. data/lib/{templates → reporting/templates}/awesome/css/reset.css +0 -0
  101. data/lib/{templates → reporting/templates}/awesome/css/syntax.css +0 -0
  102. data/lib/{templates → reporting/templates}/awesome/index.html.erb +0 -0
  103. data/lib/{templates → reporting/templates}/awesome/layout.html.erb +0 -0
  104. data/lib/{templates → reporting/templates}/javascripts/bluff-min.js +0 -0
  105. data/lib/{templates → reporting/templates}/javascripts/excanvas.js +0 -0
  106. data/lib/{templates → reporting/templates}/javascripts/js-class.js +0 -0
  107. data/lib/{templates → reporting/templates}/standard/default.css +0 -0
  108. data/lib/{templates → reporting/templates}/standard/index.html.erb +0 -0
  109. data/lib/{templates → reporting/templates}/standard/standard_template.rb +3 -3
  110. data/lib/{base/scoring_strategies.rb → scoring_strategies.rb} +0 -0
  111. data/lib/tasks/metric_fu.rake +36 -0
  112. data/lib/version.rb +3 -0
  113. data/metric_fu.gemspec +65 -0
  114. data/spec/base/base_template_spec.rb +19 -2
  115. data/spec/base/configuration_spec.rb +4 -3
  116. data/spec/base/generator_spec.rb +2 -2
  117. data/spec/base/line_numbers_spec.rb +2 -2
  118. data/spec/base/location_spec.rb +127 -0
  119. data/spec/base/metric_analyzer_spec.rb +452 -0
  120. data/spec/base/ranking_spec.rb +42 -0
  121. data/spec/base/report_spec.rb +1 -1
  122. data/spec/base/table_spec.rb +36 -0
  123. data/spec/generators/hotspots_spec.rb +88 -0
  124. data/spec/generators/rails_best_practices_spec.rb +1 -1
  125. data/spec/generators/rcov_spec.rb +3 -3
  126. data/spec/generators/stats_spec.rb +1 -1
  127. data/spec/spec_helper.rb +4 -1
  128. metadata +466 -309
  129. data/README +0 -29
  130. data/tasks/metric_fu.rake +0 -22
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module MetricFu
2
+ VERSION = "2.1.3.4"
3
+ end
data/metric_fu.gemspec ADDED
@@ -0,0 +1,65 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "metric_fu"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.version = MetricFu::VERSION
8
+ s.summary = "A fistful of code metrics, with awesome templates and graphs"
9
+ s.email = "github@benjaminfleischer.com"
10
+ s.homepage = "http://github.com/bf4/metric_fu"
11
+ s.description = "Code metrics from Flog, Flay, Simplecov-RCov, Saikuro, Churn, Reek, Roodi, Rails' stats task and Rails Best Practices"
12
+ s.authors = ["Jake Scruggs", "Sean Soper", "Andre Arko", "Petrik de Heus", "Grant McInnes", "Nick Quaranto", "Édouard Brière", "Carl Youngblood", "Richard Huang", "Dan Mayer", "Benjamin Fleischer"]
13
+ s.required_ruby_version = ">= 1.8.7"
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.files = `git ls-files`.split($\)
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ s.license = 'MIT'
20
+
21
+ {
22
+ "flay" => ["= 1.2.1"],
23
+ "flog" => ["= 2.3.0"],
24
+ "reek" => ["= 1.2.12"],
25
+ "roodi" => ["= 2.1.0"],
26
+ "rails_best_practices" => ["~> 0.6"],
27
+ "churn" => ["= 0.0.7"],
28
+ "sexp_processor" => ["~> 3.0.3"], # required because of churn.
29
+ "chronic" => ["= 0.2.3"], # required by churn
30
+ "main" => ["= 4.7.1"], # required by churn
31
+ "activesupport" => [">= 2.0.0"], # ok
32
+ # "syntax" => ["= 1.0.0"],
33
+ "coderay" => [],
34
+ "fattr" => ["= 2.2.1"],
35
+ "arrayfields" => [" =4.7.4"],
36
+ "map" => [" =6.2.0"],
37
+ "bluff" => [],
38
+ "googlecharts" => []
39
+ }.each do |gem, version|
40
+ if version == []
41
+ s.add_dependency(gem)
42
+ else
43
+ s.add_dependency(gem,version)
44
+ end
45
+ end
46
+ # string comparison ftw
47
+ if RUBY_VERSION < '1.9'
48
+ s.add_dependency("ripper",[" =1.0.5"])
49
+ s.add_dependency("rcov", ["~> 0.8"])
50
+ s.add_dependency("Saikuro", ["= 1.1.0"])
51
+ else
52
+ s.add_dependency("rcov", ["~> 0.8"])
53
+ s.add_dependency("japgolly-Saikuro", ">= 1.1.1.0")
54
+ # still using rcov in ruby 1.9 till some errors are fleshed out
55
+ # s.add_dependency("simplecov", [">= 0.5.4"])
56
+ # s.add_dependency("simplecov-rcov", [">= 0.2.3"])
57
+ end
58
+
59
+
60
+ s.add_development_dependency("rake", '<=0.9.2')
61
+ s.add_development_dependency("rspec", ["= 1.3.0"])
62
+ s.add_development_dependency("test-construct", [">= 1.2.0"])
63
+ s.add_development_dependency("googlecharts")
64
+ end
65
+
@@ -57,7 +57,7 @@ describe MetricFu::Template do
57
57
  it 'should generate the filename of the template file' do
58
58
  section = mock('section')
59
59
  section.should_receive(:to_s).and_return('section')
60
- @template.should_receive(:this_directory).and_return('dir')
60
+ @template.should_receive(:template_directory).and_return('dir')
61
61
  result = @template.send(:template, section)
62
62
  result.should == "dir/section.html.erb"
63
63
  end
@@ -75,7 +75,7 @@ describe MetricFu::Template do
75
75
  describe "#inline_css" do
76
76
  it 'should return the contents of a css file' do
77
77
  css = 'mycss.css'
78
- @template.should_receive(:this_directory).and_return('dir')
78
+ @template.should_receive(:template_directory).and_return('dir')
79
79
  io = mock('io', :read => "css contents")
80
80
  @template.should_receive(:open).and_yield(io)
81
81
  result = @template.send(:inline_css, css)
@@ -89,6 +89,7 @@ describe MetricFu::Template do
89
89
  config = mock("configuration")
90
90
  config.stub!(:platform).and_return('universal-darwin-9.0')
91
91
  config.stub!(:darwin_txmt_protocol_no_thanks).and_return(false)
92
+ config.stub!(:link_prefix).and_return(nil)
92
93
  MetricFu.stub!(:configuration).and_return(config)
93
94
  end
94
95
 
@@ -118,6 +119,7 @@ describe MetricFu::Template do
118
119
  config = mock("configuration")
119
120
  config.stub!(:platform).and_return('universal-darwin-9.0')
120
121
  config.stub!(:darwin_txmt_protocol_no_thanks).and_return(true)
122
+ config.stub!(:link_prefix).and_return(nil)
121
123
  MetricFu.stub!(:configuration).and_return(config)
122
124
  File.should_receive(:expand_path).and_return('filename')
123
125
  end
@@ -143,6 +145,7 @@ describe MetricFu::Template do
143
145
  before(:each) do
144
146
  config = mock("configuration")
145
147
  config.should_receive(:platform).and_return('other')
148
+ config.stub!(:link_prefix).and_return(nil)
146
149
  config.stub!(:darwin_txmt_protocol_no_thanks).and_return(false)
147
150
  MetricFu.stub!(:configuration).and_return(config)
148
151
  File.should_receive(:expand_path).and_return('filename')
@@ -154,6 +157,20 @@ describe MetricFu::Template do
154
157
  result.should == "<a href='file://filename'>filename</a>"
155
158
  end
156
159
  end
160
+ describe "when configured with a link_prefix" do
161
+ before(:each) do
162
+ config = mock("configuration")
163
+ config.should_receive(:link_prefix).and_return('http://example.org/files')
164
+ MetricFu.stub!(:configuration).and_return(config)
165
+ File.should_receive(:expand_path).and_return('filename')
166
+ end
167
+
168
+ it 'should return a http protocol link' do
169
+ name = "filename"
170
+ result = @template.send(:link_to_filename, name)
171
+ result.should == "<a href='http://example.org/files/filename'>filename</a>"
172
+ end
173
+ end
157
174
  end
158
175
 
159
176
  describe "#cycle" do
@@ -39,7 +39,7 @@ describe MetricFu::Configuration do
39
39
 
40
40
  it 'should return the CC_BUILD_ARTIFACTS environment variable' do
41
41
  get_new_config
42
- base_directory.should == ENV['CC_BUILD_ARTIFACTS']
42
+ compare_paths(base_directory, ENV['CC_BUILD_ARTIFACTS'])
43
43
  end
44
44
  end
45
45
 
@@ -71,13 +71,13 @@ describe MetricFu::Configuration do
71
71
 
72
72
  it 'should set @scratch_directory to scratch relative '+
73
73
  'to @base_directory' do
74
- scratch_dir = File.join(base_directory, 'scratch')
74
+ scratch_dir = MetricFu.scratch_dir
75
75
  scratch_directory.should == scratch_dir
76
76
  end
77
77
 
78
78
  it 'should set @output_directory to output relative '+
79
79
  'to @base_directory' do
80
- output_dir = File.join(base_directory, 'output')
80
+ output_dir = MetricFu.output_dir
81
81
  output_directory.should == output_dir
82
82
  end
83
83
 
@@ -132,6 +132,7 @@ describe MetricFu::Configuration do
132
132
  @config.instance_variable_get(:@rcov).
133
133
  should == { :environment => 'test',
134
134
  :test_files => ['test/**/*_test.rb',
135
+ 'spec/spec_helper.rb',
135
136
  'spec/**/*_spec.rb'],
136
137
  :rcov_opts => ["--sort coverage",
137
138
  "--no-html",
@@ -30,8 +30,8 @@ describe MetricFu::Generator do
30
30
 
31
31
  describe "ConcreteClass#metric_directory" do
32
32
  it "should be 'tmp/metric_fu/scratch/concreteclass'" do
33
- ConcreteClass.metric_directory.
34
- should == "tmp/metric_fu/scratch/concreteclass"
33
+ compare_paths(ConcreteClass.metric_directory,
34
+ "tmp/metric_fu/scratch/concreteclass")
35
35
  end
36
36
  end
37
37
 
@@ -37,7 +37,7 @@ describe MetricFu::LineNumbers do
37
37
 
38
38
  it "should know the name of a class method defined in a 'class << self block at a particular line" do
39
39
  ln = MetricFu::LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
40
- ln.method_at_line(23).should == "Foo::neat"
40
+ ln.method_at_line(22).should == "Foo::neat"
41
41
  end
42
42
 
43
43
  it "should know the name of an instance method at a particular line in a file with two classes" do
@@ -59,4 +59,4 @@ describe MetricFu::LineNumbers do
59
59
 
60
60
  end
61
61
 
62
- end
62
+ end
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe MetricFu::Location do
4
+
5
+ context "with non-standard Reek method names" do
6
+ # reek reports the method with :: not # on modules like
7
+ # module ApplicationHelper \n def signed_in?, convert it so it records correctly
8
+ # class_or_method_name = class_or_method_name.gsub(/\:\:/,"#") if method_bug_conversion
9
+
10
+ before do
11
+ @location = Location.for("ApplicationHelper::section_link")
12
+ end
13
+
14
+ it "has method name" do
15
+ @location.method_name.should == 'ApplicationHelper#section_link'
16
+ end
17
+
18
+ it "has nil file path" do
19
+ @location.file_path.should == nil
20
+ end
21
+
22
+ it "has class name" do
23
+ @location.class_name.should == 'ApplicationHelper'
24
+ end
25
+
26
+ end
27
+
28
+ context "using new" do
29
+
30
+ before do
31
+ @location = Location.new("lib/foo.rb", "Foo", "Foo#some_method")
32
+ end
33
+
34
+ it "should return fully qualified method" do
35
+ @location.method_name.should == 'Foo#some_method'
36
+ end
37
+
38
+ end
39
+
40
+ context "using .for with class" do
41
+
42
+ before do
43
+ @location = Location.for("Module::Foo")
44
+ end
45
+
46
+ it "has nil method_name" do
47
+ @location.method_name.should be nil
48
+ end
49
+
50
+ it "has nil file_path" do
51
+ @location.file_path.should be nil
52
+ end
53
+
54
+ it "has class_name" do
55
+ @location.class_name.should == 'Foo'
56
+ end
57
+
58
+ end
59
+
60
+ context "using .for with method" do
61
+
62
+ before do
63
+ @location = Location.for("Module::Foo#some_method")
64
+ end
65
+
66
+ it "strips module from class name" do
67
+ @location.class_name.should == 'Foo'
68
+ end
69
+
70
+ it "strips module from method name" do
71
+ @location.method_name.should == 'Foo#some_method'
72
+ end
73
+
74
+ it "has nil file_path" do
75
+ @location.file_path.should be nil
76
+ end
77
+
78
+ end
79
+
80
+ context "with class method" do
81
+
82
+ it "provides non-qualified name" do
83
+ location = Location.for("Foo.some_class_method")
84
+ location.simple_method_name.should == '.some_class_method'
85
+ end
86
+
87
+ end
88
+
89
+ context "with instance method" do
90
+
91
+ it "provides non-qualified name" do
92
+ location = Location.for("Foo#some_class_method")
93
+ location.simple_method_name.should == '#some_class_method'
94
+ end
95
+
96
+ end
97
+ context "testing equality" do
98
+ before :each do
99
+
100
+ @location1 = MetricFu::Location.get('/some/path','some_class','some_method')
101
+
102
+ # ensure that we get a new object
103
+ @location2 = MetricFu::Location.new('/some/path','some_class','some_method')
104
+ end
105
+ it "should match two locations with the same paths as equal" do
106
+
107
+ hsh1 = {}
108
+ hsh1[@location1] = 1
109
+
110
+ hsh2 = {}
111
+ hsh2[@location2] = 1
112
+
113
+ hsh1.should == hsh2
114
+ hsh1.eql?(hsh2).should be_true
115
+
116
+ @location1.eql?(@location2).should be_true
117
+ end
118
+
119
+
120
+ it "should produce the same hash value given the same paths" do
121
+
122
+ @location1.hash.should == @location2.hash
123
+ end
124
+
125
+ end
126
+
127
+ end
@@ -0,0 +1,452 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe MetricAnalyzer do
4
+
5
+ context "with several types of data" do
6
+
7
+ before do
8
+ @yaml =<<-__
9
+ ---
10
+ :reek:
11
+ :matches:
12
+ - :file_path: lib/client/client.rb
13
+ :code_smells:
14
+ - :type: Large Class
15
+ :message: has at least 27 methods
16
+ :method: Devver::Client
17
+ - :type: Long Method
18
+ :message: has approx 6 statements
19
+ :method: Devver::Client#client_requested_sync
20
+ :flog:
21
+ :method_containers:
22
+ - :highest_score: 61.5870319141946
23
+ :path: /lib/client/client.rb
24
+ :methods:
25
+ Client#client_requested_sync:
26
+ :path: /lib/client/client.rb
27
+ :score: 37.9270319141946
28
+ :operators:
29
+ :+: 1.70000000000001
30
+ :/: 1.80000000000001
31
+ :method_at_line: 1.90000000000001
32
+ :puts: 1.70000000000001
33
+ :assignment: 33.0000000000001
34
+ :in_method?: 1.70000000000001
35
+ :message: 1.70000000000001
36
+ :branch: 12.6
37
+ :<<: 3.40000000000001
38
+ :each: 1.50000000000001
39
+ :lit_fixnum: 1.45
40
+ :raise: 1.80000000000001
41
+ :each_pair: 1.3
42
+ :*: 1.60000000000001
43
+ :to_f: 2.00000000000001
44
+ :each_with_index: 3.00000000000001
45
+ :[]: 22.3000000000001
46
+ :new: 1.60000000000001
47
+ :average_score: 11.1209009055421
48
+ :total_score: 1817.6
49
+ :name: Client#client_requested_sync
50
+ :churn:
51
+ :changes:
52
+ - :file_path: lib/client/client.rb
53
+ :times_changed: 54
54
+ - :file_path: lib/client/foo.rb
55
+ :times_changed: 52
56
+ __
57
+ end
58
+
59
+ it "gives all files, in order, from worst to best" do
60
+ analyzer = MetricAnalyzer.new(@yaml)
61
+ expected = [
62
+ "lib/client/client.rb",
63
+ "lib/client/foo.rb"]
64
+ analyzer.worst_files.should == expected
65
+ end
66
+
67
+ it "gives all issues for a class" do
68
+ analyzer = MetricAnalyzer.new(@yaml)
69
+ expected = {
70
+ :reek => "found 2 code smells",
71
+ :flog => "complexity is 37.9"
72
+ }
73
+ analyzer.problems_with(:class, "Client").should == expected
74
+ end
75
+
76
+ it "gives all issues for a method" do
77
+ analyzer = MetricAnalyzer.new(@yaml)
78
+ expected = {
79
+ :reek => "found 1 code smells",
80
+ :flog => "complexity is 37.9"}
81
+ analyzer.problems_with(:method, "Client#client_requested_sync").should == expected
82
+ end
83
+
84
+ it "gives all issues for a file" do
85
+ analyzer = MetricAnalyzer.new(@yaml)
86
+ expected = {
87
+ :reek => "found 2 code smells" ,
88
+ :flog => "complexity is 37.9",
89
+ :churn => "detected high level of churn (changed 54 times)"}
90
+ analyzer.problems_with(:file, "lib/client/client.rb").should == expected
91
+ end
92
+
93
+ it "provide location for a method" do
94
+ analyzer = MetricAnalyzer.new(@yaml)
95
+ expected = Location.new("lib/client/client.rb",
96
+ "Client",
97
+ "Client#client_requested_sync")
98
+ analyzer.location(:method, "Client#client_requested_sync").should == expected
99
+ end
100
+
101
+ it "provides location for a class" do
102
+ analyzer = MetricAnalyzer.new(@yaml)
103
+ expected = Location.new("lib/client/client.rb",
104
+ "Client",
105
+ nil)
106
+ analyzer.location(:class, "Client").should == expected
107
+ end
108
+
109
+ it "provides location for a file" do
110
+ analyzer = MetricAnalyzer.new(@yaml)
111
+ expected = Location.new("lib/client/client.rb",
112
+ nil,
113
+ nil)
114
+ analyzer.location(:file, "lib/client/client.rb").should == expected
115
+ end
116
+
117
+ end
118
+
119
+ context "with Reek data" do
120
+
121
+ before do
122
+ @yaml =<<-__
123
+ ---
124
+ :reek:
125
+ :matches:
126
+ - :file_path: lib/client/client.rb
127
+ :code_smells:
128
+ - :type: Large Class
129
+ :message: has at least 27 methods
130
+ :method: Devver::Client
131
+ - :type: Long Method
132
+ :message: has approx 6 statements
133
+ :method: Devver::Client#client_requested_sync
134
+ - :type: Large Class
135
+ :message: has at least 20 methods
136
+ :method: Devver::Foo
137
+ __
138
+ end
139
+
140
+ it "gives worst method" do
141
+ analyzer = MetricAnalyzer.new(@yaml)
142
+ analyzer.worst_methods(1).should == ["Client#client_requested_sync"]
143
+ end
144
+
145
+ it "gives worst class" do
146
+ analyzer = MetricAnalyzer.new(@yaml)
147
+ analyzer.worst_classes(1).should == ["Client"]
148
+ end
149
+
150
+ it "gives worst file" do
151
+ analyzer = MetricAnalyzer.new(@yaml)
152
+ analyzer.worst_files(1).should == ["lib/client/client.rb"]
153
+ end
154
+
155
+ end
156
+
157
+
158
+ context "with Saikuro data" do
159
+
160
+ before do
161
+ @yaml =<<-__
162
+ :saikuro:
163
+ :files:
164
+ - :classes:
165
+ - :complexity: 0
166
+ :methods: []
167
+ :lines: 3
168
+ :class_name: Shorty
169
+ - :complexity: 19
170
+ :methods:
171
+ - :complexity: 9
172
+ :lines: 6
173
+ :name: Shorty::Supr#self.handle_full_or_hash_option
174
+ - :complexity: 1
175
+ :lines: 9
176
+ :name: Shorty::Supr#initialize
177
+ :lines: 92
178
+ :class_name: Shorty::Supr
179
+ :filename: supr.rb
180
+ - :classes:
181
+ - :complexity: 12
182
+ :methods:
183
+ - :complexity: 8
184
+ :lines: 10
185
+ :name: Shorty::Bitly#info
186
+ :lines: 104
187
+ :class_name: Shorty::Bitly
188
+ :filename: bitly.rb
189
+ __
190
+ end
191
+
192
+ it "gives worst method" do
193
+ analyzer = MetricAnalyzer.new(@yaml)
194
+ analyzer.worst_methods(1).should == ["Supr#self.handle_full_or_hash_option"]
195
+ end
196
+
197
+ it "gives worst class" do
198
+ analyzer = MetricAnalyzer.new(@yaml)
199
+ analyzer.worst_classes(1).should == ["Bitly"]
200
+ end
201
+
202
+ it "gives complexity for method" do
203
+ analyzer = MetricAnalyzer.new(@yaml)
204
+ expected = {
205
+ :saikuro => "complexity is 1.0"
206
+ }
207
+ analyzer.problems_with(:method, "Supr#initialize").should == expected
208
+ end
209
+
210
+ it "gives average complexity for class" do
211
+ analyzer = MetricAnalyzer.new(@yaml)
212
+ expected = {
213
+ :saikuro => "average complexity is 5.0"
214
+ }
215
+ analyzer.problems_with(:class, "Supr").should == expected
216
+ end
217
+
218
+ end
219
+
220
+ context "with Flog data" do
221
+
222
+ before do
223
+ @yaml =<<-__
224
+ ---
225
+ :flog:
226
+ :method_containers:
227
+ - :highest_score: 85.5481735632041
228
+ :path: ""
229
+ :methods:
230
+ main#none:
231
+ :path:
232
+ :score: 85.5481735632041
233
+ :operators:
234
+ :+: 9.10000000000001
235
+ :assignment: 11.6000000000001
236
+ :require: 38.5000000000002
237
+ :branch: 8.80000000000009
238
+ :join: 20.0000000000002
239
+ :each: 6.60000000000007
240
+ :[]: 7.80000000000007
241
+ :task_defined?: 1.10000000000001
242
+ :load: 1.20000000000001
243
+ :average_score: 85.5481735632041
244
+ :total_score: 85.5481735632041
245
+ :name: main
246
+ - :highest_score: 61.5870319141946
247
+ :path: lib/generators/rcov.rb
248
+ :methods:
249
+ Rcov#add_method_data:
250
+ :path: lib/generators/rcov.rb:57
251
+ :score: 61.5870319141946
252
+ :operators:
253
+ :+: 1.70000000000001
254
+ :/: 1.80000000000001
255
+ :method_at_line: 1.90000000000001
256
+ :puts: 1.70000000000001
257
+ :assignment: 33.0000000000001
258
+ :in_method?: 1.70000000000001
259
+ :message: 1.70000000000001
260
+ :branch: 12.6
261
+ :<<: 3.40000000000001
262
+ :each: 1.50000000000001
263
+ :lit_fixnum: 1.45
264
+ :raise: 1.80000000000001
265
+ :each_pair: 1.3
266
+ :*: 1.60000000000001
267
+ :to_f: 2.00000000000001
268
+ :each_with_index: 3.00000000000001
269
+ :[]: 22.3000000000001
270
+ :new: 1.60000000000001
271
+ Rcov#analyze:
272
+ :path: lib/generators/rcov.rb:34
273
+ :score: 19.1504569136092
274
+ :operators:
275
+ :+: 1.40000000000001
276
+ :metric_directory: 1.6
277
+ :assignment: 9.10000000000004
278
+ :assemble_files: 1.3
279
+ :branch: 1.3
280
+ :open: 1.5
281
+ :shift: 1.3
282
+ :split: 1.3
283
+ :rcov: 3.10000000000001
284
+ :add_coverage_percentage: 1.3
285
+ :read: 1.3
286
+ :[]: 2.70000000000001
287
+ :average_score: 27.8909176873585
288
+ :total_score: 195.23642381151
289
+ - :highest_score: 60.0573892206447
290
+ :path: lib/base/metric_analyzer.rb
291
+ :methods:
292
+ MetricAnalyzer#grouping_key:
293
+ :path: lib/base/metric_analyzer.rb:117
294
+ :score: 2.6
295
+ :operators:
296
+ :inspect: 1.3
297
+ :object_id: 1.3
298
+ MetricAnalyzer#fix_row_file_path!:
299
+ :path: lib/base/metric_analyzer.rb:148
300
+ :score: 20.2743680542699
301
+ :operators:
302
+ :assignment: 10.0
303
+ :include?: 3.1
304
+ :branch: 7.20000000000001
305
+ :detect: 1.5
306
+ :file_paths: 1.7
307
+ :==: 3.1
308
+ :to_s: 1.3
309
+ :[]: 5.40000000000001
310
+ __
311
+ end
312
+
313
+ it "gives worst method" do
314
+ analyzer = MetricAnalyzer.new(@yaml)
315
+ analyzer.worst_methods(1).should == ["main#none"]
316
+ end
317
+
318
+ it "gives worst class" do
319
+ analyzer = MetricAnalyzer.new(@yaml)
320
+ analyzer.worst_classes(1).should == ["main"]
321
+ end
322
+
323
+ it "gives worst file" do
324
+ analyzer = MetricAnalyzer.new(@yaml)
325
+ analyzer.worst_files(1).should == ["lib/generators/rcov.rb:57"]
326
+ end
327
+
328
+ end
329
+
330
+ context "with Roodi data" do
331
+
332
+ before do
333
+ @yaml =<<-__
334
+ :roodi:
335
+ :total:
336
+ - Found 164 errors.
337
+ :problems:
338
+ - :line: "158"
339
+ :file: lib/client/client.rb
340
+ :problem: Method name "process" cyclomatic complexity is 10. It should be 8 or less.
341
+ - :line: "232"
342
+ :file: lib/client/client.rb
343
+ :problem: Method name "process_ready" cyclomatic complexity is 15. It should be 8 or less.
344
+ - :line: "288"
345
+ :file: lib/client/foobar.rb
346
+ :problem: Method name "send_tests" cyclomatic complexity is 10. It should be 8 or less.
347
+ __
348
+ end
349
+
350
+ it "gives worst file" do
351
+ analyzer = MetricAnalyzer.new(@yaml)
352
+ analyzer.worst_files(1).should == ["lib/client/client.rb"]
353
+ end
354
+
355
+ end
356
+
357
+ context "with Stats data" do
358
+
359
+ before do
360
+ @yaml =<<-__
361
+ :stats:
362
+ :codeLOC: 4222
363
+ :testLOC: 2111
364
+ :code_to_test_ratio: 2
365
+ __
366
+ end
367
+
368
+ it "should have codeLOC" do
369
+ analyzer = MetricAnalyzer.new(@yaml)
370
+ row = analyzer.table.rows_with('stat_name' => :codeLOC).first
371
+ row['stat_value'].should == 4222
372
+ end
373
+
374
+ it "should have testLOC" do
375
+ analyzer = MetricAnalyzer.new(@yaml)
376
+ row = analyzer.table.rows_with('stat_name' => :testLOC).first
377
+ row['stat_value'].should == 2111
378
+ end
379
+
380
+ it "should have code_to_test_ration" do
381
+ analyzer = MetricAnalyzer.new(@yaml)
382
+ row = analyzer.table.rows_with('stat_name' => :code_to_test_ratio).first
383
+ row['stat_value'].should == 2
384
+ end
385
+
386
+ end
387
+
388
+ context "with three different path representations of file (from Saikuro, Flog, and Reek)" do
389
+
390
+ before do
391
+ @yaml =<<-__
392
+ :saikuro:
393
+ :files:
394
+ - :classes:
395
+ - :complexity: 19
396
+ :methods:
397
+ - :complexity: 1
398
+ :lines: 9
399
+ :name: Client#client_requested_sync
400
+ - :complexity: 1
401
+ :lines: 9
402
+ :name: Client#method_that_is_not_mentioned_elsewhere_in_stats
403
+ :lines: 92
404
+ :class_name: Devver::Client
405
+ :filename: client.rb
406
+ :reek:
407
+ :matches:
408
+ - :file_path: lib/client/client.rb
409
+ :code_smells:
410
+ - :type: Large Class
411
+ :message: has at least 27 methods
412
+ :method: Devver::Client
413
+ - :type: Long Method
414
+ :message: has approx 6 statements
415
+ :method: Devver::Client#client_requested_sync
416
+ :flog:
417
+ :total: 1817.6
418
+ :pages:
419
+ - :path: /lib/client/client.rb
420
+ :highest_score: 37.9
421
+ :average_score: 13.6
422
+ :scanned_methods:
423
+ - :operators:
424
+ - :operator: "[]"
425
+ :score: 11.1
426
+ :score: 37.9
427
+ :name: Client#client_requested_sync
428
+ __
429
+ end
430
+
431
+ specify "all records should have full file_path" do
432
+ analyzer = MetricAnalyzer.new(@yaml)
433
+ analyzer.table.each do |row|
434
+ row['file_path'].should == 'lib/client/client.rb'
435
+ end
436
+ end
437
+
438
+ specify "all records should have class name" do
439
+ analyzer = MetricAnalyzer.new(@yaml)
440
+ analyzer.table.rows_with(:class_name => nil).should have(0).rows
441
+ end
442
+
443
+ specify "one record should not have method name" do
444
+ analyzer = MetricAnalyzer.new(@yaml)
445
+ analyzer.table.rows_with(:method_name => nil).should have(1).rows
446
+ end
447
+
448
+ end
449
+
450
+ end
451
+
452
+