pretentious 0.0.7 → 0.0.8

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.
@@ -0,0 +1,460 @@
1
+ module Pretentious
2
+ class Generator
3
+
4
+ def self.test_generator=(generator)
5
+ @test_generator = generator
6
+ end
7
+
8
+ def self.test_generator
9
+ @test_generator || Pretentious::RspecGenerator
10
+ end
11
+
12
+ def self.impostor_for(module_space, klass)
13
+ newStandInKlass = Class.new()
14
+ name = klass.name
15
+ module_space.const_set "#{name.split('::').last}Impostor", newStandInKlass
16
+
17
+ newStandInKlass.class_eval("
18
+ def setup_instance(*args, &block)
19
+ @_instance = #{klass.name}_ddt.new(*args, &block)
20
+ end
21
+ ")
22
+
23
+ newStandInKlass.class_eval("
24
+ class << self
25
+ def _get_standin_class
26
+ #{newStandInKlass}
27
+ end
28
+
29
+ def test_class
30
+ #{klass.name}
31
+ end
32
+
33
+ def _current_old_class
34
+ #{klass.name}_ddt
35
+ end
36
+ end
37
+ ")
38
+
39
+ newStandInKlass.class_exec do
40
+
41
+ def initialize(*args, &block)
42
+
43
+ @_instance_init = {params: [], block: nil}
44
+
45
+ self.class.replace_procs_with_recorders(args)
46
+
47
+ @_instance_init[:params] = args
48
+
49
+ recordedProc = if (block)
50
+ RecordedProc.new(block, true)
51
+ else
52
+ nil
53
+ end
54
+
55
+ @_instance_init[:block] = recordedProc
56
+
57
+ setup_instance(*args, &recordedProc)
58
+
59
+
60
+ @_method_calls = []
61
+ @_method_calls_by_method = {}
62
+ @_methods_for_test = []
63
+ @_let_variables = {}
64
+
65
+
66
+ @_init_let_variables = {}
67
+
68
+ caller_context = binding.of_caller(2)
69
+ v_locals = caller_context.eval('local_variables')
70
+
71
+ v_locals.each { |v|
72
+ variable_value = caller_context.eval("#{v.to_s}")
73
+ @_init_let_variables[variable_value.object_id] = v
74
+ }
75
+
76
+ self.class._add_instances(self)
77
+ end
78
+
79
+ def _init_arguments
80
+ @_instance_init
81
+ end
82
+
83
+ def test_class
84
+ @_instance.class
85
+ end
86
+
87
+ def include_for_tests(method_list = [])
88
+ @_methods_for_test = @_methods_for_test + method_list
89
+ end
90
+
91
+ def let_variables
92
+ @_let_variables
93
+ end
94
+
95
+ def init_let_variables
96
+ @_init_let_variables
97
+ end
98
+
99
+ def method_calls_by_method
100
+ @_method_calls_by_method
101
+ end
102
+
103
+ def method_calls
104
+ @_method_calls
105
+ end
106
+
107
+ def to_s
108
+ @_instance.to_s
109
+ end
110
+
111
+ def ==(other)
112
+ @_instance==other
113
+ end
114
+
115
+ def kind_of?(klass)
116
+ @_instance.kind_of? klass
117
+ end
118
+
119
+ def methods
120
+ @_instance.methods + [:method_calls]
121
+ end
122
+
123
+ def freeze
124
+ @_instance.freeze
125
+ end
126
+
127
+ def hash
128
+ @instance.hash
129
+ end
130
+
131
+ def inspect
132
+ @_instance.inspect
133
+ end
134
+
135
+ def is_a?(something)
136
+ @_instance.is_a? something
137
+ end
138
+
139
+ def instance_variable_get(sym)
140
+ @_instance.instance_variable_get(sym)
141
+ end
142
+
143
+ def instance_variable_set(sym, val)
144
+ @_instance.instance_variable_get(sym, val)
145
+ end
146
+
147
+ class << self
148
+
149
+ def replace_procs_with_recorders(args)
150
+ (0..args.size).each do |index|
151
+ if (args[index].kind_of? Proc)
152
+ args[index] = Pretentious::RecordedProc.new(args[index]) {}
153
+ end
154
+ end
155
+ end
156
+
157
+ def _set_is_stub
158
+ @_is_stub = true
159
+ end
160
+
161
+ def _is_stub?
162
+ @_is_stub = @_is_stub || false
163
+ @_is_stub
164
+ end
165
+
166
+ def _add_instances(instance)
167
+ @_instances = @_instances || []
168
+ @_instances << instance unless @_instances.include? instance
169
+ end
170
+
171
+ def let_variables
172
+ @_let_variables
173
+ end
174
+
175
+ def method_calls_by_method
176
+ @_method_calls_by_method
177
+ end
178
+
179
+ def method_calls
180
+ @_method_calls
181
+ end
182
+
183
+ def _add_instances(instance)
184
+ @_instances = @_instances || []
185
+ @_instances << instance unless @_instances.include? instance
186
+ end
187
+
188
+ def _instances
189
+ @_instances
190
+ end
191
+
192
+ def instance_methods
193
+ methods = super
194
+ test_class.instance_methods + methods
195
+ end
196
+
197
+ def _call_method(target, method_sym, *arguments, &block)
198
+
199
+ klass = _get_standin_class
200
+ caller_context = binding.of_caller(2)
201
+
202
+ is_stub = _is_stub?
203
+
204
+ target.instance_exec do
205
+ @_method_calls = @_method_calls || []
206
+ @_method_calls_by_method = @_method_calls_by_method || {}
207
+ @_methods_for_test = @_methods_for_test || []
208
+ @_let_variables = @_let_variables || {}
209
+
210
+
211
+ #puts \"local_variables\"
212
+ v_locals = caller_context.eval('local_variables')
213
+
214
+ v_locals.each { |v|
215
+ variable_value = caller_context.eval("#{v.to_s}")
216
+ @_let_variables[variable_value.object_id] = v
217
+ }
218
+
219
+ klass.replace_procs_with_recorders(arguments)
220
+
221
+ info_block = {}
222
+ info_block[:method] = method_sym
223
+ info_block[:params] = arguments
224
+
225
+ recordedProc = if (block)
226
+ RecordedProc.new(block, true)
227
+ else
228
+ nil
229
+ end
230
+ info_block[:block] = recordedProc
231
+
232
+ info_block[:names] = @_instance.method(method_sym).parameters
233
+
234
+ begin
235
+
236
+ unless is_stub
237
+ current_context = { calls: [] }
238
+ info_block[:context] = current_context
239
+
240
+ Thread.current._push_context(current_context)
241
+ end
242
+
243
+ if (@_instance.methods.include? method_sym)
244
+ result = @_instance.send(method_sym, *arguments, &recordedProc)
245
+ else
246
+ result = @_instance.send(:method_missing, method_sym, *arguments, &recordedProc)
247
+ end
248
+
249
+ Thread.current._pop_context unless is_stub
250
+
251
+ # methods that end with = are a special case with return values
252
+ if method_sym.to_s.end_with? '='
253
+ info_block[:result] = arguments[0]
254
+ else
255
+ info_block[:result] = result
256
+ end
257
+
258
+ rescue Exception=>e
259
+ info_block[:result] = e
260
+ rescue StandardError=>e
261
+ info_block[:result] = e
262
+ end
263
+
264
+ if is_stub
265
+ info_block[:class] = test_class
266
+ Thread.current._all_context.each { |mock_context|
267
+ mock_context[:calls] << info_block if mock_context
268
+ }
269
+ end
270
+
271
+ @_method_calls << info_block
272
+
273
+ if (@_method_calls_by_method[method_sym].nil?)
274
+ @_method_calls_by_method[method_sym] = []
275
+ end
276
+
277
+ @_method_calls_by_method[method_sym] << info_block
278
+ raise e if (e.kind_of? Exception)
279
+ result
280
+ end
281
+ end
282
+
283
+ end
284
+
285
+ end
286
+
287
+ newStandInKlass.class_exec do
288
+ def method_missing(method_sym, *arguments, &block)
289
+ #puts "#{method_sym} #{arguments}"
290
+ self.class._call_method(self, method_sym, *arguments, &block)
291
+ end
292
+
293
+ class << self
294
+ def method_missing(method_sym, *arguments, &block)
295
+ #puts "method #{method_sym.to_s}"
296
+ _add_instances(self)
297
+ @_instance = _current_old_class
298
+ _call_method(self, method_sym, *arguments, &block)
299
+ end
300
+ end
301
+ end
302
+
303
+ newStandInKlass
304
+ end
305
+
306
+ def self.replace_class(klass, stub = false)
307
+ klass_name_parts = klass.name.split('::')
308
+ last_part = klass_name_parts.pop
309
+
310
+ module_space = Object
311
+
312
+ if (klass_name_parts.size > 0)
313
+ klass_name_parts.each do |part|
314
+ module_space = module_space.const_get(part)
315
+ end
316
+ end
317
+
318
+ newStandInKlass = impostor_for module_space, klass
319
+ newStandInKlass._set_is_stub if stub
320
+
321
+ module_space.send(:remove_const,last_part.to_sym)
322
+ module_space.const_set("#{last_part}_ddt", klass)
323
+ module_space.const_set("#{last_part}", newStandInKlass)
324
+
325
+ [module_space, klass, last_part, newStandInKlass]
326
+ end
327
+
328
+ def self.restore_class(module_space, klass, last_part)
329
+ module_space.send(:remove_const,"#{last_part}Impostor".to_sym)
330
+ module_space.send(:remove_const,"#{last_part}".to_sym)
331
+ module_space.const_set(last_part, klass)
332
+ module_space.send(:remove_const,"#{last_part}_ddt".to_sym)
333
+ end
334
+
335
+ def self.generate_for(*klasses_or_instances, &block)
336
+ all_results = {}
337
+ klasses = []
338
+ mock_dict = {}
339
+
340
+ klasses_or_instances.each { |klass_or_instance|
341
+ klass = klass_or_instance.class == Class ? klass_or_instance : klass_or_instance.class
342
+ klasses << replace_class(klass)
343
+
344
+ mock_klasses = []
345
+
346
+ klass._get_mock_classes.each do |mock_klass|
347
+ mock_klasses << replace_class(mock_klass , true)
348
+ end unless klass._get_mock_classes.nil?
349
+
350
+ mock_dict[klass] = mock_klasses
351
+ }
352
+
353
+ watch_new_instances
354
+
355
+ block.call
356
+
357
+ unwatch_new_instances
358
+
359
+ klasses.each { |module_space, klass, last_part, newStandInKlass|
360
+
361
+ #restore the previous class
362
+ restore_class module_space, klass, last_part
363
+
364
+ mock_dict[klass].each do |_module_space, _klass, _last_part, _newStandInKlass|
365
+ restore_class _module_space, _klass, _last_part
366
+ end
367
+
368
+ generator = test_generator.new
369
+ generator.begin_spec(klass)
370
+ num = 1
371
+
372
+ newStandInKlass._instances.each do |instance|
373
+ generator.generate(instance, num)
374
+ num+=1
375
+ end unless newStandInKlass._instances.nil?
376
+
377
+ generator.end_spec
378
+
379
+ result = all_results[klass]
380
+ if result.nil?
381
+ all_results[klass] = []
382
+ end
383
+
384
+ all_results[klass] = generator.output
385
+
386
+ } unless klasses.nil?
387
+
388
+ all_results
389
+ end
390
+
391
+ def self.watch_new_instances
392
+ Object.class_eval do
393
+ def _get_init_arguments
394
+ @_init_arguments
395
+ end
396
+
397
+ def _set_init_arguments(*args, &block)
398
+ @_init_arguments = @_init_arguments || {}
399
+ @_init_arguments[:params] = args
400
+ unless (block.nil?)
401
+ @_init_arguments[:block] = RecordedProc.new(block) {}
402
+ end
403
+ @_variable_names= {}
404
+
405
+ index = 0
406
+ params = method(:initialize).parameters
407
+
408
+ args.each do |arg|
409
+ p = params[index]
410
+ if p.size > 1
411
+ @_variable_names[arg.object_id] = p[1].to_s
412
+ end unless p.nil?
413
+ index+=1
414
+ end unless args.nil?
415
+
416
+ end
417
+
418
+ def _variable_map
419
+ @_variable_names
420
+ end
421
+
422
+ def _deconstruct
423
+ Pretentious::Deconstructor.new().deconstruct(self)
424
+ end
425
+
426
+ def _deconstruct_to_ruby(indentation = 0)
427
+ Pretentious::Deconstructor.new().deconstruct_to_ruby(indentation, _variable_map, {}, self)
428
+ end
429
+
430
+ end
431
+
432
+ Class.class_eval do
433
+ alias_method :_ddt_old_new, :new
434
+
435
+ def new(*args, &block)
436
+ instance = _ddt_old_new(*args, &block)
437
+ instance._set_init_arguments(*args, &block)
438
+ instance
439
+ end
440
+
441
+ end
442
+ end
443
+
444
+ def self.clean_watches
445
+ Class.class_eval do
446
+ remove_method :new
447
+ alias_method :new, :_ddt_old_new
448
+ end
449
+ end
450
+
451
+ def self.unwatch_new_instances
452
+ Class.class_eval do
453
+ remove_method :new
454
+ alias_method :new, :_ddt_old_new
455
+ end
456
+ end
457
+
458
+ end
459
+
460
+ end