dkubb-yardstick 0.0.1 → 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.
- data/.document +1 -1
- data/.gitignore +1 -0
- data/README.markdown +69 -0
- data/VERSION +1 -1
- data/lib/yardstick.rb +7 -7
- data/lib/yardstick/autoload.rb +9 -5
- data/lib/yardstick/cli.rb +8 -10
- data/lib/yardstick/measurable.rb +14 -31
- data/lib/yardstick/measurement.rb +38 -0
- data/lib/yardstick/measurement_set.rb +123 -0
- data/lib/yardstick/method.rb +25 -20
- data/lib/yardstick/ordered_set.rb +112 -0
- data/lib/yardstick/processor.rb +22 -24
- data/lib/yardstick/rule.rb +61 -0
- data/lib/yardstick/rule_set.rb +18 -0
- data/spec/public/yardstick/cli_spec.rb +108 -0
- data/spec/public/yardstick/measurement_set_spec.rb +247 -0
- data/spec/public/yardstick/measurement_spec.rb +23 -17
- data/spec/public/yardstick/method_spec.rb +351 -1
- data/spec/public/yardstick_spec.rb +65 -1
- data/spec/rcov.opts +4 -0
- data/spec/semipublic/yardstick/rule_spec.rb +28 -0
- data/spec/spec_helper.rb +45 -7
- data/tasks/ci.rake +1 -0
- data/tasks/heckle.rake +52 -0
- data/tasks/metrics.rake +5 -1
- data/tasks/spec.rake +3 -56
- data/yardstick.gemspec +82 -0
- metadata +17 -4
- data/README.rdoc +0 -16
data/lib/yardstick/method.rb
CHANGED
@@ -2,57 +2,62 @@ module Yardstick
|
|
2
2
|
module Method
|
3
3
|
include Measurable
|
4
4
|
|
5
|
-
|
5
|
+
rule 'The method summary should be specified' do
|
6
6
|
skip if has_tag?('see')
|
7
|
-
|
7
|
+
summary_text != ''
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
rule 'The method summary should be less than 80 characters in length' do
|
11
|
+
summary_text.split(//).length <= 80
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
rule 'The method summary should not end in a period' do
|
15
|
+
summary_text[-1, 1] != '.'
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
rule 'The method summary should be a single line' do
|
19
|
+
!summary_text.include?("\n")
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
skip
|
22
|
+
rule 'The public/semipublic method should have an example specified' do
|
23
|
+
skip if api?(%w[ private ]) || tag_types('return') == %w[ undefined ]
|
24
24
|
has_tag?('example')
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
rule 'The @api tag should be specified' do
|
28
28
|
has_tag?('api')
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
rule 'The @api tag must be either public, semipublic or private' do
|
32
32
|
%w[ public semipublic private ].include?(tag_text('api'))
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
skip unless visibility == :public
|
37
|
-
api?(%w[ public semipublic private ])
|
38
|
-
end
|
39
|
-
|
40
|
-
measurement 'A method with protected visibility must have an @api tag of semipublic or private' do
|
35
|
+
rule 'A method with protected visibility must have an @api tag of semipublic or private' do
|
41
36
|
skip unless visibility == :protected
|
42
37
|
api?(%w[ semipublic private ])
|
43
38
|
end
|
44
39
|
|
45
|
-
|
40
|
+
rule 'A method with private visibility must have an @api tag of private' do
|
46
41
|
skip unless visibility == :private
|
47
42
|
api?(%w[ private ])
|
48
43
|
end
|
49
44
|
|
50
|
-
|
45
|
+
rule 'The @return tag should be specified' do
|
51
46
|
has_tag?('return')
|
52
47
|
end
|
53
48
|
|
54
49
|
private
|
55
50
|
|
51
|
+
# The raw text for the summary
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
# the summary text
|
55
|
+
#
|
56
|
+
# @api private
|
57
|
+
def summary_text
|
58
|
+
split(/\r?\n\r?\n/).first || ''
|
59
|
+
end
|
60
|
+
|
56
61
|
# The text for a specified tag
|
57
62
|
#
|
58
63
|
# @param [String] tag_name
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Yardstick
|
2
|
+
class OrderedSet
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
# Returns the OrderedSet instance
|
6
|
+
#
|
7
|
+
# @param [Array] entries
|
8
|
+
# optional entries
|
9
|
+
#
|
10
|
+
# @return [OrderedSet]
|
11
|
+
# the ordered set instance
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def initialize(entries = nil)
|
15
|
+
@entries = []
|
16
|
+
@index = {}
|
17
|
+
merge(entries) if entries
|
18
|
+
end
|
19
|
+
|
20
|
+
# Append to the OrderedSet
|
21
|
+
#
|
22
|
+
# @param [Object] entry
|
23
|
+
# the object to append
|
24
|
+
#
|
25
|
+
# @return [OrderedSet]
|
26
|
+
# returns self
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def <<(entry)
|
30
|
+
unless include?(entry)
|
31
|
+
@index[entry] = @entries.length
|
32
|
+
@entries << entry
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
# Merge in another OrderedSet
|
38
|
+
#
|
39
|
+
# @param [#each] other
|
40
|
+
# the other ordered set
|
41
|
+
#
|
42
|
+
# @return [OrderedSet]
|
43
|
+
# returns self
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
def merge(other)
|
47
|
+
other.each { |entry| self << entry }
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
# Iterate over each entry
|
52
|
+
#
|
53
|
+
# @yield [entry]
|
54
|
+
# yield to the entry
|
55
|
+
#
|
56
|
+
# @yieldparam [Object] entry
|
57
|
+
# an entry in the ordered set
|
58
|
+
#
|
59
|
+
# @return [OrderedSet]
|
60
|
+
# returns self
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
def each(&block)
|
64
|
+
@entries.each(&block)
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Check if there are any entries
|
69
|
+
#
|
70
|
+
# @return [Boolean]
|
71
|
+
# true if there are no entries, false if there are
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
def empty?
|
75
|
+
@entries.empty?
|
76
|
+
end
|
77
|
+
|
78
|
+
# The number of entries
|
79
|
+
#
|
80
|
+
# @return [Integer]
|
81
|
+
# number of entries
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
def length
|
85
|
+
@entries.length
|
86
|
+
end
|
87
|
+
|
88
|
+
# Check if the entry exists in the set
|
89
|
+
#
|
90
|
+
# @return [Boolean]
|
91
|
+
# true if the entry exists in the set, false if not
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
def include?(entry)
|
95
|
+
@index.key?(entry)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return the index for the entry in the set
|
99
|
+
#
|
100
|
+
# @param [Object] entry
|
101
|
+
# the entry to check the set for
|
102
|
+
#
|
103
|
+
# @return [Integer, nil]
|
104
|
+
# the index for the entry, or nil if it does not exist
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
def index(entry)
|
108
|
+
@index[entry]
|
109
|
+
end
|
110
|
+
|
111
|
+
end # class OrderedSet
|
112
|
+
end # module Yardstick
|
data/lib/yardstick/processor.rb
CHANGED
@@ -3,16 +3,16 @@ module Yardstick
|
|
3
3
|
|
4
4
|
# Measure files provided
|
5
5
|
#
|
6
|
-
# @param [Array<#
|
6
|
+
# @param [Array<#to_s>, #to_s] path
|
7
7
|
# the files to measure
|
8
8
|
#
|
9
|
-
# @return [
|
9
|
+
# @return [MeasurementSet]
|
10
10
|
# a collection of measurements
|
11
11
|
#
|
12
12
|
# @api private
|
13
|
-
def self.
|
14
|
-
YARD.parse(
|
15
|
-
|
13
|
+
def self.process_path(path)
|
14
|
+
YARD.parse(Array(path).map { |file| file.to_s })
|
15
|
+
measurements
|
16
16
|
end
|
17
17
|
|
18
18
|
# Measure string provided
|
@@ -20,13 +20,27 @@ module Yardstick
|
|
20
20
|
# @param [#to_str] string
|
21
21
|
# the string to measure
|
22
22
|
#
|
23
|
-
# @return [
|
23
|
+
# @return [MeasurementSet]
|
24
24
|
# a collection of measurements
|
25
25
|
#
|
26
26
|
# @api private
|
27
27
|
def self.process_string(string)
|
28
28
|
YARD.parse_string(string.to_str)
|
29
|
-
|
29
|
+
measurements
|
30
|
+
end
|
31
|
+
|
32
|
+
# Measure method objects in YARD registry
|
33
|
+
#
|
34
|
+
# @return [MeasurementSet]
|
35
|
+
# a collection of measurements
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
def self.measurements
|
39
|
+
measurements = MeasurementSet.new
|
40
|
+
method_objects.each do |method_object|
|
41
|
+
measurements.merge(method_object.docstring.measure)
|
42
|
+
end
|
43
|
+
measurements
|
30
44
|
end
|
31
45
|
|
32
46
|
# Return method objects in YARD registry
|
@@ -43,24 +57,8 @@ module Yardstick
|
|
43
57
|
YARD::Registry.clear
|
44
58
|
end
|
45
59
|
|
46
|
-
# Measure the method objects provided
|
47
|
-
#
|
48
|
-
# @param [Array<YARD::CodeObjects::MethodObject>] method_objects
|
49
|
-
# a collection of method objects
|
50
|
-
#
|
51
|
-
# @return [Array<Measurement>]
|
52
|
-
# a collection of measurements
|
53
|
-
#
|
54
|
-
# @api private
|
55
|
-
def self.measure_method_objects(method_objects)
|
56
|
-
method_objects.map do |method_object|
|
57
|
-
method_object.docstring.measure
|
58
|
-
end.flatten
|
59
|
-
end
|
60
|
-
|
61
60
|
class << self
|
62
|
-
private :method_objects
|
63
|
-
private :measure_method_objects
|
61
|
+
private :measurements, :method_objects
|
64
62
|
end
|
65
63
|
|
66
64
|
end # class Processor
|
@@ -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,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} 0.0.1\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_stderr { 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_stderr { 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_stderr { 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_stderr { 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
|