virtus 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,261 +0,0 @@
1
- $LOAD_PATH.unshift(File.expand_path('../../../lib', __FILE__))
2
-
3
- # original code by Ashley Moran:
4
- # http://aviewfromafar.net/2007/11/1/rake-task-for-heckling-your-specs
5
-
6
- begin
7
- require 'pathname'
8
- require 'backports'
9
- require 'active_support/inflector'
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
- desc 'Heckle each module and class'
29
- task :heckle => :verify_rcov do
30
- unless Ruby2Ruby::VERSION == '1.2.2'
31
- raise "ruby2ruby version #{Ruby2Ruby::VERSION} may not work properly, 1.2.2 *only* is recommended for use with heckle"
32
- end
33
-
34
- require 'veritas'
35
- root_module = 'Veritas'
36
-
37
- spec_dir = Pathname('spec/unit')
38
-
39
- NameMap::MAP.each do |op, method|
40
- next if method.kind_of?(Hash)
41
- NameMap::MAP[op] = { :default => method }
42
- end
43
-
44
- %w[
45
- Veritas::Relation::Header
46
- Veritas::Algebra::Difference::Methods
47
- Veritas::Algebra::Intersection::Methods
48
- Veritas::Algebra::Join::Methods
49
- Veritas::Algebra::Product::Methods
50
- Veritas::Algebra::Projection::Methods
51
- Veritas::Algebra::Rename::Methods
52
- Veritas::Algebra::Rename::Aliases
53
- Veritas::Algebra::Restriction::Methods
54
- Veritas::Algebra::Union::Methods
55
- ].each do |mod|
56
- NameMap::MAP['-'][mod] = 'difference'
57
- NameMap::MAP['&'][mod] = 'intersect'
58
- NameMap::MAP['+'][mod] = 'join'
59
- NameMap::MAP['*'][mod] = 'product'
60
- NameMap::MAP['|'][mod] = 'union'
61
- end
62
-
63
- NameMap::MAP['==']['Veritas::Relation::Operation::Order::Direction'] = 'eql'
64
-
65
- NameMap::MAP['|']['Veritas::Relation::Operation::Order::DirectionSet'] = 'union'
66
-
67
- %w[
68
- Veritas::Function::Connective::Conjunction::Methods
69
- Veritas::Function::Connective::Disjunction::Methods
70
- Veritas::Function::Connective::Negation::Methods
71
- ].each do |mod|
72
- NameMap::MAP['&'][mod] = 'and'
73
- NameMap::MAP['|'][mod] = 'or'
74
- NameMap::MAP['-'][mod] = 'not'
75
- end
76
-
77
- aliases = Hash.new { |h,mod| h[mod] = Hash.new { |h,method| h[method] = method } }
78
-
79
- aliases['Veritas::Attribute::Numeric']['range'] = 'size'
80
- aliases['Veritas::Attribute::String']['range'] = 'length'
81
-
82
- aliases['Veritas::Aggregate::Minimum::Methods']['min'] = 'minimum'
83
- aliases['Veritas::Aggregate::Maximum::Methods']['max'] = 'maximum'
84
- aliases['Veritas::Aggregate::Mean::Methods']['avg'] = 'mean'
85
- aliases['Veritas::Aggregate::Mean::Methods']['average'] = 'mean'
86
- aliases['Veritas::Aggregate::Variance::Methods']['var'] = 'variance'
87
- aliases['Veritas::Aggregate::StandardDeviation::Methods']['stddev'] = 'standard_deviation'
88
-
89
- aliases['Veritas::Function::Numeric::Addition::Methods']['+'] = 'add'
90
- aliases['Veritas::Function::Numeric::Subtraction::Methods']['-'] = 'subtract'
91
- aliases['Veritas::Function::Numeric::Multiplication::Methods']['*'] = 'multiply'
92
- aliases['Veritas::Function::Numeric::Division::Methods']['/'] = 'divide'
93
- aliases['Veritas::Function::Numeric::Absolute::Methods']['abs'] = 'absolute'
94
- aliases['Veritas::Function::Numeric::Exponentiation::Methods']['**'] = 'exponent'
95
- aliases['Veritas::Function::Numeric::Exponentiation::Methods']['pow'] = 'exponent'
96
- aliases['Veritas::Function::Numeric::Modulo::Methods']['%'] = 'modulo'
97
- aliases['Veritas::Function::Numeric::Modulo::Methods']['mod'] = 'modulo'
98
- aliases['Veritas::Function::Numeric::Random::Methods']['rand'] = 'random'
99
- aliases['Veritas::Function::Numeric::SquareRoot::Methods']['sqrt'] = 'square_root'
100
- aliases['Veritas::Function::Numeric::UnaryPlus::Methods']['+@'] = 'unary_plus'
101
- aliases['Veritas::Function::Numeric::UnaryMinus::Methods']['-@'] = 'unary_minus'
102
-
103
- map = NameMap.new
104
-
105
- heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
106
- unhandled_mutations = 0
107
-
108
- ObjectSpace.each_object(Module) do |mod|
109
- next unless mod.name =~ /\A#{root_module}(?::|\z)/
110
-
111
- spec_prefix = spec_dir.join(mod.name.underscore)
112
-
113
- specs = []
114
-
115
- # get the public class methods
116
- metaclass = class << mod; self end
117
- ancestors = metaclass.ancestors
118
-
119
- spec_class_methods = mod.singleton_methods(false)
120
-
121
- spec_class_methods.reject! do |method|
122
- %w[ yaml_new yaml_tag_subclasses? included nesting constants ].include?(method.to_s)
123
- end
124
-
125
- if mod.ancestors.include?(Singleton)
126
- spec_class_methods.reject! { |method| method.to_s == 'instance' }
127
- end
128
-
129
- # get the protected and private class methods
130
- other_class_methods = metaclass.protected_instance_methods(false) |
131
- metaclass.private_instance_methods(false)
132
-
133
- ancestors.each do |ancestor|
134
- other_class_methods -= ancestor.protected_instance_methods(false) |
135
- ancestor.private_instance_methods(false)
136
- end
137
-
138
- other_class_methods.reject! do |method|
139
- method.to_s == 'allocate' || SKIP_METHODS.include?(method.to_s)
140
- end
141
-
142
- other_class_methods.reject! do |method|
143
- next unless spec_class_methods.any? { |specced| specced.to_s == $1 }
144
-
145
- spec_class_methods << method
146
- end
147
-
148
- # get the instances methods
149
- spec_methods = mod.public_instance_methods(false)
150
-
151
- other_methods = mod.protected_instance_methods(false) |
152
- mod.private_instance_methods(false)
153
-
154
- other_methods.reject! do |method|
155
- next unless spec_methods.any? { |specced| specced.to_s == $1 }
156
-
157
- spec_methods << method
158
- end
159
-
160
- # map the class methods to spec files
161
- spec_class_methods.each do |method|
162
- method = aliases[mod.name][method]
163
- next if SKIP_METHODS.include?(method.to_s)
164
-
165
- spec_file = spec_prefix.join('class_methods').join(map.file_name(method, mod.name))
166
-
167
- unless spec_file.file?
168
- raise "No spec file #{spec_file} for #{mod}.#{method}"
169
- end
170
-
171
- specs << [ ".#{method}", [ spec_file ] ]
172
- end
173
-
174
- # map the instance methods to spec files
175
- spec_methods.each do |method|
176
- method = aliases[mod.name][method]
177
- next if SKIP_METHODS.include?(method.to_s)
178
-
179
- spec_file = spec_prefix.join(map.file_name(method, mod.name))
180
-
181
- unless spec_file.file?
182
- raise "No spec file #{spec_file} for #{mod}##{method}"
183
- end
184
-
185
- specs << [ "##{method}", [ spec_file ] ]
186
- end
187
-
188
- # non-public methods are considered covered if they can be mutated
189
- # and any spec fails for the current or descendant modules
190
- other_methods.each do |method|
191
- descedant_specs = []
192
-
193
- ObjectSpace.each_object(Module) do |descedant|
194
- next unless descedant.name =~ /\A#{root_module}(?::|\z)/ && mod >= descedant
195
- descedant_spec_prefix = spec_dir.join(descedant.name.underscore)
196
- descedant_specs.concat(Pathname.glob(descedant_spec_prefix.join('*_spec.rb')))
197
-
198
- if method.to_s == 'initialize'
199
- descedant_specs.concat(Pathname.glob(descedant_spec_prefix.join('class_methods/new_spec.rb')))
200
- end
201
- end
202
-
203
- specs << [ "##{method}", descedant_specs ]
204
- end
205
-
206
- other_class_methods.each do |method|
207
- descedant_specs = []
208
-
209
- ObjectSpace.each_object(Module) do |descedant|
210
- next unless descedant.name =~ /\A#{root_module}(?::|\z)/ && mod >= descedant
211
- descedant_spec_prefix = spec_dir.join(descedant.name.underscore)
212
- descedant_specs.concat(Pathname.glob(descedant_spec_prefix.join('class_methods/*_spec.rb')))
213
- end
214
-
215
- specs << [ ".#{method}", descedant_specs ]
216
- end
217
-
218
- specs.sort.each do |(method, spec_files)|
219
- puts "Heckling #{mod}#{method}"
220
- IO.popen("spec #{spec_files.join(' ')} --heckle '#{mod}#{method}'") do |pipe|
221
- while line = pipe.gets
222
- case line = line.chomp
223
- when "The following mutations didn't cause test failures:"
224
- heckle_caught_modules[mod.name] << method
225
- when '+++ mutation'
226
- unhandled_mutations += 1
227
- end
228
- end
229
- end
230
- end
231
- end
232
-
233
- if unhandled_mutations > 0
234
- error_message_lines = [ "*************\n" ]
235
-
236
- error_message_lines << "Heckle found #{unhandled_mutations} " \
237
- "mutation#{"s" unless unhandled_mutations == 1} " \
238
- "that didn't cause spec violations\n"
239
-
240
- heckle_caught_modules.each do |mod, methods|
241
- error_message_lines << "#{mod} contains the following " \
242
- 'poorly-specified methods:'
243
- methods.each do |method|
244
- error_message_lines << " - #{method}"
245
- end
246
- error_message_lines << ''
247
- end
248
-
249
- error_message_lines << 'Get your act together and come back ' \
250
- 'when your specs are doing their job!'
251
-
252
- raise error_message_lines.join("\n")
253
- else
254
- puts 'Well done! Your code withstood a heckling.'
255
- end
256
- end
257
- rescue LoadError
258
- task :heckle do
259
- abort 'Heckle or mspec is not available. In order to run heckle, you must: gem install heckle mspec'
260
- end
261
- end