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