virtus 0.0.9 → 0.0.10

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.
@@ -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