dkubb-yardstick 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -1,4 +1,4 @@
1
- README.rdoc
1
+ README.markdown
2
2
  lib/**/*.rb
3
3
  bin/*
4
4
  features/**/*.feature
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  .DS_Store
3
3
  .yardoc
4
4
  coverage
5
+ profiling
5
6
  rdoc
6
7
  doc
7
8
  pkg
@@ -0,0 +1,69 @@
1
+ Yardstick 0.0.1
2
+ ===============
3
+
4
+ Synopsis
5
+ --------
6
+
7
+ Yardstick is a tool that verifies YARD coverage of ruby code.
8
+
9
+ It will measure the source and provide feedback on what is missing from
10
+ the documentation and what can be improved.
11
+
12
+ Installation
13
+ ------------
14
+
15
+ From Gem:
16
+
17
+ $ sudo gem install dkubb-yardstick --source http://gems.github.com/
18
+
19
+ With a local working copy:
20
+
21
+ $ git clone git://github.com/dkubb/yardstick.git
22
+ $ cd yardstick
23
+ $ rake build && sudo rake install
24
+
25
+ Usage
26
+ -----
27
+
28
+ Yardstick may be used two ways:
29
+
30
+ **1. yardstick Command-line Tool**
31
+
32
+ This is the simplest way to run yardstick. Provide it a list of files
33
+ and it will measure all of them and output suggestions for improvement,
34
+ eg:
35
+
36
+ $ yardstick lib/**/*.rb
37
+
38
+ **2. Yardstick Libraries**
39
+
40
+ Yardstick comes with several libraries that will allow you to process
41
+ lists of files, or String code fragments, eg:
42
+
43
+ # measure a list of file paths
44
+ measurements = Yardstick.measure(paths)
45
+
46
+ # measure a code fragment
47
+ measurements = Yardstick.measure_string <<-RUBY
48
+ # Displays the message provided to stdout
49
+ #
50
+ # @param [#to_str] message
51
+ # the message to display
52
+ #
53
+ # @return [undefined]
54
+ #
55
+ # @api public
56
+ def display(message)
57
+ puts message.to_str
58
+ end
59
+ RUBY
60
+
61
+ TODO
62
+ ----
63
+
64
+ - Add more measurements, especially for @param, @yield and type
65
+ validation
66
+ - Create a Rake task to allow integration of Yardstick into build
67
+ processes more easily
68
+
69
+ Copyright (c) 2009 Dan Kubb. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
@@ -2,7 +2,7 @@ require 'pathname'
2
2
  require 'yard'
3
3
 
4
4
  module Yardstick
5
- VERSION = '0.0.1'.freeze
5
+ VERSION = '0.1.0'.freeze
6
6
  ROOT = Pathname(__FILE__).dirname.parent.expand_path.freeze
7
7
 
8
8
  # Measure a list of files
@@ -10,17 +10,17 @@ module Yardstick
10
10
  # @example
11
11
  # Yardstick.measure('article.rb') # => [ Measurement ]
12
12
  #
13
- # @param [Array<#to_str>, #to_str] files
13
+ # @param [Array<#to_s>, #to_s] path
14
14
  # optional list of paths to measure
15
15
  # @param [Hash] options
16
16
  # optional configuration
17
17
  #
18
- # @return [Array<Measurement>]
18
+ # @return [MeasurementSet]
19
19
  # the measurements for each file
20
20
  #
21
21
  # @api public
22
- def self.measure(files = 'lib/**/*.rb', options = {})
23
- Yardstick::Processor.process_files(files)
22
+ def self.measure(path = 'lib/**/*.rb', options = {})
23
+ Yardstick::Processor.process_path(path)
24
24
  end
25
25
 
26
26
  # Measure a string of code and YARD documentation
@@ -35,7 +35,7 @@ module Yardstick
35
35
  # @param [Hash] options
36
36
  # optional configuration
37
37
  #
38
- # @return [Array<Measurement>]
38
+ # @return [MeasurementSet]
39
39
  # the measurements for the string
40
40
  #
41
41
  # @api public
@@ -45,7 +45,7 @@ module Yardstick
45
45
 
46
46
  end # module Yardstick
47
47
 
48
- $LOAD_PATH << Yardstick::ROOT + 'lib'
48
+ $LOAD_PATH.unshift(Yardstick::ROOT + 'lib')
49
49
 
50
50
  require 'yardstick/core_ext/object'
51
51
  require 'yardstick/yard_ext'
@@ -1,7 +1,11 @@
1
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'
2
+ autoload :CLI, 'yardstick/cli'
3
+ autoload :Measurable, 'yardstick/measurable'
4
+ autoload :Measurement, 'yardstick/measurement'
5
+ autoload :MeasurementSet, 'yardstick/measurement_set'
6
+ autoload :Method, 'yardstick/method'
7
+ autoload :OrderedSet, 'yardstick/ordered_set'
8
+ autoload :Processor, 'yardstick/processor'
9
+ autoload :Rule, 'yardstick/rule'
10
+ autoload :RuleSet, 'yardstick/rule_set'
7
11
  end # module Yardstick
@@ -11,14 +11,14 @@ module Yardstick
11
11
  # @param [Array] *args
12
12
  # arguments passed in from the command line
13
13
  #
14
- # @return [Array(Measurement)]
14
+ # @return [MeasurementSet]
15
15
  # the measurement for each file
16
16
  #
17
- # @api private
17
+ # @api public
18
18
  def self.run(*args)
19
- Yardstick.measure(*parse_options(args)).each do |measurement|
20
- measurement.warn
21
- end
19
+ measurements = Yardstick.measure(*parse_options(args))
20
+ measurements.warn
21
+ measurements
22
22
  end
23
23
 
24
24
  # Parse the options provided from the command-line
@@ -36,7 +36,7 @@ module Yardstick
36
36
  option_parser(options).parse!(args)
37
37
  [ args, options ]
38
38
  rescue OptionParser::InvalidOption => error
39
- display_exit(error.message << "\n" << args.inspect)
39
+ display_exit(error.message)
40
40
  end
41
41
 
42
42
  # Return an OptionParser instance for the command-line app
@@ -51,7 +51,7 @@ module Yardstick
51
51
  def self.option_parser(options)
52
52
  opts = OptionParser.new
53
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) }
54
+ opts.on_tail('-h', '--help', 'display this help and exit') { display_exit(opts.to_s) }
55
55
  opts
56
56
  end
57
57
 
@@ -69,9 +69,7 @@ module Yardstick
69
69
  end
70
70
 
71
71
  class << self
72
- private :option_parser
73
- private :parse_options
74
- private :display_exit
72
+ private :option_parser, :parse_options, :display_exit
75
73
  end
76
74
 
77
75
  end # module CLI
@@ -4,23 +4,23 @@ module Yardstick
4
4
 
5
5
  module ClassMethods
6
6
 
7
- # List of measurement types for this class
7
+ # List of rules for this class
8
8
  #
9
- # @return [Array<Array(String, Symbol)>]
10
- # the measurements for this class
9
+ # @return [RuleSet<Rule>]
10
+ # the rules for this class
11
11
  #
12
12
  # @api private
13
- def measurements
14
- @measurements ||= []
13
+ def rules
14
+ @rules ||= RuleSet.new
15
15
  end
16
16
 
17
- # Set the description for the measurement
17
+ # Set the description for the rule
18
18
  #
19
19
  # @param [#to_str] description
20
- # the measurement description
20
+ # the rule description
21
21
  #
22
22
  # @yield []
23
- # the measurement to perform
23
+ # the rule to perform
24
24
  #
25
25
  # @yieldreturn [Boolean]
26
26
  # return true if successful, false if not
@@ -28,8 +28,8 @@ module Yardstick
28
28
  # @return [undefined]
29
29
  #
30
30
  # @api private
31
- def measurement(description, &block)
32
- measurements << [ description, block ]
31
+ def rule(description, &block)
32
+ rules << Rule.new(description, &block)
33
33
  end
34
34
 
35
35
  private
@@ -43,8 +43,7 @@ module Yardstick
43
43
  #
44
44
  # @api private
45
45
  def included(mod)
46
- mod.extend(ClassMethods)
47
- copy_measurements(mod)
46
+ mod.extend(ClassMethods).rules.merge(rules)
48
47
  end
49
48
 
50
49
  # Extend the docstring meta class with measurable class methods
@@ -56,21 +55,7 @@ module Yardstick
56
55
  #
57
56
  # @api private
58
57
  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!
58
+ included(docstring.meta_class)
74
59
  end
75
60
  end # module ClassMethods
76
61
 
@@ -81,14 +66,12 @@ module Yardstick
81
66
  # @example
82
67
  # docstring.measure # => [ Measurement ]
83
68
  #
84
- # @return [Array<Measurement>]
69
+ # @return [MeasurementSet]
85
70
  # a collection of measurements
86
71
  #
87
72
  # @api public
88
73
  def measure
89
- meta_class.measurements.map do |(description, block)|
90
- Measurement.new(description, self, &block)
91
- end
74
+ meta_class.rules.measure(self)
92
75
  end
93
76
 
94
77
  end # module Measurable
@@ -1,6 +1,17 @@
1
1
  module Yardstick
2
2
  class Measurement
3
3
 
4
+ # Return the Measurement description
5
+ #
6
+ # @example
7
+ # measurement.description # => "The description"
8
+ #
9
+ # @return [String]
10
+ # the description
11
+ #
12
+ # @api public
13
+ attr_reader :description
14
+
4
15
  # Return a Measurement instance
5
16
  #
6
17
  # @example
@@ -87,6 +98,33 @@ module Yardstick
87
98
  end
88
99
  end
89
100
 
101
+ # Test if Measurement is equal to another measurement
102
+ #
103
+ # @example
104
+ # measurement == equal_measurement # => true
105
+ #
106
+ # @param [Measurement] other
107
+ # the other Measurement
108
+ #
109
+ # @return [Boolean]
110
+ # true if the Measurement is equal to the other, false if not
111
+ #
112
+ # @api semipublic
113
+ def eql?(other)
114
+ @description.eql?(other.instance_variable_get(:@description)) &&
115
+ @docstring.eql?(other.instance_variable_get(:@docstring))
116
+ end
117
+
118
+ # Return hash identifier for the Measurement
119
+ #
120
+ # @return [Integer]
121
+ # the hash identifier
122
+ #
123
+ # @api private
124
+ def hash
125
+ [ @description, @docstring ].hash
126
+ end
127
+
90
128
  private
91
129
 
92
130
  # Measure the docstring using the method provided to the constructor
@@ -0,0 +1,123 @@
1
+ require 'rational'
2
+
3
+ module Yardstick
4
+ class MeasurementSet < OrderedSet
5
+
6
+ # The total number of measurements
7
+ #
8
+ # @example
9
+ # measurements.total # => 570
10
+ #
11
+ # @return [Integer]
12
+ # total measurements
13
+ #
14
+ # @api public
15
+ def total
16
+ length
17
+ end
18
+
19
+ # The number of successful measurements
20
+ #
21
+ # @example
22
+ # measurements.successful # => 561
23
+ #
24
+ # @return [Integer]
25
+ # successful measurements
26
+ #
27
+ # @api public
28
+ def successful
29
+ select { |measurement| measurement.ok? }.length
30
+ end
31
+
32
+ # The number of failed measurements
33
+ #
34
+ # @example
35
+ # measurements.failed # => 9
36
+ #
37
+ # @return [Integer]
38
+ # failed measurements
39
+ #
40
+ # @api public
41
+ def failed
42
+ total - successful
43
+ end
44
+
45
+ # The percentage of successful measurements
46
+ #
47
+ # @example
48
+ # measurements.coverage # => Rational(561, 570).to_f # => 98.4%
49
+ #
50
+ # @return [Integer, Rational]
51
+ # the coverage percentage
52
+ #
53
+ # @api public
54
+ def coverage
55
+ empty? ? 0 : Rational(successful, total)
56
+ end
57
+
58
+ # Warn the unsuccessful measurements and a summary
59
+ #
60
+ # @example
61
+ # measurements.warn # (outputs measurements results and summary)
62
+ #
63
+ # @return [undefined]
64
+ #
65
+ # @api public
66
+ def warn
67
+ each { |measurement| measurement.warn }
68
+ warn_summary
69
+ end
70
+
71
+ private
72
+
73
+ # Warn the summary of all measurements
74
+ #
75
+ # @return [undefined]
76
+ #
77
+ # @api private
78
+ def warn_summary
79
+ Kernel.warn("\n#{[ coverage_text, successful_text, failed_text, total_text ].join(' ')}")
80
+ end
81
+
82
+ # The text for the coverage percentage to include in the summary
83
+ #
84
+ # @return [String]
85
+ # the coverage text
86
+ #
87
+ # @api private
88
+ def coverage_text
89
+ 'Coverage: %.1f%%' % (coverage * 100)
90
+ end
91
+
92
+ # The text for the successful measurements to include in the summary
93
+ #
94
+ # @return [String]
95
+ # the successful text
96
+ #
97
+ # @api private
98
+ def successful_text
99
+ 'Success: %d' % successful
100
+ end
101
+
102
+ # The text for the failed measurements to include in the summary
103
+ #
104
+ # @return [String]
105
+ # the failed text
106
+ #
107
+ # @api private
108
+ def failed_text
109
+ 'Failed: %d' % failed
110
+ end
111
+
112
+ # The text for the total measurements to include in the summary
113
+ #
114
+ # @return [String]
115
+ # the total text
116
+ #
117
+ # @api private
118
+ def total_text
119
+ 'Total: %d' % total
120
+ end
121
+
122
+ end # class MeasurementSet
123
+ end # module Yardstick