yardstick 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +10 -0
- data/LICENSE +20 -0
- data/README.markdown +117 -0
- data/Rakefile +24 -0
- data/VERSION +1 -0
- data/bin/yardstick +7 -0
- data/deps.rip +1 -0
- data/lib/yardstick/autoload.rb +16 -0
- data/lib/yardstick/cli.rb +76 -0
- data/lib/yardstick/core_ext/object.rb +13 -0
- data/lib/yardstick/measurable.rb +78 -0
- data/lib/yardstick/measurement.rb +217 -0
- data/lib/yardstick/measurement_set.rb +130 -0
- data/lib/yardstick/method.rb +111 -0
- data/lib/yardstick/ordered_set.rb +115 -0
- data/lib/yardstick/processor.rb +65 -0
- data/lib/yardstick/rake/measurement.rb +101 -0
- data/lib/yardstick/rake/verify.rb +179 -0
- data/lib/yardstick/rule.rb +61 -0
- data/lib/yardstick/rule_set.rb +18 -0
- data/lib/yardstick/yard_ext.rb +20 -0
- data/lib/yardstick.rb +52 -0
- data/spec/public/yardstick/cli_spec.rb +108 -0
- data/spec/public/yardstick/measurement_set_spec.rb +265 -0
- data/spec/public/yardstick/measurement_spec.rb +256 -0
- data/spec/public/yardstick/method_spec.rb +356 -0
- data/spec/public/yardstick/rake/measurement_spec.rb +173 -0
- data/spec/public/yardstick/rake/verify_spec.rb +229 -0
- data/spec/public/yardstick_spec.rb +70 -0
- data/spec/rcov.opts +6 -0
- data/spec/semipublic/yardstick/rule_spec.rb +28 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +45 -0
- data/tasks/ci.rake +1 -0
- data/tasks/heckle.rake +52 -0
- data/tasks/metrics.rake +5 -0
- data/tasks/rdoc.rake +15 -0
- data/tasks/spec.rake +22 -0
- data/tasks/yardstick.rake +9 -0
- data/yardstick.gemspec +90 -0
- metadata +113 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module Yardstick
|
2
|
+
class Rule
|
3
|
+
|
4
|
+
# Return a Rule instance
|
5
|
+
#
|
6
|
+
# @param [#to_str] description
|
7
|
+
# the description of the Rule
|
8
|
+
#
|
9
|
+
# @yield []
|
10
|
+
# the measurement for the rule
|
11
|
+
#
|
12
|
+
# @return [Rule]
|
13
|
+
# the rule instance
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
def initialize(description, &block)
|
17
|
+
@description = description.to_str
|
18
|
+
@block = block
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return a Measurement for a docstring
|
22
|
+
#
|
23
|
+
# @param [YARD::Docstring] docstring
|
24
|
+
# the docstring to measure
|
25
|
+
#
|
26
|
+
# @return [Measurement]
|
27
|
+
# the measurement
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
def measure(docstring)
|
31
|
+
Measurement.new(@description, docstring, &@block)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Test if Rule is equal to another rule
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# rule == equal_rule # => true
|
38
|
+
#
|
39
|
+
# @param [Rule] other
|
40
|
+
# the other Rule
|
41
|
+
#
|
42
|
+
# @return [Boolean]
|
43
|
+
# true if the Rule is equal to the other, false if not
|
44
|
+
#
|
45
|
+
# @api semipublic
|
46
|
+
def eql?(other)
|
47
|
+
@description.eql?(other.instance_variable_get(:@description))
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return hash identifier for the Rule
|
51
|
+
#
|
52
|
+
# @return [Integer]
|
53
|
+
# the hash identifier
|
54
|
+
#
|
55
|
+
# @api private
|
56
|
+
def hash
|
57
|
+
@description.hash
|
58
|
+
end
|
59
|
+
|
60
|
+
end # class Rule
|
61
|
+
end # module Yardstick
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Yardstick
|
2
|
+
class RuleSet < OrderedSet
|
3
|
+
|
4
|
+
# Measure a docstring with all Rules
|
5
|
+
#
|
6
|
+
# @param [YARD::Docstring] docstring
|
7
|
+
# the docstring to measure
|
8
|
+
#
|
9
|
+
# @return [MeasurementSet]
|
10
|
+
# a collection of measurements
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
def measure(docstring)
|
14
|
+
MeasurementSet.new(map { |rule| rule.measure(docstring) })
|
15
|
+
end
|
16
|
+
|
17
|
+
end # class RuleSet
|
18
|
+
end # module Yardstick
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module YARD #:nodoc: all
|
2
|
+
module CodeObjects
|
3
|
+
class MethodObject
|
4
|
+
|
5
|
+
# Return the docstring associated with the method
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# method_object.docstring # => YARD::Docstring instance
|
9
|
+
#
|
10
|
+
# @return [YARD::Docstring]
|
11
|
+
# the docstring for this method
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def docstring
|
15
|
+
super.extend(Yardstick::Method)
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class MethodObject
|
19
|
+
end # module CodeObjects
|
20
|
+
end # module YARD
|
data/lib/yardstick.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'yard'
|
3
|
+
|
4
|
+
module Yardstick
|
5
|
+
VERSION = '0.1.0'.freeze
|
6
|
+
ROOT = Pathname(__FILE__).dirname.parent.expand_path.freeze
|
7
|
+
|
8
|
+
# Measure a list of files
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# Yardstick.measure('article.rb') # => [ Measurement ]
|
12
|
+
#
|
13
|
+
# @param [Array<#to_s>, #to_s] path
|
14
|
+
# optional list of paths to measure
|
15
|
+
# @param [Hash] options
|
16
|
+
# optional configuration
|
17
|
+
#
|
18
|
+
# @return [MeasurementSet]
|
19
|
+
# the measurements for each file
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def self.measure(path = 'lib/**/*.rb', options = {})
|
23
|
+
Yardstick::Processor.process_path(path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Measure a string of code and YARD documentation
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# string = "def my_method; end"
|
30
|
+
#
|
31
|
+
# Yardstick.measure_string(string) # => [ Measurement ]
|
32
|
+
#
|
33
|
+
# @param [#to_str] string
|
34
|
+
# the string to measure
|
35
|
+
# @param [Hash] options
|
36
|
+
# optional configuration
|
37
|
+
#
|
38
|
+
# @return [MeasurementSet]
|
39
|
+
# the measurements for the string
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def self.measure_string(string, options = {})
|
43
|
+
Yardstick::Processor.process_string(string)
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module Yardstick
|
47
|
+
|
48
|
+
$LOAD_PATH.unshift(Yardstick::ROOT + 'lib')
|
49
|
+
|
50
|
+
require 'yardstick/core_ext/object'
|
51
|
+
require 'yardstick/yard_ext'
|
52
|
+
require 'yardstick/autoload'
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.join('..', '..', 'spec_helper')
|
3
|
+
|
4
|
+
shared_examples_for 'displays help' do
|
5
|
+
it 'should display the help message' do
|
6
|
+
@output.should == <<-OUTPUT.gsub(/^\s{6}/, '')
|
7
|
+
Usage: #{OptionParser.new.program_name} [options]
|
8
|
+
-v, --version print version information and exit
|
9
|
+
-h, --help display this help and exit
|
10
|
+
OUTPUT
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
shared_examples_for 'displays version' do
|
15
|
+
it 'should display the program and version' do
|
16
|
+
@output.should == "#{OptionParser.new.program_name} #{Yardstick::VERSION}\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
shared_examples_for 'displays coverage summary' do
|
21
|
+
it 'should output the coverage summary' do
|
22
|
+
@output.should == "\nCoverage: 100.0% Success: 20 Failed: 0 Total: 20\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Yardstick::CLI do
|
27
|
+
def capture_display(&block)
|
28
|
+
capture_stdout do
|
29
|
+
block.should raise_error(SystemExit)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.run' do
|
34
|
+
describe 'with no arguments' do
|
35
|
+
before do
|
36
|
+
capture_display { Yardstick::CLI.run }
|
37
|
+
end
|
38
|
+
|
39
|
+
it_should_behave_like 'displays help'
|
40
|
+
end
|
41
|
+
|
42
|
+
%w[ -h --help ].each do |help_option|
|
43
|
+
describe "with #{help_option} option" do
|
44
|
+
before do
|
45
|
+
capture_display { Yardstick::CLI.run(help_option) }
|
46
|
+
end
|
47
|
+
|
48
|
+
it_should_behave_like 'displays help'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
%w[ -v --version ].each do |version_option|
|
53
|
+
describe "with #{version_option} option" do
|
54
|
+
before do
|
55
|
+
capture_display { Yardstick::CLI.run(version_option) }
|
56
|
+
end
|
57
|
+
|
58
|
+
it_should_behave_like 'displays version'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'with a String path' do
|
63
|
+
before :all do
|
64
|
+
@measurements = capture_stdout { Yardstick::CLI.run(Yardstick::ROOT.join('lib', 'yardstick.rb').to_s) }
|
65
|
+
end
|
66
|
+
|
67
|
+
it_should_behave_like 'measured itself'
|
68
|
+
it_should_behave_like 'displays coverage summary'
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'with a Pathname' do
|
72
|
+
before :all do
|
73
|
+
@measurements = capture_stdout { Yardstick::CLI.run(Yardstick::ROOT.join('lib', 'yardstick.rb')) }
|
74
|
+
end
|
75
|
+
|
76
|
+
it_should_behave_like 'measured itself'
|
77
|
+
it_should_behave_like 'displays coverage summary'
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'with an Array of String objects' do
|
81
|
+
before :all do
|
82
|
+
@measurements = capture_stdout { Yardstick::CLI.run(*[ Yardstick::ROOT.join('lib', 'yardstick.rb').to_s ]) }
|
83
|
+
end
|
84
|
+
|
85
|
+
it_should_behave_like 'measured itself'
|
86
|
+
it_should_behave_like 'displays coverage summary'
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'with an Array of Pathname objects' do
|
90
|
+
before :all do
|
91
|
+
@measurements = capture_stdout { Yardstick::CLI.run(*[ Yardstick::ROOT.join('lib', 'yardstick.rb') ]) }
|
92
|
+
end
|
93
|
+
|
94
|
+
it_should_behave_like 'measured itself'
|
95
|
+
it_should_behave_like 'displays coverage summary'
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'with invalid option' do
|
99
|
+
before do
|
100
|
+
capture_display { Yardstick::CLI.run('--invalid') }
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should display the invalid option message' do
|
104
|
+
@output.should == "invalid option: --invalid\n"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.join('..', '..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Yardstick::MeasurementSet do
|
5
|
+
before do
|
6
|
+
YARD.parse_string('def test; end')
|
7
|
+
|
8
|
+
@description = 'test measurement'
|
9
|
+
@docstring = YARD::Registry.all(:method).first.docstring
|
10
|
+
|
11
|
+
@measurement = Yardstick::Measurement.new(@description, @docstring) { true }
|
12
|
+
@measurements = Yardstick::MeasurementSet.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should be Enumerable' do
|
16
|
+
Yardstick::MeasurementSet.new.should be_kind_of(Enumerable)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.new' do
|
20
|
+
describe 'with no arguments' do
|
21
|
+
before do
|
22
|
+
@measurements = Yardstick::MeasurementSet.new
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return a MeasurementSet' do
|
26
|
+
@measurements.should be_kind_of(Yardstick::MeasurementSet)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be empty' do
|
30
|
+
@measurements.should be_empty
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'with Measurements' do
|
35
|
+
before do
|
36
|
+
@measurements = Yardstick::MeasurementSet.new([ @measurement ])
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should return a MeasurementSet' do
|
40
|
+
@measurements.should be_kind_of(Yardstick::MeasurementSet)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should include the Measurements' do
|
44
|
+
@measurements.should include(@measurement)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#<<' do
|
50
|
+
describe 'with a new Measurement' do
|
51
|
+
before do
|
52
|
+
@response = @measurements << @measurement
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should return self' do
|
56
|
+
@response.should be_equal(@measurements)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should append the Measurement' do
|
60
|
+
@measurements.to_a.last.should equal(@measurement)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'with an equivalent Measurement' do
|
65
|
+
before do
|
66
|
+
@measurements << @measurement
|
67
|
+
@measurements.to_a.should == [ @measurement ]
|
68
|
+
|
69
|
+
@response = @measurements << Yardstick::Measurement.new(@description, @docstring) { true }
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should return self' do
|
73
|
+
@response.should be_equal(@measurements)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not append the Measurement again' do
|
77
|
+
@measurements.to_a.should == [ @measurement ]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#merge' do
|
83
|
+
before do
|
84
|
+
@other = Yardstick::MeasurementSet.new
|
85
|
+
@other << @measurement
|
86
|
+
|
87
|
+
@response = @measurements.merge(@other)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should return self' do
|
91
|
+
@response.should be_equal(@measurements)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should merge the other Measurements' do
|
95
|
+
@measurements.should include(*@other)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#each' do
|
100
|
+
before do
|
101
|
+
@measurements << @measurement
|
102
|
+
|
103
|
+
@yield = []
|
104
|
+
|
105
|
+
@response = @measurements.each { |*args| @yield << args }
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should return self' do
|
109
|
+
@response.should be_equal(@measurements)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should yield measurements' do
|
113
|
+
@yield.should eql([ [ @measurement ] ])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#empty?' do
|
118
|
+
describe 'when there are no measurements' do
|
119
|
+
it 'should return true' do
|
120
|
+
@measurements.empty?.should be_true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'when there are measurements' do
|
125
|
+
before do
|
126
|
+
@measurements << @measurement
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should return false' do
|
130
|
+
@measurements.empty?.should be_false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#include?' do
|
136
|
+
describe 'when provided an included measurement' do
|
137
|
+
before do
|
138
|
+
@measurements << @measurement
|
139
|
+
|
140
|
+
@response = @measurements.include?(@measurement)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should return true' do
|
144
|
+
@response.should be_true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe 'when provided an excluded measurement' do
|
149
|
+
before do
|
150
|
+
@response = @measurements.include?(@measurement)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should return false' do
|
154
|
+
@response.should be_false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe '#index' do
|
160
|
+
describe 'when provided an included measurement' do
|
161
|
+
before do
|
162
|
+
@measurements << @measurement
|
163
|
+
|
164
|
+
@response = @measurements.index(@measurement)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should return the index' do
|
168
|
+
@response.should eql(0)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe 'when provided an excluded measurement' do
|
173
|
+
before do
|
174
|
+
@response = @measurements.index(@measurement)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should return nil' do
|
178
|
+
@response.should == nil
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '#total' do
|
184
|
+
before do
|
185
|
+
@measurements << @measurement
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should return the number of total measurements' do
|
189
|
+
@measurements.total.should eql(1)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#successful' do
|
194
|
+
before do
|
195
|
+
@measurements << @measurement
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should return the number of successful measurements' do
|
199
|
+
@measurements.successful.should eql(1)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe '#failed' do
|
204
|
+
before do
|
205
|
+
@measurements << @measurement
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should return the number of failed measurements' do
|
209
|
+
@measurements.failed.should eql(0)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe '#coverage' do
|
214
|
+
describe 'when there are no measurements' do
|
215
|
+
it 'should return 0' do
|
216
|
+
@measurements.coverage.should eql(0)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe 'when there are measurements' do
|
221
|
+
before do
|
222
|
+
@response = @measurements << @measurement
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should return a Rational' do
|
226
|
+
@measurements.coverage.should be_kind_of(Rational)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should return the expected value' do
|
230
|
+
@measurements.coverage.should == 1
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe '#puts' do
|
236
|
+
before do
|
237
|
+
@measurements << Yardstick::Measurement.new(@description, @docstring) { false }
|
238
|
+
end
|
239
|
+
|
240
|
+
describe 'with no arguments' do
|
241
|
+
before do
|
242
|
+
capture_stdout { @measurements.puts }
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'should output the summary' do
|
246
|
+
@output.should == "(stdin):1: #test: test measurement\n" \
|
247
|
+
"\nCoverage: 0.0% Success: 0 Failed: 1 Total: 1\n"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe 'with an object implementing #puts' do
|
252
|
+
before do
|
253
|
+
io = StringIO.new
|
254
|
+
@measurements.puts(io)
|
255
|
+
io.rewind
|
256
|
+
@output = io.read
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'should output the summary' do
|
260
|
+
@output.should == "(stdin):1: #test: test measurement\n" \
|
261
|
+
"\nCoverage: 0.0% Success: 0 Failed: 1 Total: 1\n"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|