dkubb-yardstick 0.0.1

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 ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.sw?
2
+ .DS_Store
3
+ .yardoc
4
+ coverage
5
+ rdoc
6
+ doc
7
+ pkg
8
+ tmp
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Dan Kubb
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,16 @@
1
+ = yardstick
2
+
3
+ Yardstick is a tool that verifies YARD coverage of ruby code.
4
+
5
+ It will measure the source and provide feedback on what is missing from
6
+ the documentation and what can be improved.
7
+
8
+ == Usage
9
+
10
+ From the command-line:
11
+
12
+ yardstick lib/**/*.rb
13
+
14
+ == Copyright
15
+
16
+ Copyright (c) 2009 Dan Kubb. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'pathname'
4
+
5
+ Pathname.glob('tasks/**/*.rake').each { |task| load task.expand_path }
6
+
7
+ begin
8
+ require 'jeweler'
9
+
10
+ Jeweler::Tasks.new do |gem|
11
+ gem.name = 'yardstick'
12
+ gem.summary = 'A tool for verifying YARD documentation coverage'
13
+ gem.email = 'dan.kubb@gmail.com'
14
+ gem.homepage = 'http://github.com/dkubb/yardstick'
15
+ gem.authors = [ 'Dan Kubb' ]
16
+ gem.rubyforge_project = 'yardstick'
17
+
18
+ gem.add_dependency('yard', '~>0.2')
19
+ end
20
+
21
+ Jeweler::RubyforgeTasks.new
22
+ rescue LoadError
23
+ puts 'Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler'
24
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/yardstick ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby -KU
2
+
3
+ require 'rubygems'
4
+ require 'pathname'
5
+ require Pathname(__FILE__).dirname.expand_path.parent.join('lib', 'yardstick')
6
+
7
+ Yardstick::CLI.run(*ARGV)
@@ -0,0 +1,7 @@
1
+ module Yardstick
2
+ autoload :CLI, 'yardstick/cli'
3
+ autoload :Measurable, 'yardstick/measurable'
4
+ autoload :Measurement, 'yardstick/measurement'
5
+ autoload :Method, 'yardstick/method'
6
+ autoload :Processor, 'yardstick/processor'
7
+ end # module Yardstick
@@ -0,0 +1,78 @@
1
+ require 'optparse'
2
+
3
+ module Yardstick
4
+ class CLI
5
+
6
+ # Parse the command line options, and run the command
7
+ #
8
+ # @example
9
+ # Yardstick::CLI.run(%w[ article.rb ]) # => [ Measurement ]
10
+ #
11
+ # @param [Array] *args
12
+ # arguments passed in from the command line
13
+ #
14
+ # @return [Array(Measurement)]
15
+ # the measurement for each file
16
+ #
17
+ # @api private
18
+ def self.run(*args)
19
+ Yardstick.measure(*parse_options(args)).each do |measurement|
20
+ measurement.warn
21
+ end
22
+ end
23
+
24
+ # Parse the options provided from the command-line
25
+ #
26
+ # @param [Array<String>] args
27
+ # the command-line options
28
+ #
29
+ # @return [Array(Array<String>, Hash)]
30
+ # the list of files, and options parsed from the command-line
31
+ #
32
+ # @api private
33
+ def self.parse_options(args)
34
+ args << '--help' if args.empty?
35
+ options = {}
36
+ option_parser(options).parse!(args)
37
+ [ args, options ]
38
+ rescue OptionParser::InvalidOption => error
39
+ display_exit(error.message << "\n" << args.inspect)
40
+ end
41
+
42
+ # Return an OptionParser instance for the command-line app
43
+ #
44
+ # @param [Hash] options
45
+ # the options to set when parsing the command-line arguments
46
+ #
47
+ # @return [OptionParser]
48
+ # the option parser instance
49
+ #
50
+ # @api private
51
+ def self.option_parser(options)
52
+ opts = OptionParser.new
53
+ opts.on_tail('-v', '--version', 'print version information and exit') { display_exit("#{opts.program_name} #{Yardstick::VERSION}") }
54
+ opts.on_tail('-h', '--help', 'display this help and exit') { display_exit(opts) }
55
+ opts
56
+ end
57
+
58
+ # Display a message and exit
59
+ #
60
+ # @param [#to_str] message
61
+ # the message to display
62
+ #
63
+ # @return [undefined]
64
+ #
65
+ # @api private
66
+ def self.display_exit(message)
67
+ puts message.to_str
68
+ exit
69
+ end
70
+
71
+ class << self
72
+ private :option_parser
73
+ private :parse_options
74
+ private :display_exit
75
+ end
76
+
77
+ end # module CLI
78
+ end # module Yardstick
@@ -0,0 +1,13 @@
1
+ class Object #:nodoc:
2
+
3
+ # Return the meta class for this instance
4
+ #
5
+ # @return [Class]
6
+ # the meta class
7
+ #
8
+ # @api private
9
+ def meta_class
10
+ class << self; self end
11
+ end
12
+
13
+ end # class Object
@@ -0,0 +1,95 @@
1
+ module Yardstick
2
+ module Measurable
3
+ include Measurement::UtilityMethods
4
+
5
+ module ClassMethods
6
+
7
+ # List of measurement types for this class
8
+ #
9
+ # @return [Array<Array(String, Symbol)>]
10
+ # the measurements for this class
11
+ #
12
+ # @api private
13
+ def measurements
14
+ @measurements ||= []
15
+ end
16
+
17
+ # Set the description for the measurement
18
+ #
19
+ # @param [#to_str] description
20
+ # the measurement description
21
+ #
22
+ # @yield []
23
+ # the measurement to perform
24
+ #
25
+ # @yieldreturn [Boolean]
26
+ # return true if successful, false if not
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ # @api private
31
+ def measurement(description, &block)
32
+ measurements << [ description, block ]
33
+ end
34
+
35
+ private
36
+
37
+ # Include the class or module with measurable class methods
38
+ #
39
+ # @param [Module] mod
40
+ # the module to include within
41
+ #
42
+ # @return [undefined]
43
+ #
44
+ # @api private
45
+ def included(mod)
46
+ mod.extend(ClassMethods)
47
+ copy_measurements(mod)
48
+ end
49
+
50
+ # Extend the docstring meta class with measurable class methods
51
+ #
52
+ # @param [YARD::Docstring] docstring
53
+ # the docstring to extend
54
+ #
55
+ # @return [undefined]
56
+ #
57
+ # @api private
58
+ def extended(docstring)
59
+ meta_class = docstring.meta_class
60
+ meta_class.extend(ClassMethods)
61
+ copy_measurements(meta_class)
62
+ end
63
+
64
+ # Copy measurements from the ancestor to the descendant
65
+ #
66
+ # @param [Module] descendant
67
+ # the descendant module or class
68
+ #
69
+ # @return [undefined]
70
+ #
71
+ # @api private
72
+ def copy_measurements(descendant)
73
+ descendant.measurements.concat(measurements).uniq!
74
+ end
75
+ end # module ClassMethods
76
+
77
+ extend ClassMethods
78
+
79
+ # Return a list of measurements for this docstring instance
80
+ #
81
+ # @example
82
+ # docstring.measure # => [ Measurement ]
83
+ #
84
+ # @return [Array<Measurement>]
85
+ # a collection of measurements
86
+ #
87
+ # @api public
88
+ def measure
89
+ meta_class.measurements.map do |(description, block)|
90
+ Measurement.new(description, self, &block)
91
+ end
92
+ end
93
+
94
+ end # module Measurable
95
+ end # module Yardstick
@@ -0,0 +1,176 @@
1
+ module Yardstick
2
+ class Measurement
3
+
4
+ # Return a Measurement instance
5
+ #
6
+ # @example
7
+ # measurement = Measurement.new('The description', docstring, :successful_method)
8
+ #
9
+ # @param [#to_str] description
10
+ # the measurement description
11
+ # @param [YARD::Docstring] docstring
12
+ # the docstring to measure
13
+ #
14
+ # @yield []
15
+ # the measurement to perform
16
+ #
17
+ # @return [Yardstick::Measurement]
18
+ # the measurement instance
19
+ #
20
+ # @api public
21
+ def initialize(description, docstring, &block)
22
+ @description = description.to_str
23
+ @docstring = docstring
24
+ @block = block
25
+ @result = measure
26
+ end
27
+
28
+ # Return true if the measurement was successful
29
+ #
30
+ # @example Measurement successful
31
+ # measurement.ok? # => true
32
+ #
33
+ # @example Measurement unsuccessful
34
+ # measurement.ok? # => false
35
+ #
36
+ # @return [Boolean]
37
+ # true if the measurement was successful, false if not
38
+ #
39
+ # @api public
40
+ def ok?
41
+ @result == true || skip?
42
+ end
43
+
44
+ # Return true if the measurement was skipped
45
+ #
46
+ # @example Measurement skipped
47
+ # measurement.skip? # => true
48
+ #
49
+ # @example Measurement not skipped
50
+ # measurement.skip? # => false
51
+ #
52
+ # @return [Boolean]
53
+ # true if the measurement was skipped, false if not
54
+ #
55
+ # @api public
56
+ def skip?
57
+ @result == :skip
58
+ end
59
+
60
+ # Return true if the measurement is not implemented
61
+ #
62
+ # @example Measurement not implemented
63
+ # measurement.todo? # => true
64
+ #
65
+ # @example Measurement implemented
66
+ # measurement.todo? # => false
67
+ #
68
+ # @return [Boolean]
69
+ # true if the measurement is not implemented, false if not
70
+ #
71
+ # @api public
72
+ def todo?
73
+ @result == :todo
74
+ end
75
+
76
+ # Warns the results the measurement if it was not successful
77
+ #
78
+ # @example
79
+ # measurement.warn # (outputs results if not successful)
80
+ #
81
+ # @return [undefined]
82
+ #
83
+ # @api public
84
+ def warn
85
+ unless ok?
86
+ Kernel.warn("#{file}:#{line}: #{path}: #{@description}")
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ # Measure the docstring using the method provided to the constructor
93
+ #
94
+ # @return [Boolean, Symbol]
95
+ # true if the test is successful, false if not
96
+ # :todo if the test is not implemented
97
+ # :skip if the test does not apply
98
+ #
99
+ # @api private
100
+ def measure
101
+ catch :measurement do
102
+ @docstring.instance_eval(&@block)
103
+ end
104
+ end
105
+
106
+ # The code object for the docstring
107
+ #
108
+ # @return [YARD::CodeObjects::Base]
109
+ # the code object
110
+ #
111
+ # @api private
112
+ def object
113
+ @docstring.object
114
+ end
115
+
116
+ # The filename for the code
117
+ #
118
+ # @return [Pathname]
119
+ # the filename
120
+ #
121
+ # @api private
122
+ def file
123
+ Pathname(object.file)
124
+ end
125
+
126
+ # The line number for the code
127
+ #
128
+ # @return [Integer]
129
+ # the line number
130
+ #
131
+ # @api private
132
+ def line
133
+ object.line
134
+ end
135
+
136
+ # The class and method name for the code
137
+ #
138
+ # @return [String]
139
+ # the class and method name
140
+ #
141
+ # @api private
142
+ def path
143
+ object.path.sub(/\A::/, '')
144
+ end
145
+
146
+ module UtilityMethods #:nodoc:
147
+ private
148
+
149
+ # Throw a :skip measurement message to the caller
150
+ #
151
+ # This method allows you to short-circuit measurement methods when
152
+ # the measurement does not apply due to specific object states.
153
+ #
154
+ # @return [undefined]
155
+ #
156
+ # @api private
157
+ def skip
158
+ throw :measurement, :skip
159
+ end
160
+
161
+ # Throw a :todo measurement message to the caller
162
+ #
163
+ # This method allows you to short-circuit measurement methods when
164
+ # the measurement is not implemented.
165
+ #
166
+ # @return [undefined]
167
+ #
168
+ # @api private
169
+ def todo
170
+ throw :measurement, :todo
171
+ end
172
+
173
+ end # module UtilityMethods
174
+
175
+ end # class Measurement
176
+ end # module Yardstick
@@ -0,0 +1,106 @@
1
+ module Yardstick
2
+ module Method
3
+ include Measurable
4
+
5
+ measurement 'The method summary should be specified' do
6
+ skip if has_tag?('see')
7
+ summary != ''
8
+ end
9
+
10
+ measurement 'The method summary should be less than 80 characters in length' do
11
+ summary.length <= 78
12
+ end
13
+
14
+ measurement 'The method summary should be a single line' do
15
+ !summary.include?("\n")
16
+ end
17
+
18
+ measurement 'The method summary should not end in a period' do
19
+ summary[0, -1] != '.'
20
+ end
21
+
22
+ measurement 'The public/semipublic method should have an example specified' do
23
+ skip unless api?(%w[ public semipublic ]) && tag_types('return') != %w[ undefined ]
24
+ has_tag?('example')
25
+ end
26
+
27
+ measurement 'The @api tag should be specified' do
28
+ has_tag?('api')
29
+ end
30
+
31
+ measurement 'The @api tag must be either public, semipublic or private' do
32
+ %w[ public semipublic private ].include?(tag_text('api'))
33
+ end
34
+
35
+ measurement 'A method with public visibility must have an @api tag of public, semipublic or private' do
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
41
+ skip unless visibility == :protected
42
+ api?(%w[ semipublic private ])
43
+ end
44
+
45
+ measurement 'A method with private visibility must have an @api tag of private' do
46
+ skip unless visibility == :private
47
+ api?(%w[ private ])
48
+ end
49
+
50
+ measurement 'The @return tag should be specified' do
51
+ has_tag?('return')
52
+ end
53
+
54
+ private
55
+
56
+ # The text for a specified tag
57
+ #
58
+ # @param [String] tag_name
59
+ # the name of the tag
60
+ #
61
+ # @return [String, nil]
62
+ # the tag text if the tag exists
63
+ #
64
+ # @api private
65
+ def tag_text(tag_name)
66
+ tag(tag_name).text if has_tag?(tag_name)
67
+ end
68
+
69
+ # The types for a specified tag
70
+ #
71
+ # @param [String] tag_name
72
+ # the name of the tag
73
+ #
74
+ # @return [Array<String>, nil]
75
+ # a collection of tag types if the tag exists
76
+ #
77
+ # @api private
78
+ def tag_types(tag_name)
79
+ tag(tag_name).types if has_tag?(tag_name)
80
+ end
81
+
82
+ # The method visibility: public, protected or private
83
+ #
84
+ # @return [Symbol]
85
+ # the visibility of the method
86
+ #
87
+ # @api private
88
+ def visibility
89
+ object.visibility
90
+ end
91
+
92
+ # Check if the method API type matches
93
+ #
94
+ # @param [Array<String>] types
95
+ # a collection of API types
96
+ #
97
+ # @return [Boolean]
98
+ # true if the API type matches
99
+ #
100
+ # @api private
101
+ def api?(types)
102
+ types.include?(tag_text('api'))
103
+ end
104
+
105
+ end # module Method
106
+ end # module Yardstick
@@ -0,0 +1,67 @@
1
+ module Yardstick
2
+ class Processor
3
+
4
+ # Measure files provided
5
+ #
6
+ # @param [Array<#to_str>] files
7
+ # the files to measure
8
+ #
9
+ # @return [Array<Measurement>]
10
+ # a collection of measurements
11
+ #
12
+ # @api private
13
+ def self.process_files(files)
14
+ YARD.parse(Pathname.glob(files).map { |file| file.to_str })
15
+ measure_method_objects(method_objects)
16
+ end
17
+
18
+ # Measure string provided
19
+ #
20
+ # @param [#to_str] string
21
+ # the string to measure
22
+ #
23
+ # @return [Array<Measurement>]
24
+ # a collection of measurements
25
+ #
26
+ # @api private
27
+ def self.process_string(string)
28
+ YARD.parse_string(string.to_str)
29
+ measure_method_objects(method_objects)
30
+ end
31
+
32
+ # Return method objects in YARD registry
33
+ #
34
+ # @return [Array<YARD::CodeObjects::MethodObject>]
35
+ # a collection of method objects
36
+ #
37
+ # @api private
38
+ def self.method_objects
39
+ YARD::Registry.all(:method).sort_by do |method_object|
40
+ [ method_object.file, method_object.line ]
41
+ end
42
+ ensure
43
+ YARD::Registry.clear
44
+ end
45
+
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
+ class << self
62
+ private :method_objects
63
+ private :measure_method_objects
64
+ end
65
+
66
+ end # class Processor
67
+ end # module Yardstick
@@ -0,0 +1,25 @@
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
+ # TODO: update to use super() once reek does not flag it as
16
+ # a utility method
17
+ @docstring.extend(Yardstick::Method)
18
+ end
19
+
20
+ # TODO: create an object to wrap tags, and extend each tag object with
21
+ # the matching module, if one exists under Yardstick::Tag::*
22
+
23
+ end # class MethodObject
24
+ end # module CodeObjects
25
+ 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.0.1'.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_str>, #to_str] files
14
+ # optional list of paths to measure
15
+ # @param [Hash] options
16
+ # optional configuration
17
+ #
18
+ # @return [Array<Measurement>]
19
+ # the measurements for each file
20
+ #
21
+ # @api public
22
+ def self.measure(files = 'lib/**/*.rb', options = {})
23
+ Yardstick::Processor.process_files(files)
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 [Array<Measurement>]
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 << Yardstick::ROOT + 'lib'
49
+
50
+ require 'yardstick/core_ext/object'
51
+ require 'yardstick/yard_ext'
52
+ require 'yardstick/autoload'
@@ -0,0 +1,196 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.join('..', '..', 'spec_helper')
3
+
4
+ shared_examples_for 'measurement is successful' do
5
+ before :all do
6
+ @measurement = Yardstick::Measurement.new('successful', @docstring) { true }
7
+ end
8
+ end
9
+
10
+ shared_examples_for 'measurement is skipped' do
11
+ before :all 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 :all 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 :all do
24
+ @measurement = Yardstick::Measurement.new('not implemented', @docstring) { todo }
25
+ end
26
+ end
27
+
28
+ shared_examples_for 'measurement is warned' do
29
+ before :all do
30
+ $stderr = StringIO.new
31
+ @response = @measurement.warn
32
+ $stderr.rewind
33
+ @output = $stderr.read
34
+ end
35
+
36
+ it 'should return nil' do
37
+ @response.should be_nil
38
+ end
39
+ end
40
+
41
+ describe Yardstick::Measurement do
42
+ before :all do
43
+ YARD.parse_string('def test; end')
44
+ @docstring = YARD::Registry.all(:method).first.docstring
45
+ end
46
+
47
+ describe '.new' do
48
+ before :all do
49
+ @response = Yardstick::Measurement.new('test measurement', @docstring) { true }
50
+ end
51
+
52
+ it 'should return a Measurement' do
53
+ @response.should be_kind_of(Yardstick::Measurement)
54
+ end
55
+ end
56
+
57
+ describe '#ok?' do
58
+ describe 'when the measurement is successful' do
59
+ it_should_behave_like 'measurement is successful'
60
+
61
+ it 'should return true' do
62
+ @measurement.ok?.should be_true
63
+ end
64
+ end
65
+
66
+ describe 'when the measurement is skipped' do
67
+ it_should_behave_like 'measurement is skipped'
68
+
69
+ it 'should return true' do
70
+ @measurement.ok?.should be_true
71
+ end
72
+ end
73
+
74
+ describe 'when the measurement is not successful' do
75
+ it_should_behave_like 'measurement is not successful'
76
+
77
+ it 'should return false' do
78
+ @measurement.ok?.should be_false
79
+ end
80
+ end
81
+
82
+ describe 'when the measurement is not implemented' do
83
+ it_should_behave_like 'measurement is not implemented'
84
+
85
+ it 'should return false' do
86
+ @measurement.ok?.should be_false
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '#skip?' do
92
+ describe 'when the measurement is successful' do
93
+ it_should_behave_like 'measurement is successful'
94
+
95
+ it 'should return false' do
96
+ @measurement.skip?.should be_false
97
+ end
98
+ end
99
+
100
+ describe 'when the measurement is skipped' do
101
+ it_should_behave_like 'measurement is skipped'
102
+
103
+ it 'should return true' do
104
+ @measurement.skip?.should be_true
105
+ end
106
+ end
107
+
108
+ describe 'when the measurement is not successful' do
109
+ it_should_behave_like 'measurement is not successful'
110
+
111
+ it 'should return false' do
112
+ @measurement.skip?.should be_false
113
+ end
114
+ end
115
+
116
+ describe 'when the measurement is not implemented' do
117
+ it_should_behave_like 'measurement is not implemented'
118
+
119
+ it 'should return false' do
120
+ @measurement.skip?.should be_false
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#todo?' do
126
+ describe 'when the measurement is successful' do
127
+ it_should_behave_like 'measurement is successful'
128
+
129
+ it 'should return false' do
130
+ @measurement.todo?.should be_false
131
+ end
132
+ end
133
+
134
+ describe 'when the measurement is skipped' do
135
+ it_should_behave_like 'measurement is skipped'
136
+
137
+ it 'should return false' do
138
+ @measurement.todo?.should be_false
139
+ end
140
+ end
141
+
142
+ describe 'when the measurement is not successful' do
143
+ it_should_behave_like 'measurement is not successful'
144
+
145
+ it 'should return false' do
146
+ @measurement.todo?.should be_false
147
+ end
148
+ end
149
+
150
+ describe 'when the measurement is not implemented' do
151
+ it_should_behave_like 'measurement is not implemented'
152
+
153
+ it 'should return true' do
154
+ @measurement.todo?.should be_true
155
+ end
156
+ end
157
+ end
158
+
159
+ describe '#warn' do
160
+ describe 'when the measurement is successful' do
161
+ it_should_behave_like 'measurement is successful'
162
+ it_should_behave_like 'measurement is warned'
163
+
164
+ it 'should not output a warning' do
165
+ @output.should == ''
166
+ end
167
+ end
168
+
169
+ describe 'when the measurement is skipped' do
170
+ it_should_behave_like 'measurement is skipped'
171
+ it_should_behave_like 'measurement is warned'
172
+
173
+ it 'should not output a warning' do
174
+ @output.should == ''
175
+ end
176
+ end
177
+
178
+ describe 'when the measurement is not successful' do
179
+ it_should_behave_like 'measurement is not successful'
180
+ it_should_behave_like 'measurement is warned'
181
+
182
+ it 'should output a warning' do
183
+ @output.should == "(stdin):1: #test: not successful\n"
184
+ end
185
+ end
186
+
187
+ describe 'when the measurement is not implemented' do
188
+ it_should_behave_like 'measurement is not implemented'
189
+ it_should_behave_like 'measurement is warned'
190
+
191
+ it 'should output a warning' do
192
+ @output.should == "(stdin):1: #test: not implemented\n"
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,6 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.join('..', '..', 'spec_helper')
3
+
4
+ describe Yardstick::Method do
5
+ it 'should be awesome'
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.join('..', 'spec_helper')
3
+
4
+ describe Yardstick do
5
+ it 'should be awesome'
6
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,2 @@
1
+ --exclude "spec"
2
+ --sort coverage
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --loadby random
3
+ --format profile
4
+ --backtrace
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'pathname'
4
+
5
+ dir = Pathname(__FILE__).dirname.expand_path
6
+
7
+ $LOAD_PATH.unshift(dir)
8
+ $LOAD_PATH.unshift(dir.parent + 'lib')
9
+
10
+ require 'yardstick'
11
+
12
+ Spec::Runner.configure do |config|
13
+ end
@@ -0,0 +1 @@
1
+ require 'metric_fu'
data/tasks/rdoc.rake ADDED
@@ -0,0 +1,15 @@
1
+ require 'rake/rdoctask'
2
+
3
+ Rake::RDocTask.new do |rdoc|
4
+ version = if File.exist?('VERSION.yml')
5
+ config = YAML.load(File.read('VERSION.yml'))
6
+ "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
7
+ else
8
+ ''
9
+ end
10
+
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = "yardstick #{version}"
13
+ rdoc.rdoc_files.include('README*')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,75 @@
1
+ require 'spec/rake/spectask'
2
+ require 'spec/rake/verify_rcov'
3
+
4
+ spec_defaults = lambda do |spec|
5
+ spec.pattern = 'spec/**/*_spec.rb'
6
+ spec.libs << 'lib' << 'spec'
7
+ spec.spec_opts << '--options' << 'spec/spec.opts'
8
+ end
9
+
10
+ Spec::Rake::SpecTask.new(:spec, &spec_defaults)
11
+
12
+ Spec::Rake::SpecTask.new(:rcov) do |rcov|
13
+ spec_defaults.call(rcov)
14
+ rcov.rcov = true
15
+ rcov.rcov_opts << File.readlines('spec/rcov.opts').map { |line| line.strip }
16
+ end
17
+
18
+ RCov::VerifyTask.new(:verify_rcov => :rcov) do |rcov|
19
+ rcov.threshold = 94.73
20
+ end
21
+
22
+ # original code by Ashley Moran:
23
+ # http://aviewfromafar.net/2007/11/1/rake-task-for-heckling-your-specs
24
+ desc 'Heckle each module and class'
25
+ task :heckle => :verify_rcov do
26
+ root_module = 'Yardstick'
27
+ spec_files = FileList['spec/**/*_spec.rb']
28
+
29
+ current_module = nil
30
+ current_method = nil
31
+
32
+ heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
33
+ unhandled_mutations = 0
34
+
35
+ IO.popen("spec --heckle #{root_module} #{spec_files}") do |pipe|
36
+ while line = pipe.gets
37
+ case line = line.chomp
38
+ when /\A\*\*\*\s+(#{root_module}(?:::)?(?:\w+(?:::)?)*)#(\w+)\b/
39
+ current_module, current_method = $1, $2
40
+ when "The following mutations didn't cause test failures:"
41
+ heckle_caught_modules[current_module] << current_method
42
+ when '+++ mutation'
43
+ unhandled_mutations += 1
44
+ end
45
+
46
+ puts line
47
+ end
48
+ end
49
+
50
+ if unhandled_mutations > 0
51
+ error_message_lines = [ "*************\n" ]
52
+
53
+ error_message_lines << "Heckle found #{unhandled_mutations} " \
54
+ "mutation#{"s" unless unhandled_mutations == 1} " \
55
+ "that didn't cause spec violations\n"
56
+
57
+ heckle_caught_modules.each do |mod, methods|
58
+ error_message_lines << "#{mod} contains the following " \
59
+ 'poorly-specified methods:'
60
+ methods.each do |method|
61
+ error_message_lines << " - #{method}"
62
+ end
63
+ error_message_lines << ''
64
+ end
65
+
66
+ error_message_lines << 'Get your act together and come back ' \
67
+ 'when your specs are doing their job!'
68
+
69
+ raise error_message_lines.join("\n")
70
+ else
71
+ puts 'Well done! Your code withstood a heckling.'
72
+ end
73
+ end
74
+
75
+ task :default => :spec
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dkubb-yardstick
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Kubb
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-22 00:00:00 -07:00
13
+ default_executable: yardstick
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: yard
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: "0.2"
24
+ version:
25
+ description:
26
+ email: dan.kubb@gmail.com
27
+ executables:
28
+ - yardstick
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - bin/yardstick
42
+ - lib/yardstick.rb
43
+ - lib/yardstick/autoload.rb
44
+ - lib/yardstick/cli.rb
45
+ - lib/yardstick/core_ext/object.rb
46
+ - lib/yardstick/measurable.rb
47
+ - lib/yardstick/measurement.rb
48
+ - lib/yardstick/method.rb
49
+ - lib/yardstick/processor.rb
50
+ - lib/yardstick/yard_ext.rb
51
+ - spec/public/yardstick/measurement_spec.rb
52
+ - spec/public/yardstick/method_spec.rb
53
+ - spec/public/yardstick_spec.rb
54
+ - spec/rcov.opts
55
+ - spec/spec.opts
56
+ - spec/spec_helper.rb
57
+ - tasks/metrics.rake
58
+ - tasks/rdoc.rake
59
+ - tasks/spec.rake
60
+ has_rdoc: false
61
+ homepage: http://github.com/dkubb/yardstick
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project: yardstick
82
+ rubygems_version: 1.2.0
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A tool for verifying YARD documentation coverage
86
+ test_files:
87
+ - spec/public/yardstick/measurement_spec.rb
88
+ - spec/public/yardstick/method_spec.rb
89
+ - spec/public/yardstick_spec.rb
90
+ - spec/spec_helper.rb