pretentious 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 711f7f3102783e3fc24a2b9044daed5cd1be70ff
4
- data.tar.gz: c237cb52d65cbae1df165e094f25ca7a87f04231
3
+ metadata.gz: bcb15b476f2169fe2872dd04836ca084b8af85f1
4
+ data.tar.gz: bc78a261f3d94b73d91157e07a623143111a4d5c
5
5
  SHA512:
6
- metadata.gz: 1fc605179be58671aedfe0c45a5fa3b6f871901a1f04693e848ce8322e7baab69eba48313679e6147accd99a56cbfc32c10afa229e3ce5e9d9b213b8a5966aad
7
- data.tar.gz: 12409641664626a1907833f66bda205457c17c132ab713b182926c5daf925258a4b4dbb360bbe537637335f9e9e465f85742360463df5405dea48316c71af79d
6
+ metadata.gz: a717cd689858d75a0eb9567c0cfc7994793381e050c3b1025c8abe541955e847163c8187cb09a9a5458605e9e655e3a5cb1fc23ec1fad8771775bc20b521f357
7
+ data.tar.gz: 8f3110582c6423b258b89fad1482071c416b500469892b0777837c4d97858e611526db475a1c242e2ef35478dd299db2a9ce511a15a1e71853be04b08942b992
data/README.md CHANGED
@@ -19,10 +19,11 @@ any object, to obtain a ruby code on how it was created.
19
19
  2. [Usage](#usage)
20
20
  3. [Handling complex parameters and object constructors](#handling-complex-parameters-and-object-constructors)
21
21
  4. [Capturing Exceptions](#capturing-exceptions)
22
- 5. [Object Deconstruction Utility](#object-deconstruction-utility)
22
+ 5. [Auto Stubbing](#Auto stubbing)
23
+ 6. [Object Deconstruction Utility](#object-deconstruction-utility)
23
24
  1. [Using the Object deconstructor in rails](#using-the-object-deconstructor-in-rails)
24
- 6. [Things to do after](#things-to-do-after)
25
- 7. [Limitations](#limitations)
25
+ 7. [Things to do after](#things-to-do-after)
26
+ 8. [Limitations](#limitations)
26
27
 
27
28
 
28
29
  ## Installation
@@ -319,6 +320,53 @@ should generate the following in rspec
319
320
  # TestClass1#something_is_wrong when passed should return StandardError
320
321
  expect { @fixture.something_is_wrong }.to raise_error
321
322
  ```
323
+
324
+ ## Auto stubbing
325
+
326
+ Too lazy to generate rspec-mocks stubs? Let the Pretentious gem to it for you.
327
+
328
+ Simply call the _stub method on a class and pass the classes you want to generate
329
+ stubs for when passing calling spec_for (see below):
330
+
331
+ ```ruby
332
+ Pretentious.spec_for(TestClass._stub(ClassUsedByTestClass)) do
333
+ instance = TestClass.new
334
+ instance.method_that_uses_the_class_to_stub
335
+ end
336
+
337
+ ```
338
+
339
+ should auto generate the stub like this:
340
+
341
+ ```ruby
342
+ it 'should pass current expectations' do
343
+
344
+ var_2181613400 = ["Hello Glorious world", "HI THERE!!!!"]
345
+
346
+ allow_any_instance_of(ClassUsedByTestClass).to receive(:a_stubbed_method).and_return("Hello Glorious world")
347
+
348
+ # TestClass#method_that_uses_the_class_to_stub should return ["Hello Glorious world", "HI THERE!!!!"]
349
+ expect( @fixture.method_that_uses_the_class_to_stub ).to eq(["Hello Glorious world", "HI THERE!!!!"])
350
+
351
+ end
352
+ ```
353
+
354
+ stubs that return different values every call are automatically detected an the appropriate rspec stub return
355
+ is generated (similar to below):
356
+
357
+ ```ruby
358
+ allow_any_instance_of(TestMockSubClass).to receive(:increment_val).and_return(2, 3, 4, 5)
359
+ ```
360
+
361
+ Yes, you can pass in multiple classes to be stubbed:
362
+
363
+ ```ruby
364
+ Pretentious.spec_for(TestClass._stub(ClassUsedByTestClass, AnotherClassUsedByTestClass, ....)) do
365
+ instance = TestClass.new
366
+ instance.method_that_uses_the_class_to_stub
367
+ end
368
+ ```
369
+
322
370
  ## Object Deconstruction Utility
323
371
 
324
372
  As Pretentious as the gem is, there are other uses other than generating tests specs. Tools are also available to
@@ -365,6 +413,19 @@ The _deconstruct method generates a raw deconstruction data structure used by th
365
413
 
366
414
  Of course _deconstruct_to_ruby generates the ruby code necessary to create the object!
367
415
 
416
+ If you just want to watch certain objects, the watch method accepts a block:
417
+
418
+ ```ruby
419
+ some_other_class = SomeOtherClass.new("me")
420
+ the_object = Pretentious.watch {
421
+ MyTestClass.new("some parameter", some_other_class).new
422
+ }
423
+
424
+ the_object._deconstruct_to_ruby
425
+ ```
426
+
427
+ Note that the class SomeOtherClass won't get decomposed.
428
+
368
429
  ## Using the Object deconstructor in rails
369
430
 
370
431
  In your Gemfile, add the pretentious gem.
data/example.rb CHANGED
@@ -55,6 +55,27 @@ Pretentious.spec_for(Digest::MD5) do
55
55
  Digest::MD5.hexdigest(sample)
56
56
  end
57
57
 
58
+ Pretentious.spec_for(TestClassForMocks._stub(TestMockSubClass)) do
59
+ instance = TestClassForMocks.new
60
+ instance.method_with_assign = "test"
61
+ instance.method_with_usage
62
+ instance.method_with_usage2
63
+ instance.method_with_usage4
64
+
65
+ instance2 = TestClassForMocks.new
66
+ instance2.method_with_usage3("a message")
67
+ end
68
+
69
+ Pretentious.spec_for(TestClassForAutoStub._stub(ClassUsedByTestClass)) do
70
+ instance = TestClassForAutoStub.new
71
+ instance.method_that_uses_the_class_to_stub
72
+ end
73
+
74
+ Pretentious.spec_for(TestClassForAutoStub._stub(ClassUsedByTestClass, AnotherClassUsedByTestClass)) do
75
+ instance = TestClassForAutoStub.new
76
+ instance.method_that_uses_the_class_to_stub
77
+ end
78
+
58
79
  #Pretentious.spec_for(Pretentious::Deconstructor) do
59
80
  # deconstructor = Pretentious::Deconstructor.new
60
81
  # another_object = TestClass1.new("test")
data/lib/pretentious.rb CHANGED
@@ -1,8 +1,44 @@
1
1
  require "pretentious/version"
2
2
  require "pretentious/rspec_generator"
3
+ require "pretentious/recorded_proc"
4
+ require "pretentious/generator"
3
5
  require 'binding_of_caller'
4
6
  require 'pretentious/deconstructor'
5
7
 
8
+ Class.class_eval do
9
+
10
+ def _stub(*classes)
11
+ @classes = classes
12
+ self
13
+ end
14
+
15
+ def _get_mock_classes
16
+ @classes
17
+ end
18
+
19
+ end
20
+
21
+ Thread.class_eval do
22
+
23
+ def _push_context(context)
24
+ @_context = @_context || []
25
+ @_context << context
26
+ end
27
+
28
+ def _current_context
29
+ @_context = @_context || []
30
+ @_context.last
31
+ end
32
+
33
+ def _all_context
34
+ @_context = @_context || []
35
+ end
36
+
37
+ def _pop_context
38
+ @_context.pop
39
+ end
40
+ end
41
+
6
42
  module Pretentious
7
43
 
8
44
  def self.spec_for(*klasses, &block)
@@ -49,408 +85,5 @@ module Pretentious
49
85
  result
50
86
  end
51
87
 
52
- class RecordedProc < Proc
53
-
54
- def initialize(target_proc, is_given_block = false)
55
- @target_proc = target_proc
56
- @return_value = []
57
- @args = []
58
- @given_block = is_given_block
59
- @called = false
60
- end
61
-
62
- def given_block?
63
- @given_block
64
- end
65
-
66
- def target_proc
67
- @target_proc
68
- end
69
-
70
- def return_value
71
- @return_value
72
- end
73
-
74
- def is_called?
75
- @called
76
- end
77
-
78
- def call(*args, &block)
79
- @called = true
80
- @args << args
81
- return_value = @target_proc.call(*args, &block)
82
-
83
- unless @return_value.include? return_value
84
- @return_value << return_value
85
- end
86
-
87
- return_value
88
- end
89
-
90
- end
91
-
92
- class Generator
93
-
94
- def self.impostor_for(module_space, klass)
95
- newStandInKlass = Class.new()
96
- name = klass.name
97
- module_space.const_set "#{name.split('::').last}Impostor", newStandInKlass
98
-
99
- common_snippet = "
100
- @_method_calls = @_method_calls || []
101
- @_method_calls_by_method = @_method_calls_by_method || {}
102
- @_methods_for_test = @_methods_for_test || []
103
- @_let_variables = @_let_variables || {}
104
-
105
- caller_context = binding.of_caller(1)
106
- #puts \"local_variables\"
107
- v_locals = caller_context.eval('local_variables')
108
-
109
- v_locals.each { |v|
110
- variable_value = caller_context.eval(\"\#{v.to_s}\")
111
- @_let_variables[variable_value.object_id] = v
112
- }
113
-
114
- #{newStandInKlass}.replace_procs_with_recorders(arguments)
115
-
116
- info_block = {}
117
- info_block[:method] = method_sym
118
- info_block[:params] = arguments
119
-
120
- recordedProc = if (block)
121
- RecordedProc.new(block, true)
122
- else
123
- nil
124
- end
125
- info_block[:block] = recordedProc
126
-
127
- info_block[:names] = @_instance.method(method_sym).parameters
128
-
129
- begin
130
- if (@_instance.methods.include? method_sym)
131
- result = @_instance.send(method_sym, *arguments, &recordedProc)
132
- else
133
- result = @_instance.send(:method_missing, method_sym, *arguments, &recordedProc)
134
- end
135
- info_block[:result] = result
136
- rescue Exception=>e
137
- info_block[:result] = e
138
- rescue StandardError=>e
139
- info_block[:result] = e
140
- end
141
-
142
- @_method_calls << info_block
143
-
144
- if (@_method_calls_by_method[method_sym].nil?)
145
- @_method_calls_by_method[method_sym] = []
146
- end
147
-
148
- @_method_calls_by_method[method_sym] << info_block
149
- raise e if (e.kind_of? Exception)
150
- result"
151
-
152
- newStandInKlass.class_eval("
153
- def setup_instance(*args, &block)
154
- @_instance = #{klass.name}_ddt.new(*args, &block)
155
- end
156
- ")
157
-
158
- newStandInKlass.class_exec do
159
-
160
-
161
-
162
- def initialize(*args, &block)
163
-
164
- @_instance_init = {params: [], block: nil}
165
-
166
- self.class.replace_procs_with_recorders(args)
167
-
168
- @_instance_init[:params] = args
169
-
170
- recordedProc = if (block)
171
- RecordedProc.new(block, true)
172
- else
173
- nil
174
- end
175
-
176
- @_instance_init[:block] = recordedProc
177
-
178
- setup_instance(*args, &recordedProc)
179
-
180
-
181
- @_method_calls = []
182
- @_method_calls_by_method = {}
183
- @_methods_for_test = []
184
- @_let_variables = {}
185
-
186
-
187
- @_init_let_variables = {}
188
-
189
- caller_context = binding.of_caller(2)
190
- v_locals = caller_context.eval('local_variables')
191
-
192
- v_locals.each { |v|
193
- variable_value = caller_context.eval("#{v.to_s}")
194
- @_init_let_variables[variable_value.object_id] = v
195
- }
196
-
197
- self.class._add_instances(self)
198
- end
199
-
200
- def _init_arguments
201
- @_instance_init
202
- end
203
-
204
- def test_class
205
- @_instance.class
206
- end
207
-
208
- def include_for_tests(method_list = [])
209
- @_methods_for_test = @_methods_for_test + method_list
210
- end
211
-
212
- def let_variables
213
- @_let_variables
214
- end
215
-
216
- def init_let_variables
217
- @_init_let_variables
218
- end
219
-
220
- def method_calls_by_method
221
- @_method_calls_by_method
222
- end
223
-
224
- def method_calls
225
- @_method_calls
226
- end
227
-
228
- def to_s
229
- @_instance.to_s
230
- end
231
-
232
- def ==(other)
233
- @_instance==other
234
- end
235
-
236
- def kind_of?(klass)
237
- @_instance.kind_of? klass
238
- end
239
-
240
- def methods
241
- @_instance.methods + [:method_calls]
242
- end
243
-
244
- def freeze
245
- @_instance.freeze
246
- end
247
-
248
- def hash
249
- @instance.hash
250
- end
251
-
252
- def inspect
253
- @_instance.inspect
254
- end
255
-
256
- def is_a?(something)
257
- @_instance.is_a? something
258
- end
259
-
260
- class << self
261
-
262
- def replace_procs_with_recorders(args)
263
- (0..args.size).each do |index|
264
- if (args[index].kind_of? Proc)
265
- args[index] = Pretentious::RecordedProc.new(args[index]) {}
266
- end
267
- end
268
- end
269
-
270
- def _add_instances(instance)
271
- @_instances = @_instances || []
272
- @_instances << instance unless @_instances.include? instance
273
- end
274
-
275
- def let_variables
276
- @_let_variables
277
- end
278
-
279
- def method_calls_by_method
280
- @_method_calls_by_method
281
- end
282
-
283
- def method_calls
284
- @_method_calls
285
- end
286
-
287
- def _add_instances(instance)
288
- @_instances = @_instances || []
289
- @_instances << instance unless @_instances.include? instance
290
- end
291
-
292
- def _instances
293
- @_instances
294
- end
295
-
296
- end
297
-
298
- end
299
-
300
- newStandInKlass.class_eval("
301
- def method_missing(method_sym, *arguments, &block)
302
- #puts \"\#{method_sym} \#{arguments}\"
303
- #{common_snippet}
304
- end
305
-
306
- class << self
307
-
308
- def test_class
309
- #{klass.name}
310
- end
311
-
312
- def method_missing(method_sym, *arguments, &block)
313
- #puts \"method \#{method_sym.to_s}\"
314
- _add_instances(self)
315
- @_instance = #{klass.name}_ddt
316
- #{common_snippet}
317
- end
318
- end
319
- ")
320
-
321
- newStandInKlass
322
- end
323
-
324
- def self.generate_for(*klasses_or_instances, &block)
325
- all_results = {}
326
- klasses = []
327
-
328
- klasses_or_instances.each { |klass_or_instance|
329
- klass = klass_or_instance.class == Class ? klass_or_instance : klass_or_instance.class
330
-
331
-
332
- klass_name_parts = klass.name.split('::')
333
- last_part = klass_name_parts.pop
334
-
335
- module_space = Object
336
-
337
- if (klass_name_parts.size > 0)
338
- klass_name_parts.each do |part|
339
- module_space = module_space.const_get(part)
340
- end
341
- end
342
-
343
- newStandInKlass = impostor_for module_space, klass
344
-
345
- module_space.send(:remove_const,last_part.to_sym)
346
- module_space.const_set("#{last_part}_ddt", klass)
347
- module_space.const_set("#{last_part}", newStandInKlass)
348
-
349
- klasses << [module_space, klass, last_part, newStandInKlass]
350
- }
351
-
352
- watch_new_instances
353
-
354
- block.call
355
-
356
- unwatch_new_instances
357
-
358
- klasses.each { |module_space, klass, last_part, newStandInKlass|
359
-
360
- module_space.send(:remove_const,"#{last_part}Impostor".to_sym)
361
- module_space.send(:remove_const,"#{last_part}".to_sym)
362
- module_space.const_set(last_part, klass)
363
- module_space.send(:remove_const,"#{last_part}_ddt".to_sym)
364
-
365
- test_generator = Pretentious::RspecGenerator.new
366
- test_generator.begin_spec(klass)
367
- num = 1
368
-
369
- newStandInKlass._instances.each do |instance|
370
- test_generator.generate(instance, num)
371
- num+=1
372
- end unless newStandInKlass._instances.nil?
373
-
374
- test_generator.end_spec
375
-
376
- result = all_results[klass]
377
- if result.nil?
378
- all_results[klass] = []
379
- end
380
-
381
- all_results[klass] = test_generator.output
382
-
383
- } unless klasses.nil?
384
-
385
- all_results
386
- end
387
-
388
- def self.watch_new_instances
389
- Object.class_eval do
390
- def _get_init_arguments
391
- @_init_arguments
392
- end
393
-
394
- def _set_init_arguments(*args, &block)
395
- @_init_arguments = @_init_arguments || {}
396
- @_init_arguments[:params] = args
397
- unless (block.nil?)
398
- @_init_arguments[:block] = RecordedProc.new(block) {}
399
- end
400
- @_variable_names= {}
401
-
402
- index = 0
403
- params = method(:initialize).parameters
404
-
405
- args.each do |arg|
406
- p = params[index]
407
- if p.size > 1
408
- @_variable_names[arg.object_id] = p[1].to_s
409
- end unless p.nil?
410
- index+=1
411
- end unless args.nil?
412
-
413
- end
414
-
415
- def _variable_map
416
- @_variable_names
417
- end
418
-
419
- def _deconstruct
420
- Pretentious::Deconstructor.new().deconstruct(self)
421
- end
422
-
423
- def _deconstruct_to_ruby(indentation = 0)
424
- Pretentious::Deconstructor.new().deconstruct_to_ruby(indentation, _variable_map, {}, self)
425
- end
426
-
427
- end
428
-
429
- Class.class_eval do
430
- alias_method :_ddt_old_new, :new
431
-
432
- def new(*args, &block)
433
- instance = _ddt_old_new(*args, &block)
434
- instance._set_init_arguments(*args, &block)
435
- instance
436
- end
437
- end
438
- end
439
-
440
- def self.clean_watches
441
- Class.class_eval do
442
- remove_method :new
443
- alias_method :new, :_ddt_old_new
444
- end
445
- end
446
-
447
- def self.unwatch_new_instances
448
- Class.class_eval do
449
- remove_method :new
450
- alias_method :new, :_ddt_old_new
451
- end
452
- end
453
-
454
- end
455
88
 
456
89
  end