equalizer 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +5 -0
  3. data/.ruby-gemset +1 -0
  4. data/.travis.yml +20 -13
  5. data/CONTRIBUTING.md +11 -0
  6. data/Gemfile +3 -62
  7. data/Gemfile.devtools +55 -0
  8. data/Guardfile +22 -8
  9. data/LICENSE +1 -1
  10. data/README.md +17 -58
  11. data/Rakefile +2 -9
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +1 -1
  14. data/config/flog.yml +1 -1
  15. data/config/mutant.yml +3 -0
  16. data/config/{site.reek → reek.yml} +63 -48
  17. data/config/rubocop.yml +57 -0
  18. data/equalizer.gemspec +6 -10
  19. data/lib/equalizer.rb +1 -3
  20. data/lib/equalizer/version.rb +1 -1
  21. data/spec/spec_helper.rb +29 -5
  22. data/spec/unit/equalizer/methods/{eql_spec.rb → eql_predicate_spec.rb} +1 -1
  23. data/spec/unit/equalizer/methods/{equal_value_spec.rb → equality_operator_spec.rb} +0 -0
  24. data/spec/unit/equalizer/{class_method/new_spec.rb → universal_spec.rb} +43 -27
  25. metadata +33 -106
  26. data/.rvmrc +0 -1
  27. data/spec/rcov.opts +0 -7
  28. data/spec/shared/command_method_behavior.rb +0 -7
  29. data/spec/shared/each_method_behaviour.rb +0 -15
  30. data/spec/shared/hash_method_behavior.rb +0 -17
  31. data/spec/shared/idempotent_method_behavior.rb +0 -7
  32. data/spec/shared/invertible_method_behaviour.rb +0 -9
  33. data/spec/spec.opts +0 -3
  34. data/tasks/metrics/ci.rake +0 -9
  35. data/tasks/metrics/flay.rake +0 -45
  36. data/tasks/metrics/flog.rake +0 -49
  37. data/tasks/metrics/heckle.rake +0 -208
  38. data/tasks/metrics/metric_fu.rake +0 -31
  39. data/tasks/metrics/roodi.rake +0 -19
  40. data/tasks/metrics/yardstick.rake +0 -25
  41. data/tasks/spec.rake +0 -60
  42. data/tasks/yard.rake +0 -11
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm use @$(basename `pwd`) --create
@@ -1,7 +0,0 @@
1
- --exclude-only "spec/,^/"
2
- --sort coverage
3
- --callsites
4
- --xrefs
5
- --profile
6
- --text-summary
7
- --failure-threshold 100
@@ -1,7 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'a command method' do
4
- it 'returns self' do
5
- should equal(object)
6
- end
7
- end
@@ -1,15 +0,0 @@
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
@@ -1,17 +0,0 @@
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
@@ -1,7 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'an idempotent method' do
4
- it 'is idempotent' do
5
- should equal(instance_eval(&self.class.subject))
6
- end
7
- end
@@ -1,9 +0,0 @@
1
- # encoding: utf-8
2
-
3
- shared_examples_for 'an invertible method' do
4
- it_should_behave_like 'an idempotent method'
5
-
6
- it 'is invertible' do
7
- subject.inverse.should equal(object)
8
- end
9
- end
@@ -1,3 +0,0 @@
1
- --color
2
- --loadby random
3
- --format profile
@@ -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
@@ -1,45 +0,0 @@
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
@@ -1,49 +0,0 @@
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
@@ -1,208 +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
- 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 'equalizer'
36
-
37
- root_module_regexp = Regexp.union('Equalizer')
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
@@ -1,31 +0,0 @@
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
@@ -1,19 +0,0 @@
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