bf4-metric_fu 2.1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. data/HISTORY +252 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +49 -0
  4. data/Rakefile +22 -0
  5. data/TODO +6 -0
  6. data/lib/base/base_template.rb +182 -0
  7. data/lib/base/churn_analyzer.rb +38 -0
  8. data/lib/base/code_issue.rb +100 -0
  9. data/lib/base/configuration.rb +219 -0
  10. data/lib/base/flay_analyzer.rb +50 -0
  11. data/lib/base/flog_analyzer.rb +43 -0
  12. data/lib/base/generator.rb +166 -0
  13. data/lib/base/graph.rb +44 -0
  14. data/lib/base/grouping.rb +42 -0
  15. data/lib/base/line_numbers.rb +79 -0
  16. data/lib/base/location.rb +87 -0
  17. data/lib/base/md5_tracker.rb +52 -0
  18. data/lib/base/metric_analyzer.rb +331 -0
  19. data/lib/base/ranking.rb +34 -0
  20. data/lib/base/rcov_analyzer.rb +43 -0
  21. data/lib/base/record.rb +43 -0
  22. data/lib/base/reek_analyzer.rb +164 -0
  23. data/lib/base/report.rb +110 -0
  24. data/lib/base/roodi_analyzer.rb +37 -0
  25. data/lib/base/saikuro_analyzer.rb +48 -0
  26. data/lib/base/scoring_strategies.rb +29 -0
  27. data/lib/base/stats_analyzer.rb +37 -0
  28. data/lib/base/table.rb +108 -0
  29. data/lib/generators/churn.rb +28 -0
  30. data/lib/generators/flay.rb +31 -0
  31. data/lib/generators/flog.rb +113 -0
  32. data/lib/generators/hotspots.rb +52 -0
  33. data/lib/generators/rails_best_practices.rb +53 -0
  34. data/lib/generators/rcov.rb +124 -0
  35. data/lib/generators/reek.rb +81 -0
  36. data/lib/generators/roodi.rb +35 -0
  37. data/lib/generators/saikuro.rb +259 -0
  38. data/lib/generators/stats.rb +58 -0
  39. data/lib/graphs/engines/bluff.rb +113 -0
  40. data/lib/graphs/engines/gchart.rb +157 -0
  41. data/lib/graphs/flay_grapher.rb +18 -0
  42. data/lib/graphs/flog_grapher.rb +57 -0
  43. data/lib/graphs/grapher.rb +11 -0
  44. data/lib/graphs/rails_best_practices_grapher.rb +19 -0
  45. data/lib/graphs/rcov_grapher.rb +18 -0
  46. data/lib/graphs/reek_grapher.rb +30 -0
  47. data/lib/graphs/roodi_grapher.rb +18 -0
  48. data/lib/graphs/stats_grapher.rb +20 -0
  49. data/lib/metric_fu.rb +80 -0
  50. data/lib/tasks/metric_fu.rake +36 -0
  51. data/lib/templates/awesome/awesome_template.rb +92 -0
  52. data/lib/templates/awesome/churn.html.erb +58 -0
  53. data/lib/templates/awesome/css/buttons.css +82 -0
  54. data/lib/templates/awesome/css/default.css +91 -0
  55. data/lib/templates/awesome/css/integrity.css +334 -0
  56. data/lib/templates/awesome/css/reset.css +7 -0
  57. data/lib/templates/awesome/css/syntax.css +19 -0
  58. data/lib/templates/awesome/flay.html.erb +34 -0
  59. data/lib/templates/awesome/flog.html.erb +55 -0
  60. data/lib/templates/awesome/hotspots.html.erb +62 -0
  61. data/lib/templates/awesome/index.html.erb +34 -0
  62. data/lib/templates/awesome/layout.html.erb +30 -0
  63. data/lib/templates/awesome/rails_best_practices.html.erb +27 -0
  64. data/lib/templates/awesome/rcov.html.erb +42 -0
  65. data/lib/templates/awesome/reek.html.erb +40 -0
  66. data/lib/templates/awesome/roodi.html.erb +27 -0
  67. data/lib/templates/awesome/saikuro.html.erb +71 -0
  68. data/lib/templates/awesome/stats.html.erb +51 -0
  69. data/lib/templates/javascripts/bluff-min.js +1 -0
  70. data/lib/templates/javascripts/excanvas.js +35 -0
  71. data/lib/templates/javascripts/js-class.js +1 -0
  72. data/lib/templates/standard/churn.html.erb +31 -0
  73. data/lib/templates/standard/default.css +64 -0
  74. data/lib/templates/standard/flay.html.erb +34 -0
  75. data/lib/templates/standard/flog.html.erb +57 -0
  76. data/lib/templates/standard/hotspots.html.erb +54 -0
  77. data/lib/templates/standard/index.html.erb +41 -0
  78. data/lib/templates/standard/rails_best_practices.html.erb +29 -0
  79. data/lib/templates/standard/rcov.html.erb +43 -0
  80. data/lib/templates/standard/reek.html.erb +42 -0
  81. data/lib/templates/standard/roodi.html.erb +29 -0
  82. data/lib/templates/standard/saikuro.html.erb +84 -0
  83. data/lib/templates/standard/standard_template.rb +27 -0
  84. data/lib/templates/standard/stats.html.erb +55 -0
  85. data/spec/base/base_template_spec.rb +194 -0
  86. data/spec/base/configuration_spec.rb +277 -0
  87. data/spec/base/generator_spec.rb +223 -0
  88. data/spec/base/graph_spec.rb +61 -0
  89. data/spec/base/line_numbers_spec.rb +62 -0
  90. data/spec/base/location_spec.rb +127 -0
  91. data/spec/base/md5_tracker_spec.rb +57 -0
  92. data/spec/base/metric_analyzer_spec.rb +452 -0
  93. data/spec/base/ranking_spec.rb +42 -0
  94. data/spec/base/report_spec.rb +146 -0
  95. data/spec/base/table_spec.rb +36 -0
  96. data/spec/generators/churn_spec.rb +41 -0
  97. data/spec/generators/flay_spec.rb +105 -0
  98. data/spec/generators/flog_spec.rb +70 -0
  99. data/spec/generators/hotspots_spec.rb +88 -0
  100. data/spec/generators/rails_best_practices_spec.rb +52 -0
  101. data/spec/generators/rcov_spec.rb +180 -0
  102. data/spec/generators/reek_spec.rb +134 -0
  103. data/spec/generators/roodi_spec.rb +24 -0
  104. data/spec/generators/saikuro_spec.rb +74 -0
  105. data/spec/generators/stats_spec.rb +74 -0
  106. data/spec/graphs/engines/bluff_spec.rb +19 -0
  107. data/spec/graphs/engines/gchart_spec.rb +156 -0
  108. data/spec/graphs/flay_grapher_spec.rb +56 -0
  109. data/spec/graphs/flog_grapher_spec.rb +108 -0
  110. data/spec/graphs/rails_best_practices_grapher_spec.rb +61 -0
  111. data/spec/graphs/rcov_grapher_spec.rb +56 -0
  112. data/spec/graphs/reek_grapher_spec.rb +65 -0
  113. data/spec/graphs/roodi_grapher_spec.rb +56 -0
  114. data/spec/graphs/stats_grapher_spec.rb +68 -0
  115. data/spec/resources/line_numbers/foo.rb +33 -0
  116. data/spec/resources/line_numbers/module.rb +11 -0
  117. data/spec/resources/line_numbers/module_surrounds_class.rb +15 -0
  118. data/spec/resources/line_numbers/two_classes.rb +11 -0
  119. data/spec/resources/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
  120. data/spec/resources/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
  121. data/spec/resources/saikuro/index_cyclo.html +155 -0
  122. data/spec/resources/saikuro_sfiles/thing.rb_cyclo.html +11 -0
  123. data/spec/resources/yml/20090630.yml +7922 -0
  124. data/spec/resources/yml/metric_missing.yml +1 -0
  125. data/spec/spec.opts +6 -0
  126. data/spec/spec_helper.rb +7 -0
  127. metadata +560 -0
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Ranking do
4
+
5
+ context "with many items" do
6
+
7
+ specify "it should give top x items" do
8
+ ranking = Ranking.new
9
+ ranking[:a] = 10
10
+ ranking[:b] = 50
11
+ ranking[:c] = 1
12
+ ranking.top(2).should == [:b,:a]
13
+ end
14
+
15
+ specify "if gives all items if param is not numeric" do
16
+ ranking = Ranking.new
17
+ ranking[:a] = 10
18
+ ranking[:b] = 50
19
+ ranking[:c] = 1
20
+ ranking.top(nil).should == [:b,:a, :c]
21
+ ranking.top(:all).should == [:b,:a, :c]
22
+ end
23
+
24
+ specify "lowest item is at 0 percentile" do
25
+ ranking = Ranking.new
26
+ ranking[:a] = 10
27
+ ranking[:b] = 50
28
+ ranking.percentile(:a).should == 0
29
+ end
30
+
31
+ specify "highest item is at high percentile" do
32
+ ranking = Ranking.new
33
+ ranking[:a] = 10
34
+ ranking[:b] = 50
35
+ ranking[:c] = 0
36
+ ranking[:d] = 5
37
+ ranking.percentile(:b).should == 0.75
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,146 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe MetricFu do
4
+
5
+ describe "#report" do
6
+ it 'should return an instance of Report' do
7
+ MetricFu.report.instance_of?(Report).should be(true)
8
+ end
9
+ end
10
+ end
11
+
12
+ describe MetricFu::Report do
13
+
14
+ before(:each) do
15
+ @report = MetricFu::Report.new
16
+ end
17
+
18
+ describe "#to_yaml" do
19
+ it 'should call #report_hash' do
20
+ report_hash = mock('report_hash')
21
+ report_hash.should_receive(:to_yaml)
22
+ @report.should_receive(:report_hash).and_return(report_hash)
23
+ @report.to_yaml
24
+ end
25
+ end
26
+
27
+ describe "#report_hash" do
28
+ end
29
+
30
+ describe "#save_templatized_report" do
31
+ it 'should create a new template class assign a report_hash '\
32
+ 'to the template class, and ask it to write itself out' do
33
+ template_class = mock('template_class')
34
+ template_class.should_receive(:new).and_return(template_class)
35
+ MetricFu.should_receive(:template_class).and_return(template_class)
36
+ template_class.should_receive(:report=)
37
+ template_class.should_receive(:per_file_data=)
38
+ template_class.should_receive(:write)
39
+ @report.save_templatized_report
40
+ end
41
+ end
42
+
43
+ describe "#add" do
44
+ it 'should add a passed hash to the report_hash instance variable' do
45
+ report_type = mock('report_type')
46
+ report_type.should_receive(:to_s).any_number_of_times.and_return('type')
47
+
48
+ report_inst = mock('report_inst')
49
+ report_type.should_receive(:new).and_return(report_inst)
50
+
51
+ report_inst.should_receive(:generate_report).and_return({:a => 'b'})
52
+ report_inst.should_receive(:respond_to?).and_return(false)
53
+
54
+ MetricFu.should_receive(:const_get).
55
+ with('Type').and_return(report_type)
56
+ report_hash = mock('report_hash')
57
+ report_hash.should_receive(:merge!).with({:a => 'b'})
58
+ @report.should_receive(:report_hash).and_return(report_hash)
59
+ @report.add(report_type)
60
+ end
61
+ end
62
+
63
+ describe "#save_output" do
64
+ it 'should write the passed content to dir/index.html' do
65
+ f = mock('file')
66
+ content = 'content'
67
+ @report.should_receive(:open).with('dir/file', 'w').and_yield(f)
68
+ f.should_receive(:puts).with(content)
69
+ @report.save_output(content, 'dir', 'file')
70
+ end
71
+ end
72
+
73
+ describe '#open_in_browser? ' do
74
+
75
+ before(:each) do
76
+ @config = mock('configuration')
77
+ end
78
+
79
+ describe 'when the platform is os x ' do
80
+
81
+ before(:each) do
82
+ @config.should_receive(:platform).and_return('darwin')
83
+ end
84
+
85
+ describe 'and we are in cruise control ' do
86
+
87
+ before(:each) do
88
+ @config.should_receive(:is_cruise_control_rb?).and_return(true)
89
+ MetricFu.stub!(:configuration).and_return(@config)
90
+ end
91
+
92
+ it 'should return false' do
93
+ @report.open_in_browser?.should be_false
94
+ end
95
+ end
96
+
97
+ describe 'and we are not in cruise control' do
98
+
99
+ before(:each) do
100
+ @config.should_receive(:is_cruise_control_rb?).and_return(false)
101
+ MetricFu.stub!(:configuration).and_return(@config)
102
+ end
103
+
104
+ it 'should return true' do
105
+ @report.open_in_browser?.should be_true
106
+ end
107
+ end
108
+ end
109
+
110
+ describe 'when the platform is not os x ' do
111
+ before(:each) do
112
+ @config.should_receive(:platform).and_return('other')
113
+ end
114
+
115
+ describe 'and we are in cruise control' do
116
+ before(:each) do
117
+ MetricFu.stub!(:configuration).and_return(@config)
118
+ end
119
+
120
+ it 'should return false' do
121
+ @report.open_in_browser?.should be_false
122
+ end
123
+ end
124
+
125
+ describe 'and we are not in cruise control' do
126
+ before(:each) do
127
+ MetricFu.stub!(:configuration).and_return(@config)
128
+ end
129
+
130
+ it 'should return false' do
131
+ @report.open_in_browser?.should be_false
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+
138
+ describe '#show_in_browser' do
139
+ it 'should call open with the passed directory' do
140
+ @report.should_receive(:open_in_browser?).and_return(true)
141
+ @report.should_receive(:system).with("open my_dir/index.html")
142
+ @report.show_in_browser('my_dir')
143
+ end
144
+
145
+ end
146
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Table do
4
+
5
+ context 'rows_with' do
6
+
7
+ specify 'can select rows based on an optimized key (metric)' do
8
+ table = Table.new(:column_names => %w{foo metric})
9
+ table << {'metric' => 'flay', 'foo' => 1}
10
+ table << {'metric' => 'flay', 'foo' => 2}
11
+ table << {'metric' => 'flog', 'foo' => 1}
12
+ table << {'metric' => 'saikuro', 'foo' => 2}
13
+ matching_rows = table.rows_with(:metric => 'flay')
14
+ matching_rows.length.should == 2
15
+ matching_rows.each do |row|
16
+ row.metric.should == 'flay'
17
+ end
18
+ end
19
+
20
+ specify 'can select on arbitrary (non-optimized) field' do
21
+ table = Table.new(:column_names => %w{foo baz})
22
+ table << {'baz' => 'str1', 'foo' => 1}
23
+ table << {'baz' => 'str2', 'foo' => 2}
24
+ table << {'baz' => 'str3', 'foo' => 1}
25
+ table << {'baz' => 'str4', 'foo' => 3}
26
+ matching_rows = table.rows_with(:foo => 1)
27
+ matching_rows.length.should == 2
28
+ matching_rows.each do |row|
29
+ row.foo.should == 1
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Churn do
4
+
5
+ describe "analyze method" do
6
+ before :each do
7
+ MetricFu::Configuration.run {}
8
+ File.stub!(:directory?).and_return(true)
9
+ @changes = {"lib/generators/flog.rb"=>2, "lib/metric_fu.rb"=>3}
10
+ end
11
+
12
+ it "should be empty on error" do
13
+ churn = MetricFu::Churn.new
14
+ churn.instance_variable_set(:@output, "Churning requires a subversion or git repo")
15
+ result = churn.analyze
16
+ result.should == [:churn => {}]
17
+ end
18
+
19
+ it "should return yaml results" do
20
+ churn = MetricFu::Churn.new
21
+ churn.instance_variable_set(:@output, "--- \n:churn: \n :changed_files: \n - spec/graphs/flog_grapher_spec.rb\n - spec/base/graph_spec.rb\n - lib/templates/awesome/layout.html.erb\n - lib/graphs/rcov_grapher.rb\n - lib/base/base_template.rb\n - spec/graphs/grapher_spec.rb\n - lib/templates/awesome/flog.html.erb\n - lib/templates/awesome/flay.html.erb\n - lib/graphs/roodi_grapher.rb\n - lib/graphs/reek_grapher.rb\n - HISTORY\n - spec/graphs/roodi_grapher_spec.rb\n - lib/generators/rcov.rb\n - spec/graphs/engines/gchart_spec.rb\n - spec/graphs/rcov_grapher_spec.rb\n - lib/templates/javascripts/excanvas.js\n - lib/templates/javascripts/bluff-min.js\n - spec/graphs/reek_grapher_spec.rb\n")
22
+ result = churn.analyze
23
+ result.should == {:churn=>{:changed_files=>["spec/graphs/flog_grapher_spec.rb", "spec/base/graph_spec.rb", "lib/templates/awesome/layout.html.erb", "lib/graphs/rcov_grapher.rb", "lib/base/base_template.rb", "spec/graphs/grapher_spec.rb", "lib/templates/awesome/flog.html.erb", "lib/templates/awesome/flay.html.erb", "lib/graphs/roodi_grapher.rb", "lib/graphs/reek_grapher.rb", "HISTORY", "spec/graphs/roodi_grapher_spec.rb", "lib/generators/rcov.rb", "spec/graphs/engines/gchart_spec.rb", "spec/graphs/rcov_grapher_spec.rb", "lib/templates/javascripts/excanvas.js", "lib/templates/javascripts/bluff-min.js", "spec/graphs/reek_grapher_spec.rb"]}}
24
+ end
25
+
26
+ end
27
+
28
+ describe "to_h method" do
29
+ before :each do
30
+ MetricFu::Configuration.run {}
31
+ File.stub!(:directory?).and_return(true)
32
+ end
33
+
34
+ it "should put the changes into a hash" do
35
+ churn = MetricFu::Churn.new
36
+ churn.instance_variable_set(:@churn, {:churn => 'results'})
37
+ churn.to_h[:churn].should == "results"
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,105 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Flay do
4
+ describe "emit method" do
5
+ it "should look at the dirs" do
6
+ MetricFu::Configuration.run {|config| config.flay = { :dirs_to_flay => ['app', 'lib'], :filetypes => ['rb'] } }
7
+ File.stub!(:directory?).and_return(true)
8
+ @flay = MetricFu::Flay.new('base_dir')
9
+
10
+ @flay.should_receive(:`).with("flay app lib")
11
+ output = @flay.emit
12
+ end
13
+
14
+ it "should limit flay scores by the minimum_score" do
15
+ MetricFu::Configuration.run {|config| config.flay = { :dirs_to_flay => [], :minimum_score => 99 } }
16
+ File.stub!(:directory?).and_return(true)
17
+ @flay = MetricFu::Flay.new('base_dir')
18
+
19
+ @flay.should_receive(:`).with("flay --mass 99 ")
20
+ output = @flay.emit
21
+ end
22
+ end
23
+
24
+ describe "analyze method" do
25
+ before :each do
26
+ lines = <<-HERE
27
+ Total score (lower is better) = 246
28
+
29
+
30
+ 1) IDENTICAL code found in :or (mass*2 = 68)
31
+ app/controllers/link_targets_controller.rb:57
32
+ app/controllers/primary_sites_controller.rb:138
33
+
34
+ 2) Similar code found in :if (mass = 64)
35
+ app/controllers/primary_sites_controller.rb:75
36
+ app/controllers/primary_sites_controller.rb:76
37
+ app/controllers/primary_sites_controller.rb:88
38
+ app/controllers/primary_sites_controller.rb:89
39
+ HERE
40
+ MetricFu::Configuration.run {}
41
+ File.stub!(:directory?).and_return(true)
42
+ @flay = MetricFu::Flay.new('base_dir')
43
+ @flay.instance_variable_set(:@output, lines)
44
+ end
45
+
46
+ it "should analyze and return matches" do
47
+ @flay.analyze.should == [ ["Total score (lower is better) = 246"],
48
+ ["\n1) IDENTICAL code found in :or (mass*2 = 68)",
49
+ "app/controllers/link_targets_controller.rb:57",
50
+ "app/controllers/primary_sites_controller.rb:138"],
51
+ ["2) Similar code found in :if (mass = 64)",
52
+ "app/controllers/primary_sites_controller.rb:75",
53
+ "app/controllers/primary_sites_controller.rb:76",
54
+ "app/controllers/primary_sites_controller.rb:88",
55
+ "app/controllers/primary_sites_controller.rb:89"] ]
56
+ end
57
+ end
58
+
59
+ describe "to_h method" do
60
+
61
+ before :each do
62
+ lines = [ ["Total score (lower is better) = 284"],
63
+ ["\n1) IDENTICAL code found in :or (mass*2 = 68)",
64
+ "app/controllers/link_targets_controller.rb:57",
65
+ "app/controllers/primary_sites_controller.rb:138"],
66
+ ["2) Similar code found in :if (mass = 64)",
67
+ "app/controllers/primary_sites_controller.rb:75",
68
+ "app/controllers/primary_sites_controller.rb:76",
69
+ "app/controllers/primary_sites_controller.rb:88",
70
+ "app/controllers/primary_sites_controller.rb:89"],
71
+ ["3) Similar code found in :defn (mass = 40)",
72
+ "app/controllers/link_targets_controller.rb:40",
73
+ "app/controllers/primary_sites_controller.rb:98"],
74
+ ["4) Similar code found in :defn (mass = 38)",
75
+ "app/controllers/link_targets_controller.rb:13",
76
+ "app/controllers/primary_sites_controller.rb:50"],
77
+ ["5) Similar code found in :defn (mass = 38)",
78
+ "app/models/primary_site.rb:104",
79
+ "app/models/primary_site.rb:109"],
80
+ ["6) Similar code found in :call (mass = 36)",
81
+ "app/controllers/bookmarklet_integration_controller.rb:6",
82
+ "app/controllers/bookmarklet_integration_controller.rb:17"]]
83
+
84
+ MetricFu::Configuration.run {}
85
+ File.stub!(:directory?).and_return(true)
86
+ flay = MetricFu::Flay.new('base_dir')
87
+ flay.instance_variable_set(:@matches, lines)
88
+ @results = flay.to_h
89
+ end
90
+
91
+ it "should find the total_score" do
92
+ @results[:flay][:total_score].should == '284'
93
+ end
94
+
95
+ it "should have 6 matches" do
96
+ @results[:flay][:matches].size.should == 6
97
+ end
98
+
99
+ it "should capture info for match" do
100
+ @results[:flay][:matches].first[:reason].should =~ /IDENTICAL/
101
+ @results[:flay][:matches].first[:matches].first[:name].should =~ /link_targets_controller/
102
+ @results[:flay][:matches].first[:matches].first[:line].should == "57"
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,70 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ describe Flog do
3
+ before :each do
4
+ MetricFu::Configuration.run {}
5
+ File.stub!(:directory?).and_return(true)
6
+ @flog = MetricFu::Flog.new('base_dir')
7
+ end
8
+
9
+ describe "emit method" do
10
+ it "should look for files and flog them" do
11
+ Dir.should_receive(:glob).with("lib/**/*.rb").and_return(["found/file.rb"])
12
+ ::Flog.should_receive(:parse_options).with(["--all", "--details"]).and_return("options")
13
+ ::Flog.should_receive(:new).with("options").and_return(flogger = mock('flogger'))
14
+ flogger.should_receive(:flog).with(["found/file.rb"])
15
+ @flog.emit
16
+ end
17
+ end
18
+
19
+ describe "analyze method" do
20
+ it "should harvest the flog information and put it into method_containers" do
21
+ first_full_method_name = "ClassName#first_method_name"
22
+ second_full_method_name = "ClassName#second_method_name"
23
+
24
+ flogger = mock('flogger', :calls => {first_full_method_name => {:branch => 11.1, :puts => 1.1},
25
+ second_full_method_name => {:branch => 22.2, :puts => 2.2}},
26
+ :method_locations => {first_full_method_name => '/file/location.rb:11',
27
+ second_full_method_name => '/file/location.rb:22'},
28
+ :totals => {first_full_method_name => 11.11,
29
+ second_full_method_name => 22.22})
30
+ @flog.instance_variable_set(:@flogger, flogger)
31
+ @flog.analyze
32
+ method_containers = @flog.instance_variable_get(:@method_containers)
33
+ method_containers.size.should == 1
34
+
35
+ expected={:methods=>{"ClassName#first_method_name" => { :path=>"/file/location.rb:11",
36
+ :score=>11.11,
37
+ :operators=>{ :branch=>11.1,
38
+ :puts=>1.1}},
39
+ "ClassName#second_method_name" => {:path=>"/file/location.rb:22",
40
+ :score=>22.22,
41
+ :operators=>{ :branch=>22.2,
42
+ :puts=>2.2}}},
43
+ :path=>"/file/location.rb",
44
+ :average_score=>((11.11 + 22.22) / 2.0),
45
+ :total_score=>33.33,
46
+ :highest_score=>22.22,
47
+ :name=>"ClassName"}
48
+
49
+ method_containers["ClassName"].to_h.should == expected
50
+ end
51
+ end
52
+
53
+ describe "to_h method" do
54
+ it "should make-a nice hash" do
55
+ flogger = mock('flogger', :total => 111.1, :average => 7.3)
56
+ @flog.instance_variable_set(:@flogger, flogger)
57
+ method_containers = {:ignore_me_1 => mock('container_1', :highest_score => 11.1, :to_h => 'container_1'),
58
+ :ignore_me_2 => mock('container_2', :highest_score => 33.3, :to_h => 'container_2'),
59
+ :ignore_me_3 => mock('container_3', :highest_score => 22.2, :to_h => 'container_3')}
60
+ @flog.instance_variable_set(:@method_containers, method_containers)
61
+
62
+ expected = {:flog => { :total => 111.1,
63
+ :average => 7.3,
64
+ :method_containers => ['container_2', 'container_3', 'container_1']}}
65
+
66
+ @flog.to_h.should == expected
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,88 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Hotspots do
4
+
5
+ describe "analyze method" do
6
+ before :each do
7
+ MetricFu::Configuration.run {}
8
+ File.stub!(:directory?).and_return(true)
9
+ @yaml =<<END
10
+ ---
11
+ :reek:
12
+ :matches:
13
+ - :file_path: lib/client/client.rb
14
+ :code_smells:
15
+ - :type: Large Class
16
+ :message: has at least 27 methods
17
+ :method: Devver::Client
18
+ - :type: Long Method
19
+ :message: has approx 6 statements
20
+ :method: Devver::Client#client_requested_sync
21
+ :flog:
22
+ :method_containers:
23
+ - :highest_score: 61.5870319141946
24
+ :path: /lib/client/client.rb
25
+ :methods:
26
+ Client#client_requested_sync:
27
+ :path: /lib/client/client.rb
28
+ :score: 37.9270319141946
29
+ :operators:
30
+ :+: 1.70000000000001
31
+ :/: 1.80000000000001
32
+ :method_at_line: 1.90000000000001
33
+ :puts: 1.70000000000001
34
+ :assignment: 33.0000000000001
35
+ :in_method?: 1.70000000000001
36
+ :message: 1.70000000000001
37
+ :branch: 12.6
38
+ :<<: 3.40000000000001
39
+ :each: 1.50000000000001
40
+ :lit_fixnum: 1.45
41
+ :raise: 1.80000000000001
42
+ :each_pair: 1.3
43
+ :*: 1.60000000000001
44
+ :to_f: 2.00000000000001
45
+ :each_with_index: 3.00000000000001
46
+ :[]: 22.3000000000001
47
+ :new: 1.60000000000001
48
+ :average_score: 11.1209009055421
49
+ :total_score: 1817.6
50
+ :name: Client#client_requested_sync
51
+ :churn:
52
+ :changes:
53
+ - :file_path: lib/client/client.rb
54
+ :times_changed: 54
55
+ - :file_path: lib/client/foo.rb
56
+ :times_changed: 52
57
+ END
58
+ end
59
+
60
+ it "should be empty on error" do
61
+ hotspots = MetricFu::Hotspots.new
62
+ hotspots.instance_variable_set(:@analyzer, nil)
63
+ result = hotspots.analyze
64
+ result.should == {}
65
+ end
66
+
67
+ it "should return yaml results" do
68
+ hotspots = MetricFu::Hotspots.new
69
+ analyzer = MetricAnalyzer.new(@yaml)
70
+ hotspots.instance_variable_set(:@analyzer, analyzer)
71
+ result = hotspots.analyze
72
+ expected = JSON.parse("{\"methods\":[{\"location\":{\"class_name\":\"Client\",\"method_name\":\"Client#client_requested_sync\",\"file_path\":\"lib/client/client.rb\",\"hash\":7919384682,\"simple_method_name\":\"#client_requested_sync\"},\"details\":{\"reek\":\"found 1 code smells\",\"flog\":\"complexity is 37.9\"}}],\"classes\":[{\"location\":{\"class_name\":\"Client\",\"method_name\":null,\"file_path\":\"lib/client/client.rb\",\"hash\":7995629750},\"details\":{\"reek\":\"found 2 code smells\",\"flog\":\"complexity is 37.9\"}}],\"files\":[{\"location\":{\"class_name\":null,\"method_name\":null,\"file_path\":\"lib/client/client.rb\",\"hash\":-5738801681},\"details\":{\"reek\":\"found 2 code smells\",\"flog\":\"complexity is 37.9\",\"churn\":\"detected high level of churn (changed 54 times)\"}},{\"location\":{\"class_name\":null,\"method_name\":null,\"file_path\":\"lib/client/foo.rb\",\"hash\":-7081271905},\"details\":{\"churn\":\"detected high level of churn (changed 52 times)\"}}]}")
73
+ compare_hashes(JSON.parse(hotspots.to_h[:hotspots].to_json), expected)
74
+ end
75
+
76
+ it "should put the changes into a hash" do
77
+ hotspots = MetricFu::Hotspots.new
78
+ analyzer = MetricAnalyzer.new(@yaml)
79
+ hotspots.instance_variable_set(:@analyzer, analyzer)
80
+ hotspots.analyze
81
+ expected = JSON.parse("{\"methods\":[{\"location\":{\"class_name\":\"Client\",\"method_name\":\"Client#client_requested_sync\",\"file_path\":\"lib/client/client.rb\",\"hash\":7919384682,\"simple_method_name\":\"#client_requested_sync\"},\"details\":{\"reek\":\"found 1 code smells\",\"flog\":\"complexity is 37.9\"}}],\"classes\":[{\"location\":{\"class_name\":\"Client\",\"method_name\":null,\"file_path\":\"lib/client/client.rb\",\"hash\":7995629750},\"details\":{\"reek\":\"found 2 code smells\",\"flog\":\"complexity is 37.9\"}}],\"files\":[{\"location\":{\"class_name\":null,\"method_name\":null,\"file_path\":\"lib/client/client.rb\",\"hash\":-5738801681},\"details\":{\"reek\":\"found 2 code smells\",\"flog\":\"complexity is 37.9\",\"churn\":\"detected high level of churn (changed 54 times)\"}},{\"location\":{\"class_name\":null,\"method_name\":null,\"file_path\":\"lib/client/foo.rb\",\"hash\":-7081271905},\"details\":{\"churn\":\"detected high level of churn (changed 52 times)\"}}]}")
82
+ compare_hashes(JSON.parse(hotspots.to_h[:hotspots].to_json), expected)
83
+ end
84
+ end
85
+ end
86
+ def compare_hashes(got,expected)
87
+ got.hash == expected.hash
88
+ end