bf4-metric_fu 2.1.3.1

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.
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