descendants_tracker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +37 -0
- data/.rvmrc +1 -0
- data/.travis.yml +19 -0
- data/Gemfile +59 -0
- data/Guardfile +18 -0
- data/LICENSE +21 -0
- data/README.md +88 -0
- data/Rakefile +9 -0
- data/TODO +0 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +18 -0
- data/config/site.reek +91 -0
- data/config/yardstick.yml +2 -0
- data/descendants_tracker.gemspec +21 -0
- data/lib/descendants_tracker.rb +41 -0
- data/lib/descendants_tracker/version.rb +3 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/command_method_behavior.rb +7 -0
- data/spec/shared/each_method_behaviour.rb +15 -0
- data/spec/shared/hash_method_behavior.rb +17 -0
- data/spec/shared/idempotent_method_behavior.rb +7 -0
- data/spec/shared/invertible_method_behaviour.rb +9 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/config_alias.rb +3 -0
- data/spec/unit/descendants_tracker/add_descendant_spec.rb +24 -0
- data/spec/unit/descendants_tracker/descendants_spec.rb +22 -0
- data/tasks/metrics/ci.rake +9 -0
- data/tasks/metrics/flay.rake +45 -0
- data/tasks/metrics/flog.rake +49 -0
- data/tasks/metrics/heckle.rake +208 -0
- data/tasks/metrics/metric_fu.rake +31 -0
- data/tasks/metrics/reek.rake +21 -0
- data/tasks/metrics/roodi.rake +19 -0
- data/tasks/metrics/yardstick.rake +25 -0
- data/tasks/spec.rake +60 -0
- data/tasks/yard.rake +11 -0
- metadata +141 -0
data/.gitignore
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## Rubinius
|
17
|
+
*.rbc
|
18
|
+
.rbx
|
19
|
+
|
20
|
+
## PROJECT::GENERAL
|
21
|
+
*.gem
|
22
|
+
coverage
|
23
|
+
profiling
|
24
|
+
turbulence
|
25
|
+
rdoc
|
26
|
+
pkg
|
27
|
+
tmp
|
28
|
+
doc
|
29
|
+
log
|
30
|
+
.yardoc
|
31
|
+
measurements
|
32
|
+
|
33
|
+
## BUNDLER
|
34
|
+
.bundle
|
35
|
+
Gemfile.lock
|
36
|
+
|
37
|
+
## PROJECT::SPECIFIC
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use @$(basename `pwd`) --create
|
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
before_install: gem install bundler
|
3
|
+
bundler_args: --without yard guard
|
4
|
+
script: "bundle exec rake spec"
|
5
|
+
rvm:
|
6
|
+
- 1.8.7
|
7
|
+
- 1.9.2
|
8
|
+
- 1.9.3
|
9
|
+
- jruby-18mode
|
10
|
+
- jruby-19mode
|
11
|
+
- rbx-18mode
|
12
|
+
- rbx-19mode
|
13
|
+
- ree
|
14
|
+
- ruby-head
|
15
|
+
- jruby-head
|
16
|
+
notifications:
|
17
|
+
email:
|
18
|
+
- dan.kubb@gmail.com
|
19
|
+
- mbj@seonic.net
|
data/Gemfile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
group :yard do
|
8
|
+
gem 'yard', '~> 0.8.3'
|
9
|
+
gem 'redcarpet', '~> 2.2.2', :platforms => [ :mri, :rbx ]
|
10
|
+
end
|
11
|
+
|
12
|
+
group :guard do
|
13
|
+
gem 'guard', '~> 1.5.4'
|
14
|
+
gem 'guard-bundler', '~> 1.0.0'
|
15
|
+
gem 'guard-rspec', '~> 1.2.1'
|
16
|
+
end
|
17
|
+
|
18
|
+
group :benchmarks do
|
19
|
+
gem 'rbench', '~> 0.2.3'
|
20
|
+
end
|
21
|
+
|
22
|
+
platform :jruby do
|
23
|
+
group :jruby do
|
24
|
+
gem 'jruby-openssl', '~> 0.7.4'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
group :metrics do
|
29
|
+
gem 'flay', '~> 1.4.3'
|
30
|
+
gem 'flog', '~> 2.5.3'
|
31
|
+
gem 'reek', '~> 1.2.8', :github => 'dkubb/reek'
|
32
|
+
gem 'roodi', '~> 2.1.0'
|
33
|
+
gem 'yardstick', '~> 0.8.0'
|
34
|
+
|
35
|
+
platforms :ruby_18, :ruby_19 do
|
36
|
+
# this indirectly depends on ffi which does not build on ruby-head
|
37
|
+
gem 'yard-spellcheck', '~> 0.1.5'
|
38
|
+
end
|
39
|
+
|
40
|
+
platforms :mri_18 do
|
41
|
+
gem 'arrayfields', '~> 4.7.4' # for metric_fu
|
42
|
+
gem 'fattr', '~> 2.2.0' # for metric_fu
|
43
|
+
gem 'heckle', '~> 1.4.3'
|
44
|
+
gem 'json', '~> 1.7.3' # for metric_fu rake task
|
45
|
+
gem 'map', '~> 6.2.0' # for metric_fu
|
46
|
+
gem 'metric_fu', '~> 2.1.1'
|
47
|
+
gem 'mspec', '~> 1.5.17'
|
48
|
+
gem 'rcov', '~> 1.0.0'
|
49
|
+
gem 'ruby2ruby', '= 1.2.2' # for heckle
|
50
|
+
end
|
51
|
+
|
52
|
+
platforms :ruby_19 do
|
53
|
+
gem 'simplecov', '~> 0.7.1'
|
54
|
+
end
|
55
|
+
|
56
|
+
platforms :rbx do
|
57
|
+
gem 'pelusa', '~> 0.2.1'
|
58
|
+
end
|
59
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
guard :bundler do
|
4
|
+
watch('Gemfile')
|
5
|
+
end
|
6
|
+
|
7
|
+
guard :rspec do
|
8
|
+
# run all specs if the spec_helper or supporting files files are modified
|
9
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
10
|
+
watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec' }
|
11
|
+
|
12
|
+
# run unit specs if associated lib code is modified
|
13
|
+
watch(%r{\Alib/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}"] }
|
14
|
+
watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' }
|
15
|
+
|
16
|
+
# run a spec if it is modified
|
17
|
+
watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
|
18
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2009-2012 Dan Kubb
|
2
|
+
Copyright (c) 2012 Markus Schirp (packaging)
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
descendants_tracker
|
2
|
+
===================
|
3
|
+
|
4
|
+
[![Build Status](https://secure.travis-ci.org/dkubb/descendants_tracker.png?branch=master)](http://travis-ci.org/dkubb/descendants_tracker)
|
5
|
+
[![Dependency Status](https://gemnasium.com/dkubb/descendants_tracker.png)](https://gemnasium.com/dkubb/descendants_tracker)
|
6
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/dkubb/descendants_tracker)
|
7
|
+
|
8
|
+
Small module to track descendants in an unobtrusive way.
|
9
|
+
|
10
|
+
Installation
|
11
|
+
------------
|
12
|
+
|
13
|
+
With Rubygems:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
$ gem install descendants_tracker
|
17
|
+
$ irb -rubygems
|
18
|
+
>> require 'descendants_tracker'
|
19
|
+
=> true
|
20
|
+
```
|
21
|
+
|
22
|
+
With git and local working copy:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
$ git clone git://github.com/dkubb/descendants_tracker.git
|
26
|
+
$ cd descendants_tracker
|
27
|
+
$ rake install
|
28
|
+
$ irb -rubygems
|
29
|
+
>> require 'descendants_tracker'
|
30
|
+
=> true
|
31
|
+
```
|
32
|
+
|
33
|
+
Examples
|
34
|
+
--------
|
35
|
+
|
36
|
+
``` ruby
|
37
|
+
class Foo
|
38
|
+
extend Virtus::DescendantsTracker
|
39
|
+
end
|
40
|
+
|
41
|
+
class Bar < Foo
|
42
|
+
end
|
43
|
+
|
44
|
+
Foo.descendants # => [Bar]
|
45
|
+
```
|
46
|
+
|
47
|
+
Credits
|
48
|
+
-------
|
49
|
+
|
50
|
+
* Dan Kubb ([dkubb](https://github.com/dkubb))
|
51
|
+
* Piotr Solnica ([solnic](https://github.com/solnic))
|
52
|
+
* Markus Schirp ([mbj](https://github.com/mbj))
|
53
|
+
|
54
|
+
Contributing
|
55
|
+
-------------
|
56
|
+
|
57
|
+
* If you want your code merged into the mainline, please discuss the proposed changes with me before doing any work on it. This library is still in early development, and the direction it is going may not always be clear. Some features may not be appropriate yet, may need to be deferred until later when the foundation for them is laid, or may be more applicable in a plugin.
|
58
|
+
* Fork the project.
|
59
|
+
* Make your feature addition or bug fix.
|
60
|
+
* Follow this [style guide](https://github.com/dkubb/styleguide).
|
61
|
+
* Add specs for it. This is important so I don't break it in a future version unintentionally. Tests must cover all branches within the code, and code must be fully covered.
|
62
|
+
* Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
63
|
+
* Run "rake ci". This must pass and not show any regressions in the metrics for the code to be merged.
|
64
|
+
* Send me a pull request. Bonus points for topic branc
|
65
|
+
|
66
|
+
License
|
67
|
+
-------
|
68
|
+
|
69
|
+
Copyright (c) 2011-2012 Dan Kubb
|
70
|
+
|
71
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
72
|
+
a copy of this software and associated documentation files (the
|
73
|
+
"Software"), to deal in the Software without restriction, including
|
74
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
75
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
76
|
+
permit persons to whom the Software is furnished to do so, subject to
|
77
|
+
the following conditions:
|
78
|
+
|
79
|
+
The above copyright notice and this permission notice shall be
|
80
|
+
included in all copies or substantial portions of the Software.
|
81
|
+
|
82
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
83
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
84
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
85
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
86
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
87
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
88
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/TODO
ADDED
File without changes
|
data/config/flay.yml
ADDED
data/config/flog.yml
ADDED
data/config/roodi.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
AbcMetricMethodCheck: { score: 10.3 }
|
3
|
+
AssignmentInConditionalCheck: { }
|
4
|
+
CaseMissingElseCheck: { }
|
5
|
+
ClassLineCountCheck: { line_count: 293 }
|
6
|
+
ClassNameCheck: { pattern: !ruby/regexp '/\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/' }
|
7
|
+
ClassVariableCheck: { }
|
8
|
+
CyclomaticComplexityBlockCheck: { complexity: 2 }
|
9
|
+
CyclomaticComplexityMethodCheck: { complexity: 4 }
|
10
|
+
EmptyRescueBodyCheck: { }
|
11
|
+
ForLoopCheck: { }
|
12
|
+
# TODO: decrease line_count to 5 to 10
|
13
|
+
MethodLineCountCheck: { line_count: 14 }
|
14
|
+
MethodNameCheck: { pattern: !ruby/regexp '/\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|[+*&|-])\z/' }
|
15
|
+
ModuleLineCountCheck: { line_count: 295 }
|
16
|
+
ModuleNameCheck: { pattern: !ruby/regexp '/\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/' }
|
17
|
+
# TODO: decrease parameter_count to 2 or less
|
18
|
+
ParameterNumberCheck: { parameter_count: 3 }
|
data/config/site.reek
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
---
|
2
|
+
UncommunicativeParameterName:
|
3
|
+
accept: []
|
4
|
+
exclude: []
|
5
|
+
enabled: true
|
6
|
+
reject:
|
7
|
+
- !ruby/regexp /^.$/
|
8
|
+
- !ruby/regexp /[0-9]$/
|
9
|
+
- !ruby/regexp /[A-Z]/
|
10
|
+
LargeClass:
|
11
|
+
max_methods: 10
|
12
|
+
exclude: []
|
13
|
+
enabled: true
|
14
|
+
max_instance_variables: 2
|
15
|
+
UncommunicativeMethodName:
|
16
|
+
accept: []
|
17
|
+
exclude: []
|
18
|
+
enabled: true
|
19
|
+
reject:
|
20
|
+
- !ruby/regexp /^[a-z]$/
|
21
|
+
- !ruby/regexp /[0-9]$/
|
22
|
+
- !ruby/regexp /[A-Z]/
|
23
|
+
LongParameterList:
|
24
|
+
max_params: 2 # TODO: decrease max_params to 2
|
25
|
+
exclude: []
|
26
|
+
enabled: true
|
27
|
+
overrides: {}
|
28
|
+
FeatureEnvy:
|
29
|
+
exclude: []
|
30
|
+
enabled: true
|
31
|
+
ClassVariable:
|
32
|
+
exclude: []
|
33
|
+
enabled: true
|
34
|
+
BooleanParameter:
|
35
|
+
exclude: []
|
36
|
+
enabled: true
|
37
|
+
IrresponsibleModule:
|
38
|
+
exclude: []
|
39
|
+
enabled: true
|
40
|
+
UncommunicativeModuleName:
|
41
|
+
accept: []
|
42
|
+
exclude: []
|
43
|
+
enabled: true
|
44
|
+
reject:
|
45
|
+
- !ruby/regexp /^.$/
|
46
|
+
- !ruby/regexp /[0-9]$/
|
47
|
+
NestedIterators:
|
48
|
+
ignore_iterators: []
|
49
|
+
exclude: []
|
50
|
+
enabled: true
|
51
|
+
max_allowed_nesting: 1
|
52
|
+
LongMethod:
|
53
|
+
max_statements: 7 # TODO: decrease max_statements to 5 or less
|
54
|
+
exclude: []
|
55
|
+
enabled: true
|
56
|
+
Duplication:
|
57
|
+
allow_calls: []
|
58
|
+
exclude: []
|
59
|
+
enabled: true
|
60
|
+
max_calls: 1
|
61
|
+
UtilityFunction:
|
62
|
+
max_helper_calls: 1
|
63
|
+
exclude: []
|
64
|
+
enabled: true
|
65
|
+
Attribute:
|
66
|
+
exclude: []
|
67
|
+
enabled: false
|
68
|
+
UncommunicativeVariableName:
|
69
|
+
accept: []
|
70
|
+
exclude: []
|
71
|
+
enabled: true
|
72
|
+
reject:
|
73
|
+
- !ruby/regexp /^.$/
|
74
|
+
- !ruby/regexp /[0-9]$/
|
75
|
+
- !ruby/regexp /[A-Z]/
|
76
|
+
SimulatedPolymorphism:
|
77
|
+
exclude: []
|
78
|
+
enabled: true
|
79
|
+
max_ifs: 1
|
80
|
+
DataClump:
|
81
|
+
exclude: []
|
82
|
+
enabled: true
|
83
|
+
max_copies: 1
|
84
|
+
min_clump_size: 3
|
85
|
+
ControlCouple:
|
86
|
+
exclude: []
|
87
|
+
enabled: true
|
88
|
+
LongYieldList:
|
89
|
+
max_params: 1
|
90
|
+
exclude: []
|
91
|
+
enabled: true
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../lib/descendants_tracker/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = 'descendants_tracker'
|
7
|
+
gem.version = DescendantsTracker::VERSION.dup
|
8
|
+
gem.authors = [ 'Dan Kubb', 'Piotr Solnica', 'Markus Schirp' ]
|
9
|
+
gem.email = %w[ dan.kubb@gmail.com piotr.solnica@gmail.com mbj@seonic.net ]
|
10
|
+
gem.description = 'Module that adds descendant tracking to a class'
|
11
|
+
gem.summary = gem.description
|
12
|
+
gem.homepage = 'https://github.com/dkubb/descendants_tracker'
|
13
|
+
|
14
|
+
gem.require_paths = %w[lib]
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.test_files = `git ls-files -- {spec}/*`.split($/)
|
17
|
+
gem.extra_rdoc_files = %w[LICENSE README.md TODO]
|
18
|
+
|
19
|
+
gem.add_development_dependency('rake', '~> 10.0.2')
|
20
|
+
gem.add_development_dependency('rspec', '~> 1.3.2')
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Module that adds descendant tracking to a class
|
2
|
+
module DescendantsTracker
|
3
|
+
|
4
|
+
# Return the descendants of this class
|
5
|
+
#
|
6
|
+
# @return [Array<Class>]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
def descendants
|
10
|
+
@descendants ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add the descendant to this class and the superclass
|
14
|
+
#
|
15
|
+
# @param [Class] descendant
|
16
|
+
#
|
17
|
+
# @return [self]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
def add_descendant(descendant)
|
21
|
+
superclass = self.superclass
|
22
|
+
superclass.add_descendant(descendant) if superclass.respond_to?(:add_descendant)
|
23
|
+
descendants.unshift(descendant)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Hook called when class is inherited
|
30
|
+
#
|
31
|
+
# @param [Class] descendant
|
32
|
+
#
|
33
|
+
# @return [undefined]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
def inherited(descendant)
|
37
|
+
super
|
38
|
+
add_descendant(descendant)
|
39
|
+
end
|
40
|
+
|
41
|
+
end # module DescendantsTracker
|
data/spec/rcov.opts
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_examples_for 'an #each method' do
|
4
|
+
it_should_behave_like 'a command method'
|
5
|
+
|
6
|
+
context 'with no block' do
|
7
|
+
subject { object.each }
|
8
|
+
|
9
|
+
it { should be_instance_of(to_enum.class) }
|
10
|
+
|
11
|
+
it 'yields the expected values' do
|
12
|
+
subject.to_a.should eql(object.to_a)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_examples_for 'a hash method' do
|
4
|
+
it_should_behave_like 'an idempotent method'
|
5
|
+
|
6
|
+
specification = proc do
|
7
|
+
should be_instance_of(Fixnum)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'is a fixnum' do
|
11
|
+
instance_eval(&specification)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'memoizes the hash code' do
|
15
|
+
subject.should eql(object.memoized(:hash))
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'descendants_tracker'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
|
7
|
+
# require spec support files and shared behavior
|
8
|
+
Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require f }
|
9
|
+
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DescendantsTracker, '#add_descendant' do
|
4
|
+
subject { object.add_descendant(descendant) }
|
5
|
+
|
6
|
+
let(:described_class) { Class.new { extend DescendantsTracker } }
|
7
|
+
let(:object) { Class.new(described_class) }
|
8
|
+
let(:descendant) { Class.new }
|
9
|
+
|
10
|
+
it { should equal(object) }
|
11
|
+
|
12
|
+
it 'prepends the class to the descendants' do
|
13
|
+
object.descendants << original = Class.new
|
14
|
+
expect { subject }.to change { object.descendants.dup }.
|
15
|
+
from([ original ]).
|
16
|
+
to([ descendant, original ])
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'prepends the class to the superclass descendants' do
|
20
|
+
expect { subject }.to change { object.superclass.descendants.dup }.
|
21
|
+
from([ object ]).
|
22
|
+
to([ descendant, object ])
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DescendantsTracker, '#descendants' do
|
4
|
+
subject { object.descendants }
|
5
|
+
|
6
|
+
let(:described_class) { Class.new { extend DescendantsTracker } }
|
7
|
+
let(:object) { described_class }
|
8
|
+
|
9
|
+
context 'when there are no descendants' do
|
10
|
+
it_should_behave_like 'an idempotent method'
|
11
|
+
|
12
|
+
it { should be_empty }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when there are descendants' do
|
16
|
+
let!(:descendant) { Class.new(object) } # trigger the class inhertance
|
17
|
+
|
18
|
+
it_should_behave_like 'an idempotent method'
|
19
|
+
|
20
|
+
it { should eql([ descendant ]) }
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
desc 'Run metrics with Heckle'
|
4
|
+
task :ci => %w[ ci:metrics metrics:heckle ]
|
5
|
+
|
6
|
+
namespace :ci do
|
7
|
+
desc 'Run metrics (except heckle) and spec'
|
8
|
+
task :metrics => %w[ spec metrics:verify_measurements metrics:flog metrics:flay metrics:reek metrics:roodi metrics:all ]
|
9
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'flay'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
config = YAML.load_file(File.expand_path('../../../config/flay.yml', __FILE__)).freeze
|
8
|
+
threshold = config.fetch('threshold').to_i
|
9
|
+
total_score = config.fetch('total_score').to_f
|
10
|
+
files = Flay.expand_dirs_to_files(config.fetch('path', 'lib')).sort
|
11
|
+
|
12
|
+
namespace :metrics do
|
13
|
+
# original code by Marty Andrews:
|
14
|
+
# http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
|
15
|
+
desc 'Analyze for code duplication'
|
16
|
+
task :flay do
|
17
|
+
# run flay once without a threshold to ensure the max mass matches the threshold
|
18
|
+
flay = Flay.new(:fuzzy => false, :verbose => false, :mass => 0)
|
19
|
+
flay.process(*files)
|
20
|
+
|
21
|
+
max = (flay.masses.map { |hash, mass| mass.to_f / flay.hashes[hash].size }.max) || 0
|
22
|
+
unless max >= threshold
|
23
|
+
raise "Adjust flay threshold down to #{max}"
|
24
|
+
end
|
25
|
+
|
26
|
+
total = flay.masses.reduce(0.0) { |total, (hash, mass)| total + (mass.to_f / flay.hashes[hash].size) }
|
27
|
+
unless total == total_score
|
28
|
+
raise "Flay total is now #{total}, but expected #{total_score}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# run flay a second time with the threshold set
|
32
|
+
flay = Flay.new(:fuzzy => false, :verbose => false, :mass => threshold.succ)
|
33
|
+
flay.process(*files)
|
34
|
+
|
35
|
+
if flay.masses.any?
|
36
|
+
flay.report
|
37
|
+
raise "#{flay.masses.size} chunks of code have a duplicate mass > #{threshold}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
task :flay do
|
43
|
+
$stderr.puts 'Flay is not available. In order to run flay, you must: gem install flay'
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'flog'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
class Float
|
8
|
+
def round_to(n)
|
9
|
+
(self * 10**n).round.to_f * 10**-n
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
config = YAML.load_file(File.expand_path('../../../config/flog.yml', __FILE__)).freeze
|
14
|
+
threshold = config.fetch('threshold').to_f.round_to(1)
|
15
|
+
|
16
|
+
namespace :metrics do
|
17
|
+
# original code by Marty Andrews:
|
18
|
+
# http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
|
19
|
+
desc 'Analyze for code complexity'
|
20
|
+
task :flog do
|
21
|
+
flog = Flog.new
|
22
|
+
flog.flog Array(config.fetch('path', 'lib'))
|
23
|
+
|
24
|
+
totals = flog.totals.select { |name, score| name[-5, 5] != '#none' }.
|
25
|
+
map { |name, score| [ name, score.round_to(1) ] }.
|
26
|
+
sort_by { |name, score| score }
|
27
|
+
|
28
|
+
if totals.any?
|
29
|
+
max = totals.last[1]
|
30
|
+
unless max >= threshold
|
31
|
+
raise "Adjust flog score down to #{max}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
bad_methods = totals.select { |name, score| score > threshold }
|
36
|
+
if bad_methods.any?
|
37
|
+
bad_methods.reverse_each do |name, score|
|
38
|
+
puts '%8.1f: %s' % [ score, name ]
|
39
|
+
end
|
40
|
+
|
41
|
+
raise "#{bad_methods.size} methods have a flog complexity > #{threshold}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
rescue LoadError
|
46
|
+
task :flog do
|
47
|
+
$stderr.puts 'Flog is not available. In order to run flog, you must: gem install flog'
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path('../../../lib', __FILE__))
|
4
|
+
|
5
|
+
# original code by Ashley Moran:
|
6
|
+
# http://aviewfromafar.net/2007/11/1/rake-task-for-heckling-your-specs
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'pathname'
|
10
|
+
require 'heckle'
|
11
|
+
require 'mspec'
|
12
|
+
require 'mspec/utils/name_map'
|
13
|
+
|
14
|
+
SKIP_METHODS = %w[ blank_slate_method_added ].freeze
|
15
|
+
|
16
|
+
class NameMap
|
17
|
+
def file_name(method, constant)
|
18
|
+
map = MAP[method]
|
19
|
+
name = if map
|
20
|
+
map[constant] || map[:default]
|
21
|
+
else
|
22
|
+
method.gsub(/[?!=]\z/, '')
|
23
|
+
end
|
24
|
+
"#{name}_spec.rb"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
namespace :metrics do
|
29
|
+
desc 'Heckle each module and class'
|
30
|
+
task :heckle => :coverage do
|
31
|
+
unless Ruby2Ruby::VERSION == '1.2.2'
|
32
|
+
raise "ruby2ruby version #{Ruby2Ruby::VERSION} may not work properly, 1.2.2 *only* is recommended for use with heckle"
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'descendants_tracker'
|
36
|
+
|
37
|
+
root_module_regexp = Regexp.union('DescendantsTracker')
|
38
|
+
|
39
|
+
spec_dir = Pathname('spec/unit')
|
40
|
+
|
41
|
+
NameMap::MAP.each do |op, method|
|
42
|
+
next if method.kind_of?(Hash)
|
43
|
+
NameMap::MAP[op] = { :default => method }
|
44
|
+
end
|
45
|
+
|
46
|
+
aliases = Hash.new { |h,mod| h[mod] = Hash.new { |h,method| h[method] = method } }
|
47
|
+
map = NameMap.new
|
48
|
+
|
49
|
+
heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
|
50
|
+
uncovered_methods = 0
|
51
|
+
|
52
|
+
ObjectSpace.each_object(Module) do |mod|
|
53
|
+
next unless mod.name =~ /\A#{root_module_regexp}(?::|\z)/
|
54
|
+
|
55
|
+
spec_prefix = spec_dir.join(mod.name.underscore)
|
56
|
+
|
57
|
+
specs = []
|
58
|
+
|
59
|
+
# get the public class methods
|
60
|
+
metaclass = class << mod; self end
|
61
|
+
ancestors = metaclass.ancestors
|
62
|
+
|
63
|
+
spec_class_methods = mod.singleton_methods(false)
|
64
|
+
|
65
|
+
spec_class_methods.reject! do |method|
|
66
|
+
%w[ yaml_new yaml_tag_subclasses? included nesting constants ].include?(method.to_s)
|
67
|
+
end
|
68
|
+
|
69
|
+
if mod.ancestors.include?(Singleton)
|
70
|
+
spec_class_methods.reject! { |method| method.to_s == 'instance' }
|
71
|
+
end
|
72
|
+
|
73
|
+
# get the protected and private class methods
|
74
|
+
other_class_methods = metaclass.protected_instance_methods(false) |
|
75
|
+
metaclass.private_instance_methods(false)
|
76
|
+
|
77
|
+
ancestors.each do |ancestor|
|
78
|
+
other_class_methods -= ancestor.protected_instance_methods(false) |
|
79
|
+
ancestor.private_instance_methods(false)
|
80
|
+
end
|
81
|
+
|
82
|
+
other_class_methods.reject! do |method|
|
83
|
+
method.to_s == 'allocate' || SKIP_METHODS.include?(method.to_s)
|
84
|
+
end
|
85
|
+
|
86
|
+
other_class_methods.reject! do |method|
|
87
|
+
next unless spec_class_methods.any? { |specced| specced.to_s == $1 }
|
88
|
+
|
89
|
+
spec_class_methods << method
|
90
|
+
end
|
91
|
+
|
92
|
+
spec_class_methods -= other_class_methods
|
93
|
+
|
94
|
+
# get the instances methods
|
95
|
+
spec_methods = mod.public_instance_methods(false)
|
96
|
+
|
97
|
+
other_methods = mod.protected_instance_methods(false) |
|
98
|
+
mod.private_instance_methods(false)
|
99
|
+
|
100
|
+
other_methods.reject! do |method|
|
101
|
+
next unless spec_methods.any? { |specced| specced.to_s == $1 }
|
102
|
+
|
103
|
+
spec_methods << method
|
104
|
+
end
|
105
|
+
|
106
|
+
# map the class methods to spec files
|
107
|
+
spec_class_methods.each do |method|
|
108
|
+
method = aliases[mod.name][method]
|
109
|
+
next if SKIP_METHODS.include?(method.to_s)
|
110
|
+
|
111
|
+
spec_file = spec_prefix.join('class_methods').join(map.file_name(method, mod.name))
|
112
|
+
|
113
|
+
unless spec_file.file?
|
114
|
+
raise "No spec file #{spec_file} for #{mod}.#{method}"
|
115
|
+
end
|
116
|
+
|
117
|
+
specs << [ ".#{method}", [ spec_file ] ]
|
118
|
+
end
|
119
|
+
|
120
|
+
# map the instance methods to spec files
|
121
|
+
spec_methods.each do |method|
|
122
|
+
method = aliases[mod.name][method]
|
123
|
+
next if SKIP_METHODS.include?(method.to_s)
|
124
|
+
|
125
|
+
spec_file = spec_prefix.join(map.file_name(method, mod.name))
|
126
|
+
|
127
|
+
unless spec_file.file?
|
128
|
+
raise "No spec file #{spec_file} for #{mod}##{method}"
|
129
|
+
end
|
130
|
+
|
131
|
+
specs << [ "##{method}", [ spec_file ] ]
|
132
|
+
end
|
133
|
+
|
134
|
+
# non-public methods are considered covered if they can be mutated
|
135
|
+
# and any spec fails for the current or descendant modules
|
136
|
+
other_methods.each do |method|
|
137
|
+
descedant_specs = []
|
138
|
+
|
139
|
+
ObjectSpace.each_object(Module) do |descedant|
|
140
|
+
next unless descedant.name =~ /\A#{root_module_regexp}(?::|\z)/ && mod >= descedant
|
141
|
+
descedant_spec_prefix = spec_dir.join(descedant.name.underscore)
|
142
|
+
descedant_specs << descedant_spec_prefix
|
143
|
+
|
144
|
+
if method.to_s == 'initialize'
|
145
|
+
descedant_specs.concat(Pathname.glob(descedant_spec_prefix.join('class_methods/new_spec.rb')))
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
specs << [ "##{method}", descedant_specs ]
|
150
|
+
end
|
151
|
+
|
152
|
+
other_class_methods.each do |method|
|
153
|
+
descedant_specs = []
|
154
|
+
|
155
|
+
ObjectSpace.each_object(Module) do |descedant|
|
156
|
+
next unless descedant.name =~ /\A#{root_module_regexp}(?::|\z)/ && mod >= descedant
|
157
|
+
descedant_specs << spec_dir.join(descedant.name.underscore).join('class_methods')
|
158
|
+
end
|
159
|
+
|
160
|
+
specs << [ ".#{method}", descedant_specs ]
|
161
|
+
end
|
162
|
+
|
163
|
+
specs.sort.each do |(method, spec_files)|
|
164
|
+
puts "Heckling #{mod}#{method}"
|
165
|
+
IO.popen("spec #{spec_files.join(' ')} --heckle '#{mod}#{method}'") do |pipe|
|
166
|
+
while line = pipe.gets
|
167
|
+
case line = line.chomp
|
168
|
+
when "The following mutations didn't cause test failures:"
|
169
|
+
heckle_caught_modules[mod.name] << method
|
170
|
+
uncovered_methods += 1
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
if uncovered_methods > 0
|
178
|
+
error_message_lines = [ "*************\n" ]
|
179
|
+
|
180
|
+
error_message_lines << "Heckle found #{uncovered_methods} " \
|
181
|
+
"method#{"s" unless uncovered_methods == 1} " \
|
182
|
+
"where mutations didn't cause spec violations\n"
|
183
|
+
|
184
|
+
heckle_caught_modules.each do |mod, methods|
|
185
|
+
error_message_lines << "#{mod} contains the following " \
|
186
|
+
'poorly-specified methods:'
|
187
|
+
methods.each do |method|
|
188
|
+
error_message_lines << " - #{method}"
|
189
|
+
end
|
190
|
+
error_message_lines << ''
|
191
|
+
end
|
192
|
+
|
193
|
+
error_message_lines << 'Get your act together and come back ' \
|
194
|
+
'when your specs are doing their job!'
|
195
|
+
|
196
|
+
raise error_message_lines.join("\n")
|
197
|
+
else
|
198
|
+
puts 'Well done! Your code withstood a heckling.'
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
rescue LoadError
|
203
|
+
namespace :metrics do
|
204
|
+
task :heckle => :coverage do
|
205
|
+
$stderr.puts 'Heckle or mspec is not available. In order to run heckle, you must: gem install heckle mspec'
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'metric_fu'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
# XXX: temporary hack until metric_fu is fixed
|
8
|
+
MetricFu::Saikuro.class_eval { include FileUtils }
|
9
|
+
|
10
|
+
MetricFu::Configuration.run do |config|
|
11
|
+
config.rcov = {
|
12
|
+
:environment => 'test',
|
13
|
+
:test_files => %w[ spec/**/*_spec.rb ],
|
14
|
+
:rcov_opts => %w[
|
15
|
+
--sort coverage
|
16
|
+
--no-html
|
17
|
+
--text-coverage
|
18
|
+
--no-color
|
19
|
+
--profile
|
20
|
+
--exclude spec/,^/
|
21
|
+
--include lib:spec
|
22
|
+
],
|
23
|
+
}
|
24
|
+
end
|
25
|
+
rescue LoadError
|
26
|
+
namespace :metrics do
|
27
|
+
task :all do
|
28
|
+
$stderr.puts 'metric_fu is not available. In order to run metrics:all, you must: gem install metric_fu'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'reek/rake/task'
|
5
|
+
|
6
|
+
RBX_18_MODE = RUBY_VERSION < '1.9' && defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
7
|
+
|
8
|
+
namespace :metrics do
|
9
|
+
Reek::Rake::Task.new do |t|
|
10
|
+
# reek has some problems under rbx in 1.8 mode that cause the underlying
|
11
|
+
# script to raise an exception. Rather than halt the "rake ci" process due
|
12
|
+
# to one bug, we choose to ignore it in this specific case until reek can be
|
13
|
+
# fixed.
|
14
|
+
t.fail_on_error = ! RBX_18_MODE # always true, except under rbx 18 mode
|
15
|
+
end
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
task :reek do
|
19
|
+
$stderr.puts 'Reek is not available. In order to run reek, you must: gem install reek'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'roodi'
|
5
|
+
require 'rake/tasklib'
|
6
|
+
require 'roodi_task'
|
7
|
+
|
8
|
+
namespace :metrics do
|
9
|
+
RoodiTask.new do |t|
|
10
|
+
t.verbose = false
|
11
|
+
t.config = File.expand_path('../../../config/roodi.yml', __FILE__)
|
12
|
+
t.patterns = %w[ lib/**/*.rb ]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
task :roodi do
|
17
|
+
$stderr.puts 'Roodi is not available. In order to run roodi, you must: gem install roodi'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'yardstick/rake/measurement'
|
5
|
+
require 'yardstick/rake/verify'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
config = YAML.load_file(File.expand_path('../../../config/yardstick.yml', __FILE__))
|
9
|
+
|
10
|
+
namespace :metrics do
|
11
|
+
# yardstick_measure task
|
12
|
+
Yardstick::Rake::Measurement.new
|
13
|
+
|
14
|
+
# verify_measurements task
|
15
|
+
Yardstick::Rake::Verify.new do |verify|
|
16
|
+
verify.threshold = config.fetch('threshold')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
%w[ yardstick_measure verify_measurements ].each do |name|
|
21
|
+
task name.to_s do
|
22
|
+
$stderr.puts "Yardstick is not available. In order to run #{name}, you must: gem install yardstick"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/tasks/spec.rake
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
spec_defaults = lambda do |spec|
|
4
|
+
spec.ruby_opts = %w[ -r./spec/support/config_alias ]
|
5
|
+
spec.spec_opts << '--options' << 'spec/spec.opts'
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'spec/rake/spectask'
|
10
|
+
|
11
|
+
desc 'Run all specs'
|
12
|
+
task :spec => %w[ spec:unit spec:integration ]
|
13
|
+
|
14
|
+
namespace :spec do
|
15
|
+
desc 'Run unit specs'
|
16
|
+
Spec::Rake::SpecTask.new(:unit) do |unit|
|
17
|
+
spec_defaults.call(unit)
|
18
|
+
unit.pattern = 'spec/unit/**/*_spec.rb'
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Run integration specs'
|
22
|
+
Spec::Rake::SpecTask.new(:integration) do |integration|
|
23
|
+
spec_defaults.call(integration)
|
24
|
+
integration.pattern = 'spec/integration/**/*_spec.rb'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
rescue LoadError
|
28
|
+
%w[ spec spec:unit spec:integration ].each do |name|
|
29
|
+
task name do
|
30
|
+
$stderr.puts "rspec is not available. In order to run #{name}, you must: gem install rspec"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
namespace :metrics do
|
36
|
+
begin
|
37
|
+
if RUBY_VERSION < '1.9'
|
38
|
+
desc 'Generate code coverage'
|
39
|
+
Spec::Rake::SpecTask.new(:coverage) do |rcov|
|
40
|
+
spec_defaults.call(rcov)
|
41
|
+
rcov.rcov = true
|
42
|
+
rcov.pattern = 'spec/unit/**/*_spec.rb'
|
43
|
+
rcov.rcov_opts = File.read('spec/rcov.opts').split(/\s+/)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
desc 'Generate code coverage'
|
47
|
+
task :coverage do
|
48
|
+
ENV['COVERAGE'] = 'true'
|
49
|
+
Rake::Task['spec:unit'].execute
|
50
|
+
end
|
51
|
+
end
|
52
|
+
rescue LoadError
|
53
|
+
task :coverage do
|
54
|
+
lib = RUBY_VERSION < '1.9' ? 'rcov' : 'simplecov'
|
55
|
+
$stderr.puts "coverage is not available. In order to run #{lib}, you must: gem install #{lib}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :test => :spec
|
data/tasks/yard.rake
ADDED
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: descendants_tracker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dan Kubb
|
14
|
+
- Piotr Solnica
|
15
|
+
- Markus Schirp
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2012-11-24 00:00:00 Z
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: rake
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 75
|
31
|
+
segments:
|
32
|
+
- 10
|
33
|
+
- 0
|
34
|
+
- 2
|
35
|
+
version: 10.0.2
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rspec
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 31
|
47
|
+
segments:
|
48
|
+
- 1
|
49
|
+
- 3
|
50
|
+
- 2
|
51
|
+
version: 1.3.2
|
52
|
+
type: :development
|
53
|
+
version_requirements: *id002
|
54
|
+
description: Module that adds descendant tracking to a class
|
55
|
+
email:
|
56
|
+
- dan.kubb@gmail.com
|
57
|
+
- piotr.solnica@gmail.com
|
58
|
+
- mbj@seonic.net
|
59
|
+
executables: []
|
60
|
+
|
61
|
+
extensions: []
|
62
|
+
|
63
|
+
extra_rdoc_files:
|
64
|
+
- LICENSE
|
65
|
+
- README.md
|
66
|
+
- TODO
|
67
|
+
files:
|
68
|
+
- .gitignore
|
69
|
+
- .rvmrc
|
70
|
+
- .travis.yml
|
71
|
+
- Gemfile
|
72
|
+
- Guardfile
|
73
|
+
- LICENSE
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- TODO
|
77
|
+
- config/flay.yml
|
78
|
+
- config/flog.yml
|
79
|
+
- config/roodi.yml
|
80
|
+
- config/site.reek
|
81
|
+
- config/yardstick.yml
|
82
|
+
- descendants_tracker.gemspec
|
83
|
+
- lib/descendants_tracker.rb
|
84
|
+
- lib/descendants_tracker/version.rb
|
85
|
+
- spec/rcov.opts
|
86
|
+
- spec/shared/command_method_behavior.rb
|
87
|
+
- spec/shared/each_method_behaviour.rb
|
88
|
+
- spec/shared/hash_method_behavior.rb
|
89
|
+
- spec/shared/idempotent_method_behavior.rb
|
90
|
+
- spec/shared/invertible_method_behaviour.rb
|
91
|
+
- spec/spec.opts
|
92
|
+
- spec/spec_helper.rb
|
93
|
+
- spec/support/config_alias.rb
|
94
|
+
- spec/unit/descendants_tracker/add_descendant_spec.rb
|
95
|
+
- spec/unit/descendants_tracker/descendants_spec.rb
|
96
|
+
- tasks/metrics/ci.rake
|
97
|
+
- tasks/metrics/flay.rake
|
98
|
+
- tasks/metrics/flog.rake
|
99
|
+
- tasks/metrics/heckle.rake
|
100
|
+
- tasks/metrics/metric_fu.rake
|
101
|
+
- tasks/metrics/reek.rake
|
102
|
+
- tasks/metrics/roodi.rake
|
103
|
+
- tasks/metrics/yardstick.rake
|
104
|
+
- tasks/spec.rake
|
105
|
+
- tasks/yard.rake
|
106
|
+
homepage: https://github.com/dkubb/descendants_tracker
|
107
|
+
licenses: []
|
108
|
+
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
version: "0"
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
hash: 3
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
132
|
+
requirements: []
|
133
|
+
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 1.8.24
|
136
|
+
signing_key:
|
137
|
+
specification_version: 3
|
138
|
+
summary: Module that adds descendant tracking to a class
|
139
|
+
test_files: []
|
140
|
+
|
141
|
+
has_rdoc:
|