yardstick 0.1.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 (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