ice_nine 0.8.0 → 0.9.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.
- checksums.yaml +15 -0
- data/.rspec +5 -0
- data/.travis.yml +23 -12
- data/Gemfile +3 -65
- data/Gemfile.devtools +55 -0
- data/Rakefile +2 -6
- data/config/devtools.yml +2 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/mutant.yml +3 -0
- data/config/{site.reek → reek.yml} +63 -48
- data/config/rubocop.yml +62 -0
- data/config/yardstick.yml +1 -1
- data/lib/ice_nine.rb +1 -0
- data/lib/ice_nine/freezer.rb +3 -6
- data/lib/ice_nine/freezer/hash.rb +3 -2
- data/lib/ice_nine/freezer/module.rb +10 -0
- data/lib/ice_nine/support/recursion_guard.rb +5 -5
- data/lib/ice_nine/version.rb +1 -1
- data/spec/integration/ice_nine/class_methods/deep_freeze_spec.rb +16 -16
- data/spec/spec_helper.rb +18 -11
- data/spec/unit/ice_nine/class_methods/deep_freeze_spec.rb +2 -2
- data/spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb +1 -1
- data/spec/unit/ice_nine/freezer/class_methods/{element_reference_spec.rb → element_reader_spec.rb} +55 -4
- data/spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb +12 -12
- data/spec/unit/ice_nine/freezer/module/class_methods/deep_freeze_spec.rb +24 -0
- data/spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb +1 -1
- data/spec/unit/ice_nine/freezer/object/class_methods/deep_freeze_spec.rb +1 -1
- data/spec/unit/ice_nine/freezer/range/class_methods/deep_freeze_spec.rb +2 -2
- data/spec/unit/ice_nine/freezer/struct/class_methods/deep_freeze_spec.rb +1 -1
- data/spec/unit/ice_nine/recursion_guard/class_methods/guard_spec.rb +2 -2
- metadata +16 -24
- data/spec/rcov.opts +0 -7
- data/spec/spec.opts +0 -3
- data/spec/support/heckle.rb +0 -8
- data/tasks/metrics/ci.rake +0 -9
- data/tasks/metrics/flay.rake +0 -45
- data/tasks/metrics/flog.rake +0 -44
- data/tasks/metrics/heckle.rake +0 -207
- data/tasks/metrics/metric_fu.rake +0 -31
- data/tasks/metrics/roodi.rake +0 -19
- data/tasks/metrics/yardstick.rake +0 -25
- data/tasks/spec.rake +0 -60
- data/tasks/yard.rake +0 -11
@@ -20,11 +20,11 @@ describe IceNine::Freezer::Range, '.deep_freeze' do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'freeze the first object in the Range' do
|
23
|
-
subject.begin.
|
23
|
+
expect(subject.begin).to be_frozen
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'freeze the last object in the Range' do
|
27
|
-
subject.end.
|
27
|
+
expect(subject.end).to be_frozen
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -8,7 +8,7 @@ describe IceNine::RecursionGuard, '.guard' do
|
|
8
8
|
|
9
9
|
let(:object) { IceNine::RecursionGuard }
|
10
10
|
let(:object_id) { 1 }
|
11
|
-
let(:return_value) {
|
11
|
+
let(:return_value) { double('return_value') }
|
12
12
|
|
13
13
|
context 'when the block is not recursive' do
|
14
14
|
def block
|
@@ -22,7 +22,7 @@ describe IceNine::RecursionGuard, '.guard' do
|
|
22
22
|
|
23
23
|
context 'when the block is recursive' do
|
24
24
|
def block
|
25
|
-
subject.
|
25
|
+
expect(subject).to be_nil
|
26
26
|
return_value
|
27
27
|
end
|
28
28
|
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ice_nine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.9.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Dan Kubb
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-08-18 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -25,7 +23,6 @@ dependencies:
|
|
25
23
|
type: :development
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
27
|
- - ~>
|
31
28
|
- !ruby/object:Gem::Version
|
@@ -45,20 +42,25 @@ extra_rdoc_files:
|
|
45
42
|
files:
|
46
43
|
- .gitignore
|
47
44
|
- .pelusa.yml
|
45
|
+
- .rspec
|
48
46
|
- .ruby-gemset
|
49
47
|
- .travis.yml
|
50
48
|
- .yardopts
|
51
49
|
- CONTRIBUTING.md
|
52
50
|
- Gemfile
|
51
|
+
- Gemfile.devtools
|
53
52
|
- Guardfile
|
54
53
|
- LICENSE
|
55
54
|
- README.md
|
56
55
|
- Rakefile
|
57
56
|
- TODO
|
57
|
+
- config/devtools.yml
|
58
58
|
- config/flay.yml
|
59
59
|
- config/flog.yml
|
60
|
+
- config/mutant.yml
|
61
|
+
- config/reek.yml
|
60
62
|
- config/roodi.yml
|
61
|
-
- config/
|
63
|
+
- config/rubocop.yml
|
62
64
|
- config/yardstick.yml
|
63
65
|
- ice_nine.gemspec
|
64
66
|
- lib/ice_nine.rb
|
@@ -68,6 +70,7 @@ files:
|
|
68
70
|
- lib/ice_nine/freezer/false_class.rb
|
69
71
|
- lib/ice_nine/freezer/hash.rb
|
70
72
|
- lib/ice_nine/freezer/hash/state.rb
|
73
|
+
- lib/ice_nine/freezer/module.rb
|
71
74
|
- lib/ice_nine/freezer/nil_class.rb
|
72
75
|
- lib/ice_nine/freezer/no_freeze.rb
|
73
76
|
- lib/ice_nine/freezer/numeric.rb
|
@@ -80,16 +83,14 @@ files:
|
|
80
83
|
- lib/ice_nine/support/recursion_guard.rb
|
81
84
|
- lib/ice_nine/version.rb
|
82
85
|
- spec/integration/ice_nine/class_methods/deep_freeze_spec.rb
|
83
|
-
- spec/rcov.opts
|
84
|
-
- spec/spec.opts
|
85
86
|
- spec/spec_helper.rb
|
86
87
|
- spec/support/config_alias.rb
|
87
|
-
- spec/support/heckle.rb
|
88
88
|
- spec/unit/ice_nine/class_methods/deep_freeze_spec.rb
|
89
89
|
- spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb
|
90
|
-
- spec/unit/ice_nine/freezer/class_methods/
|
90
|
+
- spec/unit/ice_nine/freezer/class_methods/element_reader_spec.rb
|
91
91
|
- spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb
|
92
92
|
- spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb
|
93
|
+
- spec/unit/ice_nine/freezer/module/class_methods/deep_freeze_spec.rb
|
93
94
|
- spec/unit/ice_nine/freezer/nil_class/class_methods/deep_freeze_spec.rb
|
94
95
|
- spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb
|
95
96
|
- spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb
|
@@ -100,46 +101,37 @@ files:
|
|
100
101
|
- spec/unit/ice_nine/freezer/true_class/class_methods/deep_freeze_spec.rb
|
101
102
|
- spec/unit/ice_nine/recursion_guard/class_methods/guard_spec.rb
|
102
103
|
- spec/unit/object/deep_freeze_spec.rb
|
103
|
-
- tasks/metrics/ci.rake
|
104
|
-
- tasks/metrics/flay.rake
|
105
|
-
- tasks/metrics/flog.rake
|
106
|
-
- tasks/metrics/heckle.rake
|
107
|
-
- tasks/metrics/metric_fu.rake
|
108
|
-
- tasks/metrics/roodi.rake
|
109
|
-
- tasks/metrics/yardstick.rake
|
110
|
-
- tasks/spec.rake
|
111
|
-
- tasks/yard.rake
|
112
104
|
homepage: https://github.com/dkubb/ice_nine
|
113
105
|
licenses: []
|
106
|
+
metadata: {}
|
114
107
|
post_install_message:
|
115
108
|
rdoc_options: []
|
116
109
|
require_paths:
|
117
110
|
- lib
|
118
111
|
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
-
none: false
|
120
112
|
requirements:
|
121
113
|
- - ! '>='
|
122
114
|
- !ruby/object:Gem::Version
|
123
115
|
version: '0'
|
124
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
-
none: false
|
126
117
|
requirements:
|
127
118
|
- - ! '>='
|
128
119
|
- !ruby/object:Gem::Version
|
129
120
|
version: '0'
|
130
121
|
requirements: []
|
131
122
|
rubyforge_project:
|
132
|
-
rubygems_version:
|
123
|
+
rubygems_version: 2.0.6
|
133
124
|
signing_key:
|
134
|
-
specification_version:
|
125
|
+
specification_version: 4
|
135
126
|
summary: Deep Freeze Ruby Objects
|
136
127
|
test_files:
|
137
128
|
- spec/integration/ice_nine/class_methods/deep_freeze_spec.rb
|
138
129
|
- spec/unit/ice_nine/class_methods/deep_freeze_spec.rb
|
139
130
|
- spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb
|
140
|
-
- spec/unit/ice_nine/freezer/class_methods/
|
131
|
+
- spec/unit/ice_nine/freezer/class_methods/element_reader_spec.rb
|
141
132
|
- spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb
|
142
133
|
- spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb
|
134
|
+
- spec/unit/ice_nine/freezer/module/class_methods/deep_freeze_spec.rb
|
143
135
|
- spec/unit/ice_nine/freezer/nil_class/class_methods/deep_freeze_spec.rb
|
144
136
|
- spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb
|
145
137
|
- spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb
|
data/spec/rcov.opts
DELETED
data/spec/spec.opts
DELETED
data/spec/support/heckle.rb
DELETED
data/tasks/metrics/ci.rake
DELETED
@@ -1,9 +0,0 @@
|
|
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:roodi metrics:all ]
|
9
|
-
end
|
data/tasks/metrics/flay.rake
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
namespace :metrics do
|
4
|
-
begin
|
5
|
-
require 'flay'
|
6
|
-
require 'yaml'
|
7
|
-
|
8
|
-
config = YAML.load_file(File.expand_path('../../../config/flay.yml', __FILE__)).freeze
|
9
|
-
threshold = config.fetch('threshold').to_i
|
10
|
-
total_score = config.fetch('total_score').to_f
|
11
|
-
files = Flay.expand_dirs_to_files(config.fetch('path', 'lib')).sort
|
12
|
-
|
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
|
-
rescue LoadError
|
41
|
-
task :flay do
|
42
|
-
$stderr.puts 'Flay is not available. In order to run flay, you must: gem install flay'
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/tasks/metrics/flog.rake
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
namespace :metrics do
|
4
|
-
begin
|
5
|
-
require 'backports'
|
6
|
-
require 'flog'
|
7
|
-
require 'yaml'
|
8
|
-
|
9
|
-
config = YAML.load_file(File.expand_path('../../../config/flog.yml', __FILE__)).freeze
|
10
|
-
threshold = config.fetch('threshold').to_f.round(1)
|
11
|
-
|
12
|
-
# original code by Marty Andrews:
|
13
|
-
# http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
|
14
|
-
desc 'Analyze for code complexity'
|
15
|
-
task :flog do
|
16
|
-
flog = Flog.new
|
17
|
-
flog.flog Array(config.fetch('path', 'lib'))
|
18
|
-
|
19
|
-
totals = flog.totals.select { |name, score| name[-5, 5] != '#none' }.
|
20
|
-
map { |name, score| [ name, score.round(1) ] }.
|
21
|
-
sort_by { |name, score| score }
|
22
|
-
|
23
|
-
if totals.any?
|
24
|
-
max = totals.last[1]
|
25
|
-
unless max >= threshold
|
26
|
-
raise "Adjust flog score down to #{max}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
bad_methods = totals.select { |name, score| score > threshold }
|
31
|
-
if bad_methods.any?
|
32
|
-
bad_methods.reverse_each do |name, score|
|
33
|
-
puts '%8.1f: %s' % [ score, name ]
|
34
|
-
end
|
35
|
-
|
36
|
-
raise "#{bad_methods.size} methods have a flog complexity > #{threshold}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
rescue LoadError
|
40
|
-
task :flog do
|
41
|
-
$stderr.puts 'Flog is not available. In order to run flog, you must: gem install flog'
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/tasks/metrics/heckle.rake
DELETED
@@ -1,207 +0,0 @@
|
|
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
|
-
namespace :metrics do
|
9
|
-
begin
|
10
|
-
require 'pathname'
|
11
|
-
require 'heckle'
|
12
|
-
require 'mspec'
|
13
|
-
require 'mspec/utils/name_map'
|
14
|
-
|
15
|
-
SKIP_METHODS = %w[ blank_slate_method_added guarded_objects ].freeze
|
16
|
-
|
17
|
-
class NameMap
|
18
|
-
def file_name(method, constant)
|
19
|
-
map = MAP[method]
|
20
|
-
name = if map
|
21
|
-
map[constant] || map[:default]
|
22
|
-
else
|
23
|
-
method.gsub(/[?!=]\z/, '')
|
24
|
-
end
|
25
|
-
"#{name}_spec.rb"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
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 'ice_nine'
|
36
|
-
|
37
|
-
root_module_regexp = Regexp.union('IceNine')
|
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
|
-
unhandled_mutations = 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
|
-
when '+++ mutation'
|
171
|
-
unhandled_mutations += 1
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
if unhandled_mutations > 0
|
179
|
-
error_message_lines = [ "*************\n" ]
|
180
|
-
|
181
|
-
error_message_lines << "Heckle found #{unhandled_mutations} " \
|
182
|
-
"mutation#{"s" unless unhandled_mutations == 1} " \
|
183
|
-
"that didn't cause spec violations\n"
|
184
|
-
|
185
|
-
heckle_caught_modules.each do |mod, methods|
|
186
|
-
error_message_lines << "#{mod} contains the following " \
|
187
|
-
'poorly-specified methods:'
|
188
|
-
methods.each do |method|
|
189
|
-
error_message_lines << " - #{method}"
|
190
|
-
end
|
191
|
-
error_message_lines << ''
|
192
|
-
end
|
193
|
-
|
194
|
-
error_message_lines << 'Get your act together and come back ' \
|
195
|
-
'when your specs are doing their job!'
|
196
|
-
|
197
|
-
raise error_message_lines.join("\n")
|
198
|
-
else
|
199
|
-
puts 'Well done! Your code withstood a heckling.'
|
200
|
-
end
|
201
|
-
end
|
202
|
-
rescue LoadError
|
203
|
-
task :heckle => :coverage do
|
204
|
-
$stderr.puts 'Heckle or mspec is not available. In order to run heckle, you must: gem install heckle mspec'
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|