flyerhzm-metric_fu 1.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.
Files changed (92) hide show
  1. data/HISTORY +164 -0
  2. data/MIT-LICENSE +22 -0
  3. data/Manifest.txt +25 -0
  4. data/README.textile +27 -0
  5. data/Rakefile +18 -0
  6. data/TODO +9 -0
  7. data/lib/base/base_template.rb +145 -0
  8. data/lib/base/configuration.rb +180 -0
  9. data/lib/base/generator.rb +167 -0
  10. data/lib/base/graph.rb +39 -0
  11. data/lib/base/md5_tracker.rb +52 -0
  12. data/lib/base/report.rb +100 -0
  13. data/lib/generators/churn.rb +90 -0
  14. data/lib/generators/flay.rb +34 -0
  15. data/lib/generators/flog.rb +167 -0
  16. data/lib/generators/rails_best_practices.rb +31 -0
  17. data/lib/generators/rcov.rb +87 -0
  18. data/lib/generators/reek.rb +64 -0
  19. data/lib/generators/roodi.rb +32 -0
  20. data/lib/generators/saikuro.rb +208 -0
  21. data/lib/generators/stats.rb +43 -0
  22. data/lib/graphs/engines/bluff.rb +98 -0
  23. data/lib/graphs/engines/gchart.rb +119 -0
  24. data/lib/graphs/flay_grapher.rb +20 -0
  25. data/lib/graphs/flog_grapher.rb +40 -0
  26. data/lib/graphs/grapher.rb +11 -0
  27. data/lib/graphs/rails_best_practices_grapher.rb +20 -0
  28. data/lib/graphs/rcov_grapher.rb +20 -0
  29. data/lib/graphs/reek_grapher.rb +32 -0
  30. data/lib/graphs/roodi_grapher.rb +20 -0
  31. data/lib/metric_fu.rb +31 -0
  32. data/lib/templates/awesome/awesome_template.rb +37 -0
  33. data/lib/templates/awesome/churn.html.erb +19 -0
  34. data/lib/templates/awesome/css/buttons.css +82 -0
  35. data/lib/templates/awesome/css/default.css +75 -0
  36. data/lib/templates/awesome/css/integrity.css +335 -0
  37. data/lib/templates/awesome/css/reset.css +7 -0
  38. data/lib/templates/awesome/flay.html.erb +33 -0
  39. data/lib/templates/awesome/flog.html.erb +53 -0
  40. data/lib/templates/awesome/index.html.erb +31 -0
  41. data/lib/templates/awesome/layout.html.erb +30 -0
  42. data/lib/templates/awesome/rails_best_practices.html.erb +27 -0
  43. data/lib/templates/awesome/rcov.html.erb +42 -0
  44. data/lib/templates/awesome/reek.html.erb +40 -0
  45. data/lib/templates/awesome/roodi.html.erb +27 -0
  46. data/lib/templates/awesome/saikuro.html.erb +71 -0
  47. data/lib/templates/awesome/stats.html.erb +41 -0
  48. data/lib/templates/javascripts/bluff-min.js +1 -0
  49. data/lib/templates/javascripts/excanvas.js +19 -0
  50. data/lib/templates/javascripts/js-class.js +1 -0
  51. data/lib/templates/standard/churn.html.erb +31 -0
  52. data/lib/templates/standard/default.css +64 -0
  53. data/lib/templates/standard/flay.html.erb +34 -0
  54. data/lib/templates/standard/flog.html.erb +53 -0
  55. data/lib/templates/standard/index.html.erb +41 -0
  56. data/lib/templates/standard/rails_best_practices.html.erb +29 -0
  57. data/lib/templates/standard/rcov.html.erb +43 -0
  58. data/lib/templates/standard/reek.html.erb +42 -0
  59. data/lib/templates/standard/roodi.html.erb +29 -0
  60. data/lib/templates/standard/saikuro.html.erb +84 -0
  61. data/lib/templates/standard/standard_template.rb +26 -0
  62. data/lib/templates/standard/stats.html.erb +55 -0
  63. data/spec/base/base_template_spec.rb +161 -0
  64. data/spec/base/configuration_spec.rb +269 -0
  65. data/spec/base/generator_spec.rb +244 -0
  66. data/spec/base/graph_spec.rb +24 -0
  67. data/spec/base/md5_tracker_spec.rb +57 -0
  68. data/spec/base/report_spec.rb +139 -0
  69. data/spec/generators/churn_spec.rb +152 -0
  70. data/spec/generators/flay_spec.rb +104 -0
  71. data/spec/generators/flog_spec.rb +238 -0
  72. data/spec/generators/reek_spec.rb +126 -0
  73. data/spec/generators/saikuro_spec.rb +58 -0
  74. data/spec/generators/stats_spec.rb +74 -0
  75. data/spec/graphs/engines/bluff_spec.rb +15 -0
  76. data/spec/graphs/engines/gchart_spec.rb +15 -0
  77. data/spec/graphs/flay_grapher_spec.rb +37 -0
  78. data/spec/graphs/flog_grapher_spec.rb +45 -0
  79. data/spec/graphs/rcov_grapher_spec.rb +37 -0
  80. data/spec/graphs/reek_grapher_spec.rb +46 -0
  81. data/spec/graphs/roodi_grapher_spec.rb +37 -0
  82. data/spec/resources/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
  83. data/spec/resources/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
  84. data/spec/resources/saikuro/index_cyclo.html +155 -0
  85. data/spec/resources/saikuro_sfiles/thing.rb_cyclo.html +11 -0
  86. data/spec/resources/yml/20090630.yml +7844 -0
  87. data/spec/spec.opts +8 -0
  88. data/spec/spec_helper.rb +7 -0
  89. data/tasks/metric_fu.rake +22 -0
  90. data/vendor/_fonts/monaco.ttf +0 -0
  91. data/vendor/saikuro/saikuro.rb +1219 -0
  92. metadata +234 -0
@@ -0,0 +1,244 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe MetricFu::Generator do
4
+
5
+ include Construct::Helpers
6
+
7
+ MetricFu::Configuration.run do |config|
8
+ end
9
+
10
+ class ConcreteClass < MetricFu::Generator
11
+ def emit
12
+ end
13
+
14
+ def analyze
15
+ end
16
+
17
+ def to_h
18
+ end
19
+ end
20
+
21
+ before(:each) do
22
+ @concrete_class = ConcreteClass.new
23
+ end
24
+
25
+ describe "ConcreteClass#class_name" do
26
+ it "should be 'concreteclass'" do
27
+ ConcreteClass.class_name.should == 'concreteclass'
28
+ end
29
+ end
30
+
31
+ describe "ConcreteClass#metric_directory" do
32
+ it "should be 'tmp/metric_fu/scratch/concreteclass'" do
33
+ ConcreteClass.metric_directory.
34
+ should == "tmp/metric_fu/scratch/concreteclass"
35
+ end
36
+ end
37
+
38
+ describe "#create_metric_dir_if_missing " do
39
+ describe "when the metric_dir exists " do
40
+ it 'should not call mkdir_p on FileUtils' do
41
+ File.stub!(:directory?).and_return(true)
42
+ FileUtils.should_not_receive(:mkdir_p)
43
+ @concrete_class.create_metric_dir_if_missing
44
+ end
45
+ end
46
+
47
+ describe "when the metric_dir does not exist " do
48
+ it 'should call mkdir_p on FileUtils' do
49
+ File.stub!(:directory?).and_return(false)
50
+ FileUtils.should_receive(:mkdir_p)
51
+ @concrete_class.create_metric_dir_if_missing
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#create_output_dir_if_missing" do
57
+ describe "when the output_dir exists " do
58
+ it 'should not call mkdir_p on FileUtils' do
59
+ File.stub!(:directory?).and_return(true)
60
+ FileUtils.should_not_receive(:mkdir_p)
61
+ @concrete_class.create_output_dir_if_missing
62
+ end
63
+ end
64
+
65
+ describe "when the output_dir does not exist " do
66
+ it 'should call mkdir_p on FileUtils' do
67
+ File.stub!(:directory?).and_return(false)
68
+ FileUtils.should_receive(:mkdir_p)
69
+ @concrete_class.create_output_dir_if_missing
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#metric_directory' do
75
+ it 'should return the results of ConcreteClass#metric_directory' do
76
+ ConcreteClass.stub!(:metric_directory).and_return('foo')
77
+ @concrete_class.metric_directory.should == 'foo'
78
+ end
79
+ end
80
+
81
+ describe 'ConcreteClass#generate_report' do
82
+ it 'should create a new instance of ConcreteClass' do
83
+ ConcreteClass.should_receive(:new).and_return(@concrete_class)
84
+ @concrete_class.should_receive(:generate_report).and_return(true)
85
+ ConcreteClass.generate_report
86
+ end
87
+
88
+ it 'should call #generate_report on the new ConcreteClass' do
89
+ ConcreteClass.should_receive(:new).and_return(@concrete_class)
90
+ @concrete_class.should_receive(:generate_report).and_return(true)
91
+ ConcreteClass.generate_report
92
+ end
93
+ end
94
+
95
+ describe '@concrete_class should have hook methods for '\
96
+ +'[before|after]_[emit|analyze|to_h]' do
97
+
98
+ %w[emit analyze].each do |meth|
99
+
100
+ it "should respond to #before_#{meth}" do
101
+ @concrete_class.respond_to?("before_#{meth}".to_sym).should be_true
102
+ end
103
+
104
+ it "should respond to #after_#{meth}" do
105
+ @concrete_class.respond_to?("after_#{meth}".to_sym).should be_true
106
+ end
107
+ end
108
+
109
+ it "should respond to #before_to_h" do
110
+ @concrete_class.respond_to?("before_to_h".to_sym).should be_true
111
+ end
112
+ end
113
+
114
+ describe "#generate_report" do
115
+ it 'should raise an error when calling #emit' do
116
+ @abstract_class = MetricFu::Generator.new
117
+ lambda { @abstract_class.generate_report }.should raise_error
118
+ end
119
+
120
+ it 'should call #analyze' do
121
+ @abstract_class = MetricFu::Generator.new
122
+ lambda { @abstract_class.generate_report }.should raise_error
123
+ end
124
+
125
+ it 'should call #to_h' do
126
+ @abstract_class = MetricFu::Generator.new
127
+ lambda { @abstract_class.generate_report }.should raise_error
128
+ end
129
+ end
130
+
131
+ describe "#generate_report (in a concrete class)" do
132
+
133
+ %w[emit analyze].each do |meth|
134
+ it "should call #before_#{meth}" do
135
+ @concrete_class.should_receive("before_#{meth}")
136
+ @concrete_class.generate_report
137
+ end
138
+
139
+ it "should call ##{meth}" do
140
+ @concrete_class.should_receive("#{meth}")
141
+ @concrete_class.generate_report
142
+ end
143
+
144
+ it "should call #after_#{meth}" do
145
+ @concrete_class.should_receive("after_#{meth}")
146
+ @concrete_class.generate_report
147
+ end
148
+ end
149
+
150
+ it "should call #before_to_h" do
151
+ @concrete_class.should_receive("before_to_h")
152
+ @concrete_class.generate_report
153
+ end
154
+
155
+ it "should call #to_h" do
156
+ @concrete_class.should_receive(:to_h)
157
+ @concrete_class.generate_report
158
+ end
159
+
160
+ it "should raise error if the concrete class is missing a required dependency" do
161
+ concrete_class_with_missing_gem = Class.new(MetricFu::Generator) do
162
+ def self.verify_dependencies!
163
+ raise 'gem install something # if you want these tasks'
164
+ end
165
+ end
166
+ lambda { concrete_class_with_missing_gem.generate_report }.should raise_error("gem install something # if you want these tasks")
167
+ end
168
+
169
+ end
170
+
171
+ describe "instantiation" do
172
+ it "should fail is dependencies not verified" do
173
+ ConcreteClass.should_receive(:verify_dependencies!).and_raise("Missing a required gem. Please 'gem install something'")
174
+ lambda { ConcreteClass.new() }.should raise_error("Missing a required gem. Please 'gem install something'")
175
+ end
176
+
177
+ it "should succeed when dependencies verified" do
178
+ ConcreteClass.should_receive(:verify_dependencies!).and_return(true)
179
+ ConcreteClass.new()
180
+ end
181
+ end
182
+
183
+ describe "path filter" do
184
+
185
+ context "given a list of paths" do
186
+
187
+ before do
188
+ @paths = %w(lib/fake/fake.rb
189
+ lib/this/dan_file.rb
190
+ lib/this/ben_file.rb
191
+ lib/this/avdi_file.rb
192
+ basic.rb
193
+ lib/bad/one.rb
194
+ lib/bad/two.rb
195
+ lib/bad/three.rb
196
+ lib/worse/four.rb)
197
+ @container = create_construct
198
+ @paths.each do |path|
199
+ @container.file(path)
200
+ end
201
+ @old_dir = Dir.pwd
202
+ Dir.chdir(@container)
203
+ end
204
+
205
+ after do
206
+ Dir.chdir(@old_dir)
207
+ @container.destroy!
208
+ end
209
+
210
+ it "should return entire pathlist given no exclude pattens" do
211
+ files = @concrete_class.remove_excluded_files(@paths)
212
+ files.should be == @paths
213
+ end
214
+
215
+ it "should filter filename at root level" do
216
+ files = @concrete_class.remove_excluded_files(@paths, ['basic.rb'])
217
+ files.should_not include('basic.rb')
218
+ end
219
+
220
+ it "should remove files that are two levels deep" do
221
+ files = @concrete_class.remove_excluded_files(@paths, ['**/fake.rb'])
222
+ files.should_not include('lib/fake/fake.rb')
223
+ end
224
+
225
+ it "should remove files from an excluded directory" do
226
+ files = @concrete_class.remove_excluded_files(@paths, ['lib/bad/**'])
227
+ files.should_not include('lib/bad/one.rb')
228
+ files.should_not include('lib/bad/two.rb')
229
+ files.should_not include('lib/bad/three.rb')
230
+ end
231
+
232
+ it "should support shell alternation globs" do
233
+ files = @concrete_class.remove_excluded_files(@paths, ['lib/this/{ben,dan}_file.rb'])
234
+ files.should_not include('lib/this/dan_file.rb')
235
+ files.should_not include('lib/this/ben_file.rb')
236
+ files.should include('lib/this/avdi_file.rb')
237
+ end
238
+
239
+ end
240
+
241
+
242
+ end
243
+
244
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe MetricFu do
4
+
5
+ describe "responding to #graph" do
6
+ it "should return an instance of Graph" do
7
+ MetricFu.graph.should be_a(Graph)
8
+ end
9
+ end
10
+ end
11
+
12
+ describe MetricFu::Graph do
13
+
14
+ before(:each) do
15
+ @graph = MetricFu::Graph.new
16
+ end
17
+
18
+ describe "responding to #add with gchart enabled" do
19
+ it 'should instantiate a grapher and push it to clazz' do
20
+ @graph.clazz.should_receive(:push).with(an_instance_of(RcovGchartGrapher))
21
+ @graph.add("rcov", 'gchart')
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe MetricFu::MD5Tracker do
4
+ before do
5
+ @tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
6
+ FileUtils.mkdir_p(@tmp_dir, :verbose => false) unless File.directory?(@tmp_dir)
7
+ @file1 = File.new(File.join(@tmp_dir, 'file1.txt'), 'w')
8
+ @file2 = File.new(File.join(@tmp_dir, 'file2.txt'), 'w')
9
+ end
10
+
11
+ after do
12
+ FileUtils.rm_rf(@tmp_dir, :verbose => false)
13
+ end
14
+
15
+ it "identical files should match" do
16
+ @file1.puts("Hello World")
17
+ @file1.close
18
+ file1_md5 = MD5Tracker.track(@file1.path, @tmp_dir)
19
+
20
+ @file2.puts("Hello World")
21
+ @file2.close
22
+ file2_md5 = MD5Tracker.track(@file2.path, @tmp_dir)
23
+
24
+ file2_md5.should == file1_md5
25
+ end
26
+
27
+ it "different files should not match" do
28
+ @file1.puts("Hello World")
29
+ @file1.close
30
+ file1_md5 = MD5Tracker.track(@file1.path, @tmp_dir)
31
+
32
+ @file2.puts("Goodbye World")
33
+ @file2.close
34
+ file2_md5 = MD5Tracker.track(@file2.path, @tmp_dir)
35
+
36
+ file2_md5.should_not == file1_md5
37
+ end
38
+
39
+ it "file_changed? should detect a change" do
40
+ @file2.close
41
+
42
+ @file1.puts("Hello World")
43
+ @file1.close
44
+ file1_md5 = MD5Tracker.track(@file1.path, @tmp_dir)
45
+
46
+ @file1 = File.new(File.join(@tmp_dir, 'file1.txt'), 'w')
47
+ @file1.puts("Goodbye World")
48
+ @file1.close
49
+ MD5Tracker.file_changed?(@file1.path, @tmp_dir).should be_true
50
+ end
51
+
52
+ it "should detect a new file" do
53
+ @file2.close
54
+ MD5Tracker.file_changed?(@file1.path, @tmp_dir).should be_true
55
+ File.exist?(MD5Tracker.md5_file(@file1.path, @tmp_dir)).should be_true
56
+ end
57
+ end
@@ -0,0 +1,139 @@
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(:write)
38
+ @report.save_templatized_report
39
+ end
40
+ end
41
+
42
+ describe "#add" do
43
+ it 'should add a passed hash to the report_hash instance variable' do
44
+ report_type = mock('report_type')
45
+ report_type.should_receive(:to_s).and_return('type')
46
+ report_type.should_receive(:generate_report).and_return({:a => 'b'})
47
+ MetricFu.should_receive(:const_get).
48
+ with('Type').and_return(report_type)
49
+ report_hash = mock('report_hash')
50
+ report_hash.should_receive(:merge!).with({:a => 'b'})
51
+ @report.should_receive(:report_hash).and_return(report_hash)
52
+ @report.add(report_type)
53
+ end
54
+ end
55
+
56
+ describe "#save_output" do
57
+ it 'should write the passed content to dir/index.html' do
58
+ f = mock('file')
59
+ content = 'content'
60
+ @report.should_receive(:open).with('dir/file', 'w').and_yield(f)
61
+ f.should_receive(:puts).with(content)
62
+ @report.save_output(content, 'dir', 'file')
63
+ end
64
+ end
65
+
66
+ describe '#open_in_browser? ' do
67
+
68
+ before(:each) do
69
+ @config = mock('configuration')
70
+ end
71
+
72
+ describe 'when the platform is os x ' do
73
+
74
+ before(:each) do
75
+ @config.should_receive(:platform).and_return('darwin')
76
+ end
77
+
78
+ describe 'and we are in cruise control ' do
79
+
80
+ before(:each) do
81
+ @config.should_receive(:is_cruise_control_rb?).and_return(true)
82
+ MetricFu.stub!(:configuration).and_return(@config)
83
+ end
84
+
85
+ it 'should return false' do
86
+ @report.open_in_browser?.should be_false
87
+ end
88
+ end
89
+
90
+ describe 'and we are not in cruise control' do
91
+
92
+ before(:each) do
93
+ @config.should_receive(:is_cruise_control_rb?).and_return(false)
94
+ MetricFu.stub!(:configuration).and_return(@config)
95
+ end
96
+
97
+ it 'should return true' do
98
+ @report.open_in_browser?.should be_true
99
+ end
100
+ end
101
+ end
102
+
103
+ describe 'when the platform is not os x ' do
104
+ before(:each) do
105
+ @config.should_receive(:platform).and_return('other')
106
+ end
107
+
108
+ describe 'and we are in cruise control' do
109
+ before(:each) do
110
+ MetricFu.stub!(:configuration).and_return(@config)
111
+ end
112
+
113
+ it 'should return false' do
114
+ @report.open_in_browser?.should be_false
115
+ end
116
+ end
117
+
118
+ describe 'and we are not in cruise control' do
119
+ before(:each) do
120
+ MetricFu.stub!(:configuration).and_return(@config)
121
+ end
122
+
123
+ it 'should return false' do
124
+ @report.open_in_browser?.should be_false
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+
131
+ describe '#show_in_browser' do
132
+ it 'should call open with the passed directory' do
133
+ @report.should_receive(:open_in_browser?).and_return(true)
134
+ @report.should_receive(:system).with("open my_dir/index.html")
135
+ @report.show_in_browser('my_dir')
136
+ end
137
+
138
+ end
139
+ end