mcmire-rr 1.0.5.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/CHANGES +269 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +47 -0
  4. data/LICENSE +22 -0
  5. data/README.rdoc +390 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/lib/rr.rb +101 -0
  9. data/lib/rr/adapters/minitest.rb +31 -0
  10. data/lib/rr/adapters/rr_methods.rb +146 -0
  11. data/lib/rr/adapters/rspec.rb +61 -0
  12. data/lib/rr/adapters/rspec2.rb +22 -0
  13. data/lib/rr/adapters/test_unit.rb +31 -0
  14. data/lib/rr/blank_slate.rb +17 -0
  15. data/lib/rr/class_instance_method_defined.rb +9 -0
  16. data/lib/rr/double.rb +154 -0
  17. data/lib/rr/double_definitions/child_double_definition_create.rb +27 -0
  18. data/lib/rr/double_definitions/double_definition.rb +365 -0
  19. data/lib/rr/double_definitions/double_definition_create.rb +139 -0
  20. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +26 -0
  21. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +28 -0
  22. data/lib/rr/double_definitions/double_injections/instance.rb +16 -0
  23. data/lib/rr/double_definitions/strategies/double_injection/any_instance_of.rb +30 -0
  24. data/lib/rr/double_definitions/strategies/double_injection/double_injection_strategy.rb +10 -0
  25. data/lib/rr/double_definitions/strategies/double_injection/instance.rb +17 -0
  26. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +10 -0
  27. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +60 -0
  28. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  29. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +15 -0
  30. data/lib/rr/double_definitions/strategies/strategy.rb +43 -0
  31. data/lib/rr/double_definitions/strategies/strategy_methods.rb +53 -0
  32. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +31 -0
  33. data/lib/rr/double_definitions/strategies/verification/mock.rb +42 -0
  34. data/lib/rr/double_definitions/strategies/verification/stub.rb +43 -0
  35. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +10 -0
  36. data/lib/rr/double_matches.rb +42 -0
  37. data/lib/rr/errors/argument_equality_error.rb +6 -0
  38. data/lib/rr/errors/double_definition_error.rb +6 -0
  39. data/lib/rr/errors/double_not_found_error.rb +6 -0
  40. data/lib/rr/errors/double_order_error.rb +6 -0
  41. data/lib/rr/errors/rr_error.rb +20 -0
  42. data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
  43. data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
  44. data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
  45. data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
  46. data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
  47. data/lib/rr/errors/times_called_error.rb +6 -0
  48. data/lib/rr/expectations/any_argument_expectation.rb +21 -0
  49. data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
  50. data/lib/rr/expectations/times_called_expectation.rb +57 -0
  51. data/lib/rr/hash_with_object_id_key.rb +46 -0
  52. data/lib/rr/injections/double_injection.rb +220 -0
  53. data/lib/rr/injections/injection.rb +33 -0
  54. data/lib/rr/injections/method_missing_injection.rb +73 -0
  55. data/lib/rr/injections/singleton_method_added_injection.rb +72 -0
  56. data/lib/rr/method_dispatches/base_method_dispatch.rb +84 -0
  57. data/lib/rr/method_dispatches/method_dispatch.rb +59 -0
  58. data/lib/rr/method_dispatches/method_missing_dispatch.rb +61 -0
  59. data/lib/rr/proc_from_block.rb +7 -0
  60. data/lib/rr/recorded_calls.rb +103 -0
  61. data/lib/rr/space.rb +119 -0
  62. data/lib/rr/spy_verification.rb +48 -0
  63. data/lib/rr/spy_verification_proxy.rb +13 -0
  64. data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
  65. data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
  66. data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
  67. data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
  68. data/lib/rr/times_called_matchers/never_matcher.rb +23 -0
  69. data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
  70. data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
  71. data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
  72. data/lib/rr/times_called_matchers/terminal.rb +20 -0
  73. data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
  74. data/lib/rr/wildcard_matchers.rb +158 -0
  75. data/lib/rr/wildcard_matchers/anything.rb +18 -0
  76. data/lib/rr/wildcard_matchers/boolean.rb +23 -0
  77. data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
  78. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  79. data/lib/rr/wildcard_matchers/is_a.rb +25 -0
  80. data/lib/rr/wildcard_matchers/numeric.rb +13 -0
  81. data/lib/rr/wildcard_matchers/range.rb +7 -0
  82. data/lib/rr/wildcard_matchers/regexp.rb +7 -0
  83. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  84. data/spec/api/any_instance_of/all_instances_of_spec.rb +12 -0
  85. data/spec/api/any_instance_of/any_instance_of_spec.rb +47 -0
  86. data/spec/api/any_instance_of/instance_of_spec.rb +12 -0
  87. data/spec/api/dont_allow/dont_allow_after_stub_spec.rb +14 -0
  88. data/spec/api/mock/mock_spec.rb +193 -0
  89. data/spec/api/proxy/proxy_spec.rb +86 -0
  90. data/spec/api/spy/spy_spec.rb +49 -0
  91. data/spec/api/strong/strong_spec.rb +87 -0
  92. data/spec/api/stub/stub_spec.rb +152 -0
  93. data/spec/core_spec_suite.rb +18 -0
  94. data/spec/environment_fixture_setup.rb +7 -0
  95. data/spec/minitest_spec_suite.rb +21 -0
  96. data/spec/proc_from_block_spec.rb +14 -0
  97. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  98. data/spec/rr/adapters/rr_methods_creator_spec.rb +137 -0
  99. data/spec/rr/adapters/rr_methods_space_spec.rb +98 -0
  100. data/spec/rr/adapters/rr_methods_spec_helper.rb +7 -0
  101. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +13 -0
  102. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
  103. data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +91 -0
  104. data/spec/rr/double_definitions/double_definition_create_spec.rb +443 -0
  105. data/spec/rr/double_injection/double_injection_spec.rb +546 -0
  106. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  107. data/spec/rr/errors/rr_error_spec.rb +67 -0
  108. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  109. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  110. data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
  111. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
  112. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  113. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  114. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  115. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  116. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +22 -0
  117. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +37 -0
  118. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +43 -0
  119. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +11 -0
  120. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +58 -0
  121. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +35 -0
  122. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +39 -0
  123. data/spec/rr/minitest/minitest_integration_test.rb +59 -0
  124. data/spec/rr/minitest/test_helper.rb +7 -0
  125. data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
  126. data/spec/rr/rspec/rspec_adapter_spec.rb +63 -0
  127. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +21 -0
  128. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
  129. data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
  130. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  131. data/spec/rr/space/space_spec.rb +596 -0
  132. data/spec/rr/test_unit/test_helper.rb +7 -0
  133. data/spec/rr/test_unit/test_unit_backtrace_test.rb +36 -0
  134. data/spec/rr/test_unit/test_unit_integration_test.rb +59 -0
  135. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  136. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  137. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  138. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  139. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  140. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  141. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  142. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  143. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  144. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  145. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  146. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  147. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  148. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  149. data/spec/rr_spec.rb +28 -0
  150. data/spec/rspec_spec_suite.rb +16 -0
  151. data/spec/spec_helper.rb +40 -0
  152. data/spec/spec_suite.rb +50 -0
  153. data/spec/spy_verification_spec.rb +129 -0
  154. data/spec/test_unit_spec_suite.rb +20 -0
  155. metadata +220 -0
data/CHANGES ADDED
@@ -0,0 +1,269 @@
1
+ 1.0.5 (unreleased)
2
+ - Compatibility with RSpec 2 (especially for spies)
3
+
4
+ 1.0.3
5
+ - Eliminate usage of ObjectSpace._id2ref (Patch Evan Phoenix)
6
+ - Added minitest adapter (Patch Caleb Spare)
7
+ - Added instructions on installing the gem (Patch Gavin Miller)
8
+ - delete missing scratch.rb file from gemspec (Patch bonkydog)
9
+
10
+ 1.0.2
11
+ - Fixed Two calls recorded to a mock expecting only one call when called via another mock's yield block (http://github.com/btakita/rr/issues/closed#issue/42). Patch by Eugene Pimenov (http://github.com/libc).
12
+
13
+ 1.0.1
14
+ - Removed new_instance_of for Ruby 1.9.2 compatibility. instance_of is now an alias for any_instance_of.
15
+ - Compatible with Ruby 1.9.2
16
+
17
+ 1.0.0
18
+ - Added any_instance_of (aliased by all_instances_of), which binds methods directly to the class (instead of the eigenclass).
19
+ - Subclasses of a injected class do not have their methods overridden.
20
+ - any_instance_of and new_instance_of now have a block syntax
21
+
22
+ 0.10.11
23
+ - Added RR.blank_slate_whitelist
24
+ - Fixed class_eval method redefinition warning in jruby
25
+
26
+ 0.10.10
27
+ - Suite passes for Ruby 1.9.1
28
+
29
+ 0.10.9
30
+ - Fixed 1.8.6 bug for real
31
+
32
+ 0.10.8
33
+ - Fixed 1.8.6 bug
34
+
35
+ 0.10.7
36
+ - Fixed issue with DoubleInjections binding to objects overriding the method method.
37
+
38
+ 0.10.6
39
+ - Added MIT license
40
+ - Fixed Bug - dont_allow doesn't work when it follows stub (http://github.com/btakita/rr/issues#issue/20)
41
+ - Fixed exception with DoubleInjections on proxy objects (http://github.com/btakita/rr/issues#issue/24)
42
+ - Fixed Bug - Can't stub attribute methods on a BelongsToAssociation (http://github.com/btakita/rr/issues#issue/24)
43
+
44
+ 0.10.5
45
+ - Fixed stack overflow caused by double include in Test::Unit adapter [http://github.com/btakita/rr/issues#issue/16]. Identified by Dave Myron (http://github.com/contentfree)
46
+ - Fixed warnings (Patch by Bryan Helmkamp)
47
+
48
+ 0.10.4
49
+ - Handle lazily defined methods (where respond_to? returns true yet the method is not yet defined and the first call to method_missing defines the method). This pattern is used in ActiveRecord and ActionMailer.
50
+ - Fixed warning about aliasing #instance_exec in jruby. http://github.com/btakita/rr/issues#issue/9 (Patch by Nathan Sobo)
51
+
52
+ 0.10.2
53
+ - RR properly proxies subjects with private methods [http://github.com/btakita/rr/issues/#issue/7]. Identified by Matthew O'Connor.
54
+
55
+ 0.10.1
56
+ - Fixed issue with DoubleInjection not invoking methods that are lazily created [http://github.com/btakita/rr/issues/#issue/4]. Identified by davidlee (http://github.com/davidlee)
57
+ - Fixed issue with mock.proxy and returns [http://github.com/btakita/rr/issues/#issue/2]. Identified by trogdoro (http://github.com/trogdoro)
58
+
59
+ * 0.10.0
60
+ - Method is no longer invoked if respond_to? returns false. This was in place to support ActiveRecord association proxies, and is no longer needed.
61
+
62
+ * 0.9.0
63
+ - instance_of Doubles now apply to methods invoked in the subject's #initialize method.
64
+
65
+ * 0.8.1
66
+ - Fixed exception where the Subject uses method delegation via method_missing (e.g. certain ActiveRecord AssociationProxy methods)
67
+
68
+ * 0.8.0
69
+ - Fixed compatability issues with Ruby 1.9
70
+ - Aliased any_number_of_times with any_times
71
+ - Better error messages for have_received and assert_received matchers (Patch by Joe Ferris)
72
+ - Better documentation on RR wilcard matchers (Patch by Phil Arnowsky)
73
+
74
+ * 0.7.1
75
+ - Performance improvements
76
+
77
+ * 0.7.0
78
+ - Added spies (Patchs by Joe Ferris, Michael Niessner & Mike Mangino)
79
+ - Added strongly typed reimplementation doubles (Patch by Michael Niessner)
80
+
81
+ * 0.6.2
82
+ - Fixed DoubleDefinition chaining edge cases
83
+
84
+ * 0.6.1
85
+ - DoubleDefinitionCreatorProxy definition eval block is instance_evaled when the arity is not 1. When the arity is 1, the block is yielded with the DoubleDefinitionCreatorProxy passed in.
86
+
87
+ * 0.6.0
88
+ - Friendlier DoubleNotFound error message
89
+ - Implemented Double strategy creation methods (#mock, #stub, #proxy, #instance_of, and ! equivalents) on DoubleDefinition
90
+ - Implemented hash_including matcher (Patch by Matthew O'Conner)
91
+ - Implemented satisfy matcher (Patch by Matthew O'Conner)
92
+ - Implemented DoubleDefinitionCreator#mock!, #stub!, and #dont_allow!
93
+ - Modified api to method chain Doubles
94
+ - Fix conflict with Mocha overriding Object#verify
95
+
96
+ * 0.5.0
97
+ - Method chaining Doubles (Patch by Nick Kallen)
98
+ - Chained ordered expectations (Patch by Nick Kallen)
99
+ - Space#verify_doubles can take one or more objects with DoubleInjections to be verified
100
+
101
+ * 0.4.10
102
+ - DoubleDefinitionCreatorProxy does not undef #object_id
103
+ - Fixed rdoc pointer to README
104
+
105
+ * 0.4.9
106
+ - Proxying from RR module to RR::Space.instance
107
+
108
+ * 0.4.8
109
+ - Fixed issue with Hash arguments
110
+
111
+ * 0.4.7
112
+ - Improved error message
113
+
114
+ * 0.4.6
115
+ - Added Double#verbose and Double#verbose?
116
+
117
+ * 0.4.5
118
+ - Fixed doubles for == and #eql? methods
119
+
120
+ * 0.4.4
121
+ - Doc improvements
122
+ - Methods that are not alphabetic, such as ==, can be doubles
123
+
124
+ * 0.4.3
125
+ - Doc improvements
126
+ - Cleanup
127
+ - Finished renaming scenario to double
128
+
129
+ * 0.4.2
130
+ - Renamed DoubleInsertion to DoubleInjection to be consistent with Mocha terminology
131
+
132
+ * 0.4.1
133
+ - Fixed backward compatability issues with rspec
134
+ - Renamed Space#verify_double_insertions to #verify_doubles
135
+
136
+ * 0.4.0
137
+ - Documentation improvements
138
+ - Renamed Double to DoubleInsertion
139
+ - Renamed Scenario to Double
140
+
141
+ * 0.3.11
142
+ - Fixed [#13724] Mock Proxy on Active Record Association proxies causes error
143
+
144
+ * 0.3.10
145
+ - Fixed [#13139] Blocks added to proxy sets the return_value and not the after_call callback
146
+
147
+ * 0.3.9
148
+ - Alias probe to proxy
149
+
150
+ * 0.3.8
151
+ - Implemented [#13009] Better error mesage from TimesCalledMatcher
152
+
153
+ * 0.3.7
154
+ - Fixed [#12928] Reset doubles fails on Rails association proxies
155
+
156
+ * 0.3.6
157
+ - Fixed [#12765] Issues with ObjectSpace._id2ref
158
+
159
+ * 0.3.5
160
+ - trim_backtrace is only set for Test::Unit
161
+
162
+ * 0.3.4
163
+ - Implemented instance_of
164
+
165
+ * 0.3.3
166
+ - Fixed [#12495] Error Probing method_missing interaction
167
+
168
+ * 0.3.2
169
+ - Fixed [#12486] ScenarioMethodProxy when Kernel passed into instance methods
170
+
171
+ * 0.3.1
172
+ - Automatically require Test::Unit and Rspec adapters
173
+
174
+ * 0.3.0
175
+ - ScenarioCreator strategy method chaining
176
+ - Removed mock_probe
177
+ - Removed stub_probe
178
+
179
+ * 0.2.5
180
+ - mock takes method_name argument
181
+ - stub takes method_name argument
182
+ - mock_probe takes method_name argument
183
+ - stub_probe takes method_name argument
184
+ - probe takes method_name argument
185
+ - dont_allow takes method_name argument
186
+ - do_not_allow takes method_name argument
187
+
188
+ * 0.2.4
189
+ - Space#doubles key is now the object id
190
+ - Fixed [#12402] Stubbing return value of probes fails after calling the stubbed method two times
191
+
192
+ * 0.2.3
193
+ - Added RRMethods#rr_verify and RRMethods#rr_reset
194
+
195
+ * 0.2.2
196
+ - Fixed "singleton method bound for a different object"
197
+ - Doing Method aliasing again to store original method
198
+
199
+ * 0.2.1
200
+ - Added mock_probe
201
+ - Added stub_probe
202
+ - Probe returns the return value of the passed in block, instead of ignoring its return value
203
+ - Scenario#after_call returns the return value of the passed in block
204
+ - Not using method aliasing to store original method
205
+ - Renamed DoubleMethods to RRMethods
206
+ - Added RRMethods#mock_probe
207
+
208
+ * 0.1.15
209
+ - Fixed [#12333] Rebinding original_methods causes blocks not to work
210
+
211
+ * 0.1.14
212
+ - Introduced concept of Terminal and NonTerminal TimesCalledMatchers
213
+ - Doubles that can be called many times can be replaced
214
+ - Terminal Scenarios are called before NonTerminal Scenarios
215
+ - Error message tweaking
216
+ - Raise error when making a Scenarios with NonTerminal TimesMatcher Ordered
217
+
218
+ * 0.1.13
219
+ - Fixed [#12290] Scenario#returns with false causes a return value of nil
220
+
221
+ * 0.1.12
222
+ - Fixed bug where Creators methods are not removed when methods are defined on Object
223
+ - Fixed [#12289] Creators methods are not removed in Rails environment
224
+
225
+ * 0.1.11
226
+ - Fixed [#12287] AtLeastMatcher does not cause Scenario to be called
227
+
228
+ * 0.1.10
229
+ - Fixed [#12286] AnyArgumentExpectation#expected_arguments not implemented
230
+
231
+ * 0.1.9
232
+ - Added DoubleMethods#any_times
233
+ - Added Scenario#any_number_of_times
234
+
235
+ * 0.1.8
236
+ - TimesCalledError Message Formatted to be on multiple lines
237
+ - ScenarioNotFoundError Message includes all Scenarios for the Double
238
+ - ScenarioOrderError shows list of remaining ordered scenarios
239
+
240
+ * 0.1.7
241
+ - Fixed [#12194] Double#reset_doubles are not clearing Ordered Scenarios bug
242
+ - Added Space#reset
243
+ - Space#reset_doubles and Space#reset_ordered_scenarios is now protected
244
+ - Added Scenario#at_least
245
+ - Added Scenario#at_most
246
+
247
+ * 0.1.6
248
+ - [#12120] probe allows a the return value to be intercepted
249
+
250
+ * 0.1.5
251
+ - TimesCalledExpectation says how many times were called and how many times called were expected on error
252
+
253
+ * 0.1.4
254
+ - TimesCalledError prints the backtrace to where the Scenario was defined when being verified
255
+ - Error message includes method name when Scenario is not found
256
+
257
+ * 0.1.3
258
+ - Fixed issue where Double#placeholder_name issues when Double method name has a ! or ?
259
+
260
+ * 0.1.2
261
+ - Scenario#returns also accepts an argument
262
+ - Implemented Scenario#yields
263
+
264
+ * 0.1.1
265
+ - Trim the backtrace for Rspec and Test::Unit
266
+ - Rspec and Test::Unit integration fixes
267
+
268
+ * 0.1.0
269
+ - Initial Release
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem "jeweler", '~> 1.8.3'
5
+ end
6
+
7
+ group :test do
8
+ gem "rspec", "~> 2.10.0"
9
+ gem "session", "~> 2.4.0"
10
+ gem "diff-lcs", "~> 1.1.2"
11
+ if RUBY_VERSION.include?("1.9")
12
+ gem "ruby-debug19", "~> 0.11.6"
13
+ else
14
+ gem "ruby-debug", "~> 0.10.4"
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ archive-tar-minitar (0.5.2)
5
+ columnize (0.3.6)
6
+ diff-lcs (1.1.3)
7
+ git (1.2.5)
8
+ jeweler (1.8.3)
9
+ bundler (~> 1.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ rdoc
13
+ json (1.7.3)
14
+ linecache19 (0.5.12)
15
+ ruby_core_source (>= 0.1.4)
16
+ rake (0.9.2.2)
17
+ rdoc (3.12)
18
+ json (~> 1.4)
19
+ rspec (2.10.0)
20
+ rspec-core (~> 2.10.0)
21
+ rspec-expectations (~> 2.10.0)
22
+ rspec-mocks (~> 2.10.0)
23
+ rspec-core (2.10.0)
24
+ rspec-expectations (2.10.0)
25
+ diff-lcs (~> 1.1.3)
26
+ rspec-mocks (2.10.1)
27
+ ruby-debug-base19 (0.11.25)
28
+ columnize (>= 0.3.1)
29
+ linecache19 (>= 0.5.11)
30
+ ruby_core_source (>= 0.1.4)
31
+ ruby-debug19 (0.11.6)
32
+ columnize (>= 0.3.1)
33
+ linecache19 (>= 0.5.11)
34
+ ruby-debug-base19 (>= 0.11.19)
35
+ ruby_core_source (0.1.5)
36
+ archive-tar-minitar (>= 0.5.2)
37
+ session (2.4.0)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ diff-lcs (~> 1.1.2)
44
+ jeweler
45
+ rspec (~> 2.10.0)
46
+ ruby-debug19 (~> 0.11.6)
47
+ session (~> 2.4.0)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Brian Takita
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,390 @@
1
+ = RR
2
+
3
+ RR (Double Ruby) is a test double framework that features a rich
4
+ selection of double techniques and a terse syntax.
5
+
6
+ To get started, install RR from the command prompt:
7
+
8
+ gem install rr
9
+
10
+ == More Information
11
+ === Mailing Lists
12
+ * double-ruby-users@rubyforge.org
13
+ * double-ruby-devel@rubyforge.org
14
+
15
+ === Websites
16
+ * http://rubyforge.org/projects/double-ruby
17
+ * http://github.com/btakita/rr
18
+
19
+ == What is a Test Double?
20
+ A Test Double is a generalization of something that replaces a real
21
+ object to make it easier to test another object. Its like a stunt
22
+ double for tests. The following are test doubles:
23
+ * Mocks
24
+ * Stubs
25
+ * Fakes
26
+ * Spies
27
+ * Proxies
28
+ http://xunitpatterns.com/Test%20Double.html
29
+
30
+ Currently RR implements mocks, stubs, proxies, and spies. Fakes usually require custom code, so it is beyond the scope of RR.
31
+
32
+ == Using RR
33
+ === test/unit
34
+ class Test::Unit::TestCase
35
+ include RR::Adapters::TestUnit
36
+ end
37
+
38
+ === rspec
39
+ RSpec.configure do |config|
40
+ config.mock_framework = :rr
41
+ end
42
+
43
+ == standalone
44
+ extend RR::Adapters::RRMethods
45
+ mock(object).method_name {:return_value}
46
+
47
+ object.method_name # Returns :return_value
48
+
49
+ RR.verify # Verifies the Double expectations are satisfied
50
+
51
+ == Syntax between RR and other double/mock frameworks
52
+ === Terse Syntax
53
+ One of the goals of RR is to make doubles more scannable.
54
+ This is accomplished by making the double declaration look as much as the actual method invocation as possible.
55
+ Here is RR compared to other mock frameworks:
56
+
57
+ flexmock(User).should_receive(:find).with('42').and_return(jane) # Flexmock
58
+ User.should_receive(:find).with('42').and_return(jane) # Rspec
59
+ User.expects(:find).with('42').returns {jane} # Mocha
60
+ User.should_receive(:find).with('42') {jane} # Rspec using return value blocks
61
+ mock(User).find('42') {jane} # RR
62
+
63
+ === Double Injections (a.k.a Partial Mocking)
64
+ RR utilizes a technique known as "double injection".
65
+
66
+ my_object = MyClass.new
67
+ mock(my_object).hello
68
+
69
+ Compare this with doing a mock in mocha:
70
+ my_mocked_object = mock()
71
+ my_mocked_object.expects(:hello)
72
+
73
+ == Pure Mock objects
74
+ If you wish to use objects for the sole purpose of being a mock, you can
75
+ do so by creating an empty object.
76
+ mock(my_mock_object = Object.new).hello
77
+
78
+ or by using mock!
79
+ my_mock_object = mock!.hello.subject # Mocks the #hello method and retrieves that object via the #subject method
80
+
81
+ === No should_receive or expects method
82
+ RR uses method_missing to set your method expectation. This means you do not
83
+ need to use a method such as should_receive or expects.
84
+
85
+ mock(my_object).hello # The hello method on my_object is mocked
86
+
87
+ Mocha:
88
+ my_object.expects(:hello) # expects sets the hello method expectation
89
+ Rspec mocks:
90
+ my_object.should_receive(:hello) # should_receive sets the hello method expectation
91
+
92
+ === with method call is not necessary
93
+ Since RR uses method_missing, it also makes using the #with method unnecessary in most circumstances
94
+ to set the argument expectations.
95
+
96
+ mock(my_object).hello('bob', 'jane')
97
+
98
+ Mocha:
99
+ my_object.expects(:hello).with('bob', 'jane')
100
+ Rspec mocks:
101
+ my_object.should_receive(:hello).with('bob', 'jane')
102
+
103
+ === using a block to set the return value
104
+ RR supports using a block to set the return value. RR also has the #returns method.
105
+ Both of the examples are equivalent.
106
+
107
+ mock(my_object).hello('bob', 'jane') {'Hello Bob and Jane'}
108
+ mock(my_object).hello('bob', 'jane').returns('Hello Bob and Jane')
109
+
110
+ Mocha:
111
+ my_object.expects(:hello).with('bob', 'jane').returns('Hello Bob and Jane')
112
+ Rspec mocks:
113
+ my_object.should_receive(:hello).with('bob', 'jane').and_return('Hello Bob and Jane')
114
+ my_object.should_receive(:hello).with('bob', 'jane') {'Hello Bob and Jane'} #rspec also supports blocks for the return value
115
+
116
+ == Using RR
117
+ To create a double on an object, you can use the following methods:
118
+ * mock or mock!
119
+ * stub or stub!
120
+ * dont_allow or dont_allow!
121
+ * proxy or proxy!
122
+ * instance_of or instance_of!
123
+
124
+ These methods are composable. mock, stub, and dont_allow can be used by themselves and
125
+ are mutually exclusive.
126
+ proxy and instance_of must be chained with mock or stub. You can also chain
127
+ proxy and instance_of together.
128
+
129
+ The ! (bang) version of these methods causes the subject object of the Double to be instantiated.
130
+
131
+ === mock
132
+ mock replaces the method on the object with an expectation and implementation.
133
+ The expectations are a mock will be called with certain arguments a certain
134
+ number of times (the default is once). You can also set the return value
135
+ of the method invocation.
136
+
137
+ See http://xunitpatterns.com/Mock%20Object.html
138
+
139
+ The following example sets an expectation that the view will receive a method
140
+ call to #render with the arguments {:partial => "user_info"} once.
141
+ When the method is called "Information" is returned.
142
+ view = controller.template
143
+ mock(view).render(:partial => "user_info") {"Information"}
144
+
145
+ You can also allow any number of arguments to be passed into the mock by using:
146
+ mock(view).render.with_any_args.twice do |*args|
147
+ if args.first == {:partial => "user_info}
148
+ "User Info"
149
+ else
150
+ "Stuff in the view #{args.inspect}"
151
+ end
152
+ end
153
+
154
+ === stub
155
+ stub replaces the method on the object with only an implementation. You
156
+ can still use arguments to differentiate which stub gets invoked.
157
+
158
+ See http://xunitpatterns.com/Test%20Stub.html
159
+
160
+ The following example makes the User.find method return jane when passed
161
+ '42' and returns bob when passed '99'. If another id is passed to User.find,
162
+ an exception is raised.
163
+ jane = User.new
164
+ bob = User.new
165
+ stub(User).find('42') {jane}
166
+ stub(User).find('99') {bob}
167
+ stub(User).find do |id|
168
+ raise "Unexpected id #{id.inspect} passed to me"
169
+ end
170
+
171
+ === dont_allow - aliased with do_not_allow, dont_call, and do_not_call
172
+ dont_allow sets an expectation on the Double that it will never be called.
173
+ If the Double is called, then a TimesCalledError is raised.
174
+ dont_allow(User).find('42')
175
+ User.find('42') # raises a TimesCalledError
176
+
177
+ === mock.proxy
178
+ mock.proxy replaces the method on the object with an expectation, implementation, and
179
+ also invokes the actual method. mock.proxy also intercepts the return value and
180
+ passes it into the return value block.
181
+
182
+ The following example makes sets an expectation that view.render({:partial => "right_navigation"})
183
+ gets called once and return the actual content of the rendered partial template.
184
+ A call to view.render({:partial => "user_info"}) will render the user_info
185
+ partial template and send the content into the block and is represented by the html variable.
186
+ An assertion is done on the html and "Different html" is returned.
187
+ view = controller.template
188
+ mock.proxy(view).render(:partial => "right_navigation")
189
+ mock.proxy(view).render(:partial => "user_info") do |html|
190
+ html.should include("John Doe")
191
+ "Different html"
192
+ end
193
+
194
+ You can also use mock.proxy to set expectations on the returned value. In
195
+ the following example, a call to User.find('5') does the normal ActiveRecord
196
+ implementation and passes the actual value, represented by the variable bob,
197
+ into the block. bob is then set with a mock.proxy for projects to return
198
+ only the first 3 projects. bob is also mocked with valid? to return false.
199
+ mock.proxy(User).find('5') do |bob|
200
+ mock.proxy(bob).projects do |projects|
201
+ projects[0..3]
202
+ end
203
+ mock(bob).valid? {false}
204
+ bob
205
+ end
206
+
207
+ === stub.proxy
208
+ Intercept the return value of a method call.
209
+ The following example verifies render partial will be called and
210
+ renders the partial.
211
+
212
+ view = controller.template
213
+ stub.proxy(view).render(:partial => "user_info") do |html|
214
+ html.should include("Joe Smith")
215
+ html
216
+ end
217
+
218
+ === any_instance_of
219
+ Allows stubs to be added to all instances of a class. It works by binding to methods from the class itself, rather than the eigenclass.
220
+ This allows all instances (excluding instances with the method redefined in the eigenclass) to get the change.
221
+
222
+ Due to Ruby runtime limitations, mocks will not work as expected. It's not obviously feasible (without an ObjectSpace lookup) to support all of RR's methods (such as mocking).
223
+ ObjectSpace is not readily supported in jRuby, since it causes general slowness in the interpreter.
224
+ I'm of the opinion that test speed is more important than having mocks on all instances of a class.
225
+ If there is another solution, I'd be willing to add it.
226
+
227
+ any_instance_of(User) do |u|
228
+ stub(u).valid? {false}
229
+ end
230
+ # or
231
+ any_instance_of(User, :valid? => false)
232
+ # or
233
+ any_instance_of(User, :valid? => lambda {false})
234
+
235
+ === new_instance_of
236
+ Stubs the new method of the class and allows doubles to be bound to new instances.
237
+
238
+ Mocks can be used, because new instances are deterministically bound.
239
+
240
+ new_instance_of(User) do |u|
241
+ mock(u).valid? {false}
242
+ end
243
+
244
+ # Deprecated syntax
245
+ mock.instance_of(User).valid? {false}
246
+
247
+ === Spies
248
+
249
+ Adding a DoubleInjection to an Object + Method (done by stub, mock, or dont_allow) causes RR to record any method
250
+ invocations to the Object + method. Assertions can then be made on the recorded method calls.
251
+
252
+ ==== test/unit
253
+
254
+ subject = Object.new
255
+ stub(subject).foo
256
+ subject.foo(1)
257
+ assert_received(subject) {|subject| subject.foo(1)}
258
+ assert_received(subject) {|subject| subject.bar} # This fails
259
+
260
+ ==== rspec
261
+
262
+ subject = Object.new
263
+ stub(subject).foo
264
+ subject.foo(1)
265
+ subject.should have_received.foo(1)
266
+ subject.should have_received.bar # this fails
267
+
268
+ === Block Syntax
269
+ The block syntax has two modes
270
+ * A normal block mode with a DoubleDefinitionCreatorProxy argument
271
+
272
+ script = MyScript.new
273
+ mock(script) do |expect|
274
+ expect.system("cd #{RAILS_ENV}") {true}
275
+ expect.system("rake foo:bar") {true}
276
+ expect.system("rake baz") {true}
277
+ end
278
+
279
+ * An instance_eval mode where the DoubleDefinitionCreatorProxy is instance_evaled
280
+
281
+ script = MyScript.new
282
+ mock(script) do
283
+ system("cd #{RAILS_ENV}") {true}
284
+ system("rake foo:bar") {true}
285
+ system("rake baz") {true}
286
+ end
287
+
288
+ === Block Syntax with explicit DoubleDefinitionCreatorProxy argument
289
+
290
+
291
+ === Double Graphs
292
+ RR has a method-chaining api support for Double graphs. For example,
293
+ lets say you want an object to receive a method call to #foo, and have
294
+ the return value receive a method call to #bar.
295
+
296
+ In RR, you would do:
297
+ stub(object).foo.stub!.bar {:baz}
298
+ object.foo.bar # :baz
299
+ # or
300
+ stub(object).foo {stub!.bar {:baz}}
301
+ object.foo.bar # :baz
302
+ # or
303
+ bar = stub!.bar {:baz}
304
+ stub(object).foo {bar}
305
+ object.foo.bar # :baz
306
+
307
+ === Argument Wildcard matchers
308
+ ==== anything
309
+ mock(object).foobar(1, anything)
310
+ object.foobar(1, :my_symbol)
311
+
312
+ ==== is_a
313
+ mock(object).foobar(is_a(Time))
314
+ object.foobar(Time.now)
315
+
316
+ ==== numeric
317
+ mock(object).foobar(numeric)
318
+ object.foobar(99)
319
+
320
+ ==== boolean
321
+ mock(object).foobar(boolean)
322
+ object.foobar(false)
323
+
324
+ ==== duck_type
325
+ mock(object).foobar(duck_type(:walk, :talk))
326
+ arg = Object.new
327
+ def arg.walk; 'waddle'; end
328
+ def arg.talk; 'quack'; end
329
+ object.foobar(arg)
330
+
331
+ ==== Ranges
332
+ mock(object).foobar(1..10)
333
+ object.foobar(5)
334
+
335
+ ==== Regexps
336
+ mock(object).foobar(/on/)
337
+ object.foobar("ruby on rails")
338
+
339
+ ==== hash_including
340
+ mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF"))
341
+ object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"})
342
+
343
+ ==== satisfy
344
+ mock(object).foobar(satisfy {|arg| arg.length == 2})
345
+ object.foobar("xy")
346
+
347
+ ==== Writing your own Argument Matchers
348
+ Writing a custom argument wildcard matcher is not difficult. See
349
+ RR::WildcardMatchers for details.
350
+
351
+ === Invocation Amount Wildcard Matchers
352
+ ==== any_times
353
+ mock(object).method_name(anything).times(any_times) {return_value}
354
+
355
+ == Special Thanks To
356
+ With any development effort, there are countless people who have contributed to making it possible. We all are standing on the shoulders of giants.
357
+ If you have directly contributed to RR and I missed you in this list, please let me know and I will add you. Thanks!
358
+ * Andreas Haller for patches
359
+ * Aslak Hellesoy for Developing Rspec
360
+ * Bryan Helmkamp for patches
361
+ * Caleb Spare for patches
362
+ * Christopher Redinger for patches
363
+ * Dan North for syntax ideas
364
+ * Dave Astels for some BDD inspiration
365
+ * Dave Myron for a bug report
366
+ * David Chelimsky for encouragement to make the RR framework, for developing the Rspec mock framework, syntax ideas, and patches
367
+ * Daniel Sudol for identifing performance issues with RR
368
+ * Dmitry Ratnikov for patches
369
+ * Eugene Pimenov for patches
370
+ * Evan Phoenix for patches
371
+ * Felix Morio for pairing with me
372
+ * Gabriel Horner for patches
373
+ * Gavin Miller for patches
374
+ * Gerard Meszaros for his excellent book "xUnit Test Patterns"
375
+ * James Mead for developing Mocha
376
+ * Jeff Whitmire for documentation suggestions
377
+ * Jim Weirich for developing Flexmock, the first Terse ruby mock framework in Ruby
378
+ * Joe Ferris for patches
379
+ * Matthew O'Connor for patches and pairing with me
380
+ * Michael Niessner for patches and pairing with me
381
+ * Mike Mangino (from Elevated Rails) for patches and pairing with me
382
+ * Myron Marston for bug reports
383
+ * Nick Kallen for documentation suggestions, bug reports, and patches
384
+ * Nathan Sobo for various ideas and inspiration for cleaner and more expressive code
385
+ * Parker Thompson for pairing with me
386
+ * Phil Darnowsky for patches
387
+ * Pivotal Labs for sponsoring RR development
388
+ * Stephen Baker for Developing Rspec
389
+ * Tatsuya Ono for patches
390
+ * Tuomas Kareinen for a bug report