yardstick 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.document +5 -0
  2. data/.gitignore +10 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +117 -0
  5. data/Rakefile +24 -0
  6. data/VERSION +1 -0
  7. data/bin/yardstick +7 -0
  8. data/deps.rip +1 -0
  9. data/lib/yardstick/autoload.rb +16 -0
  10. data/lib/yardstick/cli.rb +76 -0
  11. data/lib/yardstick/core_ext/object.rb +13 -0
  12. data/lib/yardstick/measurable.rb +78 -0
  13. data/lib/yardstick/measurement.rb +217 -0
  14. data/lib/yardstick/measurement_set.rb +130 -0
  15. data/lib/yardstick/method.rb +111 -0
  16. data/lib/yardstick/ordered_set.rb +115 -0
  17. data/lib/yardstick/processor.rb +65 -0
  18. data/lib/yardstick/rake/measurement.rb +101 -0
  19. data/lib/yardstick/rake/verify.rb +179 -0
  20. data/lib/yardstick/rule.rb +61 -0
  21. data/lib/yardstick/rule_set.rb +18 -0
  22. data/lib/yardstick/yard_ext.rb +20 -0
  23. data/lib/yardstick.rb +52 -0
  24. data/spec/public/yardstick/cli_spec.rb +108 -0
  25. data/spec/public/yardstick/measurement_set_spec.rb +265 -0
  26. data/spec/public/yardstick/measurement_spec.rb +256 -0
  27. data/spec/public/yardstick/method_spec.rb +356 -0
  28. data/spec/public/yardstick/rake/measurement_spec.rb +173 -0
  29. data/spec/public/yardstick/rake/verify_spec.rb +229 -0
  30. data/spec/public/yardstick_spec.rb +70 -0
  31. data/spec/rcov.opts +6 -0
  32. data/spec/semipublic/yardstick/rule_spec.rb +28 -0
  33. data/spec/spec.opts +4 -0
  34. data/spec/spec_helper.rb +45 -0
  35. data/tasks/ci.rake +1 -0
  36. data/tasks/heckle.rake +52 -0
  37. data/tasks/metrics.rake +5 -0
  38. data/tasks/rdoc.rake +15 -0
  39. data/tasks/spec.rake +22 -0
  40. data/tasks/yardstick.rake +9 -0
  41. data/yardstick.gemspec +90 -0
  42. metadata +113 -0
@@ -0,0 +1,256 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.join('..', '..', 'spec_helper')
3
+
4
+ shared_examples_for 'measurement is successful' do
5
+ before do
6
+ @measurement = Yardstick::Measurement.new('successful', @docstring) { true }
7
+ end
8
+ end
9
+
10
+ shared_examples_for 'measurement is skipped' do
11
+ before do
12
+ @measurement = Yardstick::Measurement.new('skipped', @docstring) { skip }
13
+ end
14
+ end
15
+
16
+ shared_examples_for 'measurement is not successful' do
17
+ before do
18
+ @measurement = Yardstick::Measurement.new('not successful', @docstring) { false }
19
+ end
20
+ end
21
+
22
+ shared_examples_for 'measurement is not implemented' do
23
+ before do
24
+ @measurement = Yardstick::Measurement.new('not implemented', @docstring) { todo }
25
+ end
26
+ end
27
+
28
+ shared_examples_for 'measurement is displayed' do
29
+ before do
30
+ capture_stdout { @measurement.puts }
31
+ end
32
+ end
33
+
34
+ shared_examples_for 'measurement is sent to object' do
35
+ before do
36
+ io = StringIO.new
37
+ @measurement.puts(io)
38
+ io.rewind
39
+ @output = io.read
40
+ end
41
+ end
42
+
43
+ describe Yardstick::Measurement do
44
+ before do
45
+ YARD.parse_string(<<-RUBY)
46
+ class MeasurementTest
47
+ def test
48
+ end
49
+ end
50
+ RUBY
51
+
52
+ @docstring = YARD::Registry.all(:method).first.docstring
53
+ end
54
+
55
+ describe '.new' do
56
+ before do
57
+ @measurement = Yardstick::Measurement.new('test measurement', @docstring) { true }
58
+ end
59
+
60
+ it 'should return a Measurement' do
61
+ @measurement.should be_kind_of(Yardstick::Measurement)
62
+ end
63
+ end
64
+
65
+ describe '#description' do
66
+ before do
67
+ @description = 'test measurement'
68
+
69
+ @measurement = Yardstick::Measurement.new(@description, @docstring) { true }
70
+ end
71
+
72
+ it 'should return the expected description' do
73
+ @measurement.description.should equal(@description)
74
+ end
75
+ end
76
+
77
+ describe '#ok?' do
78
+ describe 'when the measurement is successful' do
79
+ it_should_behave_like 'measurement is successful'
80
+
81
+ it 'should return true' do
82
+ @measurement.ok?.should be_true
83
+ end
84
+ end
85
+
86
+ describe 'when the measurement is skipped' do
87
+ it_should_behave_like 'measurement is skipped'
88
+
89
+ it 'should return true' do
90
+ @measurement.ok?.should be_true
91
+ end
92
+ end
93
+
94
+ describe 'when the measurement is not successful' do
95
+ it_should_behave_like 'measurement is not successful'
96
+
97
+ it 'should return false' do
98
+ @measurement.ok?.should be_false
99
+ end
100
+ end
101
+
102
+ describe 'when the measurement is not implemented' do
103
+ it_should_behave_like 'measurement is not implemented'
104
+
105
+ it 'should return false' do
106
+ @measurement.ok?.should be_false
107
+ end
108
+ end
109
+ end
110
+
111
+ describe '#skip?' do
112
+ describe 'when the measurement is successful' do
113
+ it_should_behave_like 'measurement is successful'
114
+
115
+ it 'should return false' do
116
+ @measurement.skip?.should be_false
117
+ end
118
+ end
119
+
120
+ describe 'when the measurement is skipped' do
121
+ it_should_behave_like 'measurement is skipped'
122
+
123
+ it 'should return true' do
124
+ @measurement.skip?.should be_true
125
+ end
126
+ end
127
+
128
+ describe 'when the measurement is not successful' do
129
+ it_should_behave_like 'measurement is not successful'
130
+
131
+ it 'should return false' do
132
+ @measurement.skip?.should be_false
133
+ end
134
+ end
135
+
136
+ describe 'when the measurement is not implemented' do
137
+ it_should_behave_like 'measurement is not implemented'
138
+
139
+ it 'should return false' do
140
+ @measurement.skip?.should be_false
141
+ end
142
+ end
143
+ end
144
+
145
+ describe '#todo?' do
146
+ describe 'when the measurement is successful' do
147
+ it_should_behave_like 'measurement is successful'
148
+
149
+ it 'should return false' do
150
+ @measurement.todo?.should be_false
151
+ end
152
+ end
153
+
154
+ describe 'when the measurement is skipped' do
155
+ it_should_behave_like 'measurement is skipped'
156
+
157
+ it 'should return false' do
158
+ @measurement.todo?.should be_false
159
+ end
160
+ end
161
+
162
+ describe 'when the measurement is not successful' do
163
+ it_should_behave_like 'measurement is not successful'
164
+
165
+ it 'should return false' do
166
+ @measurement.todo?.should be_false
167
+ end
168
+ end
169
+
170
+ describe 'when the measurement is not implemented' do
171
+ it_should_behave_like 'measurement is not implemented'
172
+
173
+ it 'should return true' do
174
+ @measurement.todo?.should be_true
175
+ end
176
+ end
177
+ end
178
+
179
+ describe '#puts' do
180
+ describe 'with no arguments' do
181
+ describe 'when the measurement is successful' do
182
+ it_should_behave_like 'measurement is successful'
183
+ it_should_behave_like 'measurement is displayed'
184
+
185
+ it 'should not display any output' do
186
+ @output.should == ''
187
+ end
188
+ end
189
+
190
+ describe 'when the measurement is skipped' do
191
+ it_should_behave_like 'measurement is skipped'
192
+ it_should_behave_like 'measurement is displayed'
193
+
194
+ it 'should not display any output' do
195
+ @output.should == ''
196
+ end
197
+ end
198
+
199
+ describe 'when the measurement is not successful' do
200
+ it_should_behave_like 'measurement is not successful'
201
+ it_should_behave_like 'measurement is displayed'
202
+
203
+ it 'should display output' do
204
+ @output.should == "(stdin):2: MeasurementTest#test: not successful\n"
205
+ end
206
+ end
207
+
208
+ describe 'when the measurement is not implemented' do
209
+ it_should_behave_like 'measurement is not implemented'
210
+ it_should_behave_like 'measurement is displayed'
211
+
212
+ it 'should display output' do
213
+ @output.should == "(stdin):2: MeasurementTest#test: not implemented\n"
214
+ end
215
+ end
216
+ end
217
+
218
+ describe 'with an object implementing #puts' do
219
+ describe 'when the measurement is successful' do
220
+ it_should_behave_like 'measurement is successful'
221
+ it_should_behave_like 'measurement is sent to object'
222
+
223
+ it 'should not display any output' do
224
+ @output.should == ''
225
+ end
226
+ end
227
+
228
+ describe 'when the measurement is skipped' do
229
+ it_should_behave_like 'measurement is skipped'
230
+ it_should_behave_like 'measurement is sent to object'
231
+
232
+ it 'should not display any output' do
233
+ @output.should == ''
234
+ end
235
+ end
236
+
237
+ describe 'when the measurement is not successful' do
238
+ it_should_behave_like 'measurement is not successful'
239
+ it_should_behave_like 'measurement is sent to object'
240
+
241
+ it 'should display output' do
242
+ @output.should == "(stdin):2: MeasurementTest#test: not successful\n"
243
+ end
244
+ end
245
+
246
+ describe 'when the measurement is not implemented' do
247
+ it_should_behave_like 'measurement is not implemented'
248
+ it_should_behave_like 'measurement is sent to object'
249
+
250
+ it 'should display output' do
251
+ @output.should == "(stdin):2: MeasurementTest#test: not implemented\n"
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,356 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.join('..', '..', 'spec_helper')
3
+
4
+ shared_examples_for 'method is measured' do
5
+ before do
6
+ @measurements = docstring.measure
7
+ end
8
+
9
+ it 'should return a MeasurementSet' do
10
+ @measurements.should be_kind_of(Yardstick::MeasurementSet)
11
+ end
12
+ end
13
+
14
+ shared_examples_for 'a valid method' do
15
+ before do
16
+ YARD.parse_string(<<-RUBY)
17
+ # This is a method summary that is the maximum --- exactly 80 characters in length
18
+ #
19
+ # @example
20
+ # test('Hello World') # => nil
21
+ #
22
+ # @param [#to_str] value
23
+ # the value
24
+ #
25
+ # @return [nil]
26
+ # returns nil
27
+ #
28
+ # @api public
29
+ def test(value)
30
+ end
31
+ RUBY
32
+ end
33
+ end
34
+
35
+ describe Yardstick::Method do
36
+ def docstring
37
+ YARD::Registry.all(:method).first.docstring
38
+ end
39
+
40
+ describe '#measure' do
41
+ describe 'with a method summary' do
42
+ it_should_behave_like 'a valid method'
43
+ it_should_behave_like 'method is measured'
44
+
45
+ it 'should have a correct measurement' do
46
+ @measurements.detect { |measurement| measurement.description == 'The method summary should be specified' }.should be_ok
47
+ end
48
+ end
49
+
50
+ describe 'without a method summary' do
51
+ before do
52
+ YARD.parse_string('def test(value); end')
53
+ end
54
+
55
+ it_should_behave_like 'method is measured'
56
+
57
+ it 'should have an incorrect measurement' do
58
+ @measurements.detect { |measurement| measurement.description == 'The method summary should be specified' }.should_not be_ok
59
+ end
60
+ end
61
+
62
+ describe 'with a method summary that is 80 characters in length' do
63
+ it_should_behave_like 'a valid method'
64
+ it_should_behave_like 'method is measured'
65
+
66
+ it 'should have a correct measurement' do
67
+ @measurements.detect { |measurement| measurement.description == 'The method summary should be less than 80 characters in length' }.should be_ok
68
+ end
69
+ end
70
+
71
+ describe 'with a method summary that is 81 characters in length' do
72
+ before do
73
+ YARD.parse_string(<<-RUBY)
74
+ # This is a method summary greater than the maximum - it is 81 characters in length
75
+ def test(value)
76
+ end
77
+ RUBY
78
+ end
79
+
80
+ it_should_behave_like 'method is measured'
81
+
82
+ it 'should have an incorrect measurement' do
83
+ @measurements.detect { |measurement| measurement.description == 'The method summary should be less than 80 characters in length' }.should_not be_ok
84
+ end
85
+ end
86
+
87
+ describe 'with a method summary that does not end in a period' do
88
+ it_should_behave_like 'a valid method'
89
+ it_should_behave_like 'method is measured'
90
+
91
+ it 'should have a correct measurement' do
92
+ @measurements.detect { |measurement| measurement.description == 'The method summary should not end in a period' }.should be_ok
93
+ end
94
+ end
95
+
96
+ describe 'with a method summary that does end in a period' do
97
+ before do
98
+ YARD.parse_string(<<-RUBY)
99
+ # This method summary ends in a period.
100
+ def test(value)
101
+ end
102
+ RUBY
103
+ end
104
+
105
+ it_should_behave_like 'method is measured'
106
+
107
+ it 'should have an incorrect measurement' do
108
+ @measurements.detect { |measurement| measurement.description == 'The method summary should not end in a period' }.should_not be_ok
109
+ end
110
+ end
111
+
112
+ describe 'with a method summary that is on one line' do
113
+ it_should_behave_like 'a valid method'
114
+ it_should_behave_like 'method is measured'
115
+
116
+ it 'should have a correct measurement' do
117
+ @measurements.detect { |measurement| measurement.description == 'The method summary should be a single line' }.should be_ok
118
+ end
119
+ end
120
+
121
+ describe 'with a method summary that is not on one line' do
122
+ before do
123
+ YARD.parse_string(<<-RUBY)
124
+ # This method summary
125
+ # is on two lines
126
+ def test(value)
127
+ end
128
+ RUBY
129
+ end
130
+
131
+ it_should_behave_like 'method is measured'
132
+
133
+ it 'should have an incorrect measurement' do
134
+ @measurements.detect { |measurement| measurement.description == 'The method summary should be a single line' }.should_not be_ok
135
+ end
136
+ end
137
+
138
+ describe 'with a method that has an @example tag' do
139
+ it_should_behave_like 'a valid method'
140
+ it_should_behave_like 'method is measured'
141
+
142
+ it 'should have a correct measurement' do
143
+ @measurements.detect { |measurement| measurement.description == 'The public/semipublic method should have an example specified' }.should be_ok
144
+ end
145
+ end
146
+
147
+ describe 'with a method that is private' do
148
+ before do
149
+ YARD.parse_string(<<-RUBY)
150
+ # @api private
151
+ def test(value)
152
+ end
153
+ RUBY
154
+ end
155
+
156
+ it_should_behave_like 'method is measured'
157
+
158
+ it 'should be skipped' do
159
+ @measurements.detect { |measurement| measurement.description == 'The public/semipublic method should have an example specified' }.should be_skip
160
+ end
161
+ end
162
+
163
+ describe 'with a method that does not have an @example tag, and has an undefined @return tag' do
164
+ before do
165
+ YARD.parse_string(<<-RUBY)
166
+ # @return [undefined]
167
+ #
168
+ # @api public
169
+ def test(value)
170
+ end
171
+ RUBY
172
+ end
173
+
174
+ it_should_behave_like 'method is measured'
175
+
176
+ it 'should be skipped' do
177
+ @measurements.detect { |measurement| measurement.description == 'The public/semipublic method should have an example specified' }.should be_skip
178
+ end
179
+ end
180
+
181
+ describe 'with a method that has an @api tag' do
182
+ it_should_behave_like 'a valid method'
183
+ it_should_behave_like 'method is measured'
184
+
185
+ it 'should have a correct measurement' do
186
+ @measurements.detect { |measurement| measurement.description == 'The @api tag should be specified' }.should be_ok
187
+ end
188
+ end
189
+
190
+ describe 'with a method that does not have an @api tag' do
191
+ before do
192
+ YARD.parse_string('def test(value); end')
193
+ end
194
+
195
+ it_should_behave_like 'method is measured'
196
+
197
+ it 'should have an incorrect measurement' do
198
+ @measurements.detect { |measurement| measurement.description == 'The @api tag should be specified' }.should_not be_ok
199
+ end
200
+ end
201
+
202
+ describe 'with a method that has a public @api tag' do
203
+ it_should_behave_like 'a valid method'
204
+ it_should_behave_like 'method is measured'
205
+
206
+ it 'should have a correct measurement' do
207
+ @measurements.detect { |measurement| measurement.description == 'The @api tag must be either public, semipublic or private' }.should be_ok
208
+ end
209
+ end
210
+
211
+ describe 'with a method that has an invalid @api tag' do
212
+ before do
213
+ YARD.parse_string(<<-RUBY)
214
+ # @api invalid
215
+ def test(value)
216
+ end
217
+ RUBY
218
+ end
219
+
220
+ it_should_behave_like 'method is measured'
221
+
222
+ it 'should have an incorrect measurement' do
223
+ @measurements.detect { |measurement| measurement.description == 'The @api tag must be either public, semipublic or private' }.should_not be_ok
224
+ end
225
+ end
226
+
227
+ describe 'with a protected method and a semipublic @api tag' do
228
+ before do
229
+ YARD.parse_string(<<-RUBY)
230
+ protected
231
+
232
+ # @api semipublic
233
+ def test(value)
234
+ end
235
+ RUBY
236
+ end
237
+
238
+ it_should_behave_like 'method is measured'
239
+
240
+ it 'should have a correct measurement' do
241
+ @measurements.detect { |measurement| measurement.description == 'A method with protected visibility must have an @api tag of semipublic or private' }.should be_ok
242
+ end
243
+ end
244
+
245
+ describe 'with a protected method and a private @api tag' do
246
+ before do
247
+ YARD.parse_string(<<-RUBY)
248
+ protected
249
+
250
+ # @api private
251
+ def test(value)
252
+ end
253
+ RUBY
254
+ end
255
+
256
+ it_should_behave_like 'method is measured'
257
+
258
+ it 'should have a correct measurement' do
259
+ @measurements.detect { |measurement| measurement.description == 'A method with protected visibility must have an @api tag of semipublic or private' }.should be_ok
260
+ end
261
+ end
262
+
263
+ describe 'with a protected method and a public @api tag' do
264
+ before do
265
+ YARD.parse_string(<<-RUBY)
266
+ protected
267
+
268
+ # @api public
269
+ def test(value)
270
+ end
271
+ RUBY
272
+ end
273
+
274
+ it_should_behave_like 'method is measured'
275
+
276
+ it 'should have an incorrect measurement' do
277
+ @measurements.detect { |measurement| measurement.description == 'A method with protected visibility must have an @api tag of semipublic or private' }.should_not be_ok
278
+ end
279
+ end
280
+
281
+ describe 'with a private method and a private @api tag' do
282
+ before do
283
+ YARD.parse_string(<<-RUBY)
284
+ private
285
+
286
+ # @api private
287
+ def test(value)
288
+ end
289
+ RUBY
290
+ end
291
+
292
+ it_should_behave_like 'method is measured'
293
+
294
+ it 'should have a correct measurement' do
295
+ @measurements.detect { |measurement| measurement.description == 'A method with private visibility must have an @api tag of private' }.should be_ok
296
+ end
297
+ end
298
+
299
+ describe 'with a private method and a public @api tag' do
300
+ before do
301
+ YARD.parse_string(<<-RUBY)
302
+ private
303
+
304
+ # @api public
305
+ def test(value)
306
+ end
307
+ RUBY
308
+ end
309
+
310
+ it_should_behave_like 'method is measured'
311
+
312
+ it 'should have an incorrect measurement' do
313
+ @measurements.detect { |measurement| measurement.description == 'A method with private visibility must have an @api tag of private' }.should_not be_ok
314
+ end
315
+ end
316
+
317
+ describe 'with a private method and a semipublic @api tag' do
318
+ before do
319
+ YARD.parse_string(<<-RUBY)
320
+ private
321
+
322
+ # @api semipublic
323
+ def test(value)
324
+ end
325
+ RUBY
326
+ end
327
+
328
+ it_should_behave_like 'method is measured'
329
+
330
+ it 'should have an incorrect measurement' do
331
+ @measurements.detect { |measurement| measurement.description == 'A method with private visibility must have an @api tag of private' }.should_not be_ok
332
+ end
333
+ end
334
+
335
+ describe 'with a method that has a @return tag' do
336
+ it_should_behave_like 'a valid method'
337
+ it_should_behave_like 'method is measured'
338
+
339
+ it 'should have a correct measurement' do
340
+ @measurements.detect { |measurement| measurement.description == 'The @return tag should be specified' }.should be_ok
341
+ end
342
+ end
343
+
344
+ describe 'with a method that does not have a @return tag' do
345
+ before do
346
+ YARD.parse_string('def test(value); end')
347
+ end
348
+
349
+ it_should_behave_like 'method is measured'
350
+
351
+ it 'should have an incorrect measurement' do
352
+ @measurements.detect { |measurement| measurement.description == 'The @return tag should be specified' }.should_not be_ok
353
+ end
354
+ end
355
+ end
356
+ end