gimme 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+
4
+ # Add dependencies to develop your gem here.
5
+ # Include everything needed to run rake, tests, features, etc.
6
+ group :development do
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.5.2"
9
+ gem "rspec", ">= 1.3.1"
10
+ gem "cucumber", ">= 0.10.0"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ builder (3.0.0)
5
+ cucumber (0.10.0)
6
+ builder (>= 2.1.2)
7
+ diff-lcs (~> 1.1.2)
8
+ gherkin (~> 2.3.2)
9
+ json (~> 1.4.6)
10
+ term-ansicolor (~> 1.0.5)
11
+ diff-lcs (1.1.2)
12
+ gherkin (2.3.3)
13
+ json (~> 1.4.6)
14
+ git (1.2.5)
15
+ jeweler (1.5.2)
16
+ bundler (~> 1.0.0)
17
+ git (>= 1.2.5)
18
+ rake
19
+ json (1.4.6)
20
+ rake (0.8.7)
21
+ rspec (2.4.0)
22
+ rspec-core (~> 2.4.0)
23
+ rspec-expectations (~> 2.4.0)
24
+ rspec-mocks (~> 2.4.0)
25
+ rspec-core (2.4.0)
26
+ rspec-expectations (2.4.0)
27
+ diff-lcs (~> 1.1.2)
28
+ rspec-mocks (2.4.0)
29
+ term-ansicolor (1.0.5)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ bundler (~> 1.0.0)
36
+ cucumber (>= 0.10.0)
37
+ jeweler (~> 1.5.2)
38
+ rspec (>= 1.3.1)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Justin Searls
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,219 @@
1
+ # Gimme
2
+
3
+ Gimme is a very lightweight test double library for ruby. Written to be an opinionated (but not noisy) means to facilitate test-driving by enabling the author to specifying only what matters. But if could only feed Google one thing at this point, it would be: "[Mockito](http://mockito.org/) for Ruby"
4
+
5
+ You can read the (possibly stale) documentation below or the (fresh) [gimme Cucumber features on Relish](http://relishapp.com/searls/gimme)
6
+
7
+ ## Basics (or "What does it Gimme?" ... har.)
8
+
9
+ Gimme was originally named (well, for the first five hours of its life) "[Tabula Rasa](http://en.wikipedia.org/wiki/Tabula_rasa)," to very clearly indicate that it generates blank slate test doubles that lack any initial coupling with the concepts associated with specific [test double](http://xunitpatterns.com/Test%20Double.html) subtypes like mocks/stubs/fakes/spies/proxies. But in the end, "gimme" was easier to type than "tabula rasa", and I generally wanted to avoid test pattern lingo from leaking into the context and language of everybody's tests (hence no method named "stub").
10
+
11
+ Gimme doubles are most accurately identified as [test spies](http://xunitpatterns.com/Test%20Spy.html) in [this table discriminating the types](http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html) over at Gerard Meszaros' helpful xUnit patterns repository.
12
+
13
+ Gimme aims to enable you to write low-friction, low-specification tests that feel a little more like [Mockito](http://mockito.org/) than existing ruby test double libraries. Gimme should do whatever it can to help you isolate your SUT from its dependencies and then get out of your way. And if gimme can provide some fast-feedback about potential problems, it should try to do that too.
14
+
15
+ The few things it gives you:
16
+
17
+ * Many typical test double library features, like: stubbing & verifying methods, argument matchers for determining what gets stubbed and what to verify, and argument captors for inspecting stuff your [SUT](http://xunitpatterns.com/SUT.html) passes its dependencies
18
+ * Natural arrange-act-assert flow — meaning that you can call `verify` after you've interacted with your system under test.
19
+ * No stringy/symbolic representations of methods — similar to [rr](https://github.com/btakita/rr), gimme uses the blank slate pattern and `method_missing` to allow for minimally terse stubs and verifications
20
+ * Sometimes you know the class of a dependency of your SUT; when you do, gimme can try to help out by raising a NoMethodError when you attempt to stub or verify a method that the class doesn't respond to.
21
+ * Gimme won't punish you for not setting up an expectation for every interaction your SUT has with your test double, leaving you to verify exactly what matters to you in the context of what you're building; sometimes specifying the behavior of your SUT on a collaborator is significant, and sometimes it isn't.
22
+
23
+
24
+ ## The Disclaimer
25
+
26
+ Gimme is still in early development and a little light on features / hardening. While gimme should be enough to get started writing tests/specs, you'll likely run into edge cases that haven't been handled yet. If you're willing to try out gimme on your next toy project and either submit issues or pull requests when you run into issues, hopefully we can work together to make gimme a first-class test double framework in the Ruby community.
27
+
28
+ ## Getting started
29
+
30
+ ### Setting up
31
+ First, install the gem:
32
+
33
+ gem install gimme
34
+
35
+ Next, wherever you set up your test environment, require gimme:
36
+
37
+ require 'gimme'
38
+
39
+ ### Creating a double
40
+ Once you're in your test or spec, to create a test double.
41
+
42
+ If you know what what class your SUT will be depending on, you can specify it:
43
+
44
+ double = gimme(Object)
45
+
46
+ Or you could just create a generic double can stub/verify any method you need:
47
+
48
+ double = gimme()
49
+
50
+ ### Stubbing
51
+
52
+ Once you have your double, you can stub methods:
53
+
54
+ give(double).to_s { 'Pants' }
55
+ double.to_s #=> 'Pants'
56
+
57
+ give(double).equal?(:ninja) { true }
58
+ give(double).equal?(:fruit) { false }
59
+ double.equal?(:ninja) #=> true
60
+
61
+ You can also stub your double to raise an exception (or really, do anything in the passed block):
62
+
63
+ dog = gimme(Dog)
64
+ give(dog).holler_at(:mail_man) { raise LeashLawError }
65
+
66
+ dog.holler_at(:mail_man) # raises LeashLawError
67
+
68
+ ### Verifying
69
+
70
+ You can also verify interactions with your double
71
+
72
+ double.equal?(:fruit)
73
+
74
+ verify(double).equal?(:fruit) # passes verification (read: does nothing)
75
+ verify(double).equal?(:what_the) # fails verification (raises a Gimme::VerifyFailedError)
76
+
77
+ You can also specify how many times a specific invocation should have occurred (defaults to 1):
78
+
79
+ double.equal?(:fruit)
80
+ double.equal?(:fruit)
81
+
82
+ verify(double,2).equal?(:fruit)
83
+
84
+ ### Using Argument Matchers
85
+
86
+ Gimme includes several argument matchers which can be used to control which invocations will satisfy a particular stubbing or verification.
87
+
88
+ **anything**
89
+
90
+ Replacing an argument with `anything` will instantiate a `Gimme::Matchers::Anything` matcher, which always returns true, regardless of what gets passed in.
91
+
92
+ give(dog).walk_to(anything,5) { 'Park' }
93
+
94
+ walk_to(3,5) #=> 'Park'
95
+ walk_to('pants',5) #=> 'Park'
96
+ walk_to(nil,5) #=> 'Park'
97
+ walk_to(3,5.1) #=> nil
98
+
99
+ Matchers can be used when both stubbing and verifying a method. To verify on anything, you could:
100
+
101
+ dog.holler_at(true)
102
+
103
+ verify(dog).holler_at(anything) #=> passes verification
104
+
105
+ Other matchers:
106
+
107
+ **is_a(class)** — matches any arguments that are `kind_of?` the provided class
108
+ **any(class)** — same as `is_a`, but also matches nil
109
+ **boolean** — matches true or false arguments
110
+ **numeric** — matches numeric arguments
111
+
112
+ See the [cucumber feature for examples using these matchers](http://relishapp.com/searls/gimme/stubbing-with-matchers)
113
+
114
+ #### Writing Custom Argument Matchers
115
+
116
+ It's pretty easy to roll your own argument matchers as well. All you really need to do is pass as an argument to a method stubbed by `give` or verified by `verify` an object
117
+ that can respond to `matches?(arg)`. Maybe something like this would work (even though it'd be of questionable utility):
118
+
119
+ class Nothing
120
+ def matches?(arg)
121
+ false
122
+ end
123
+ end
124
+
125
+ give(dog).introduce_to(Nothing.new) { :meow } #b/c Nothing.matches? always returns false, :meow will never returned by the double.
126
+
127
+
128
+ ### Using Argument Captors
129
+
130
+ An instance of an argument `Captor`, when paired with the `capture` matcher, is a valuable way for your test to get at the values that your SUT passes to its collaborators. Often, classes are responsible for building objects to be ingested by their collaborators but for which normal state verification would either be difficult or nonsensical. Argument captors should only be necessary sparingly for most types of applications, but they're a handy tool to have in the toolbox.
131
+
132
+ In cases like these, a captor can be used to "capture" the real argument value that the system under test passes its collaborator. This pseudocode provides an example:
133
+
134
+ #arrange
135
+ searches_system = gimme(SearchesSystem)
136
+ sut = QueryExecutor.new(searches_sytem)
137
+ query_captor = Captor.new
138
+
139
+ #act
140
+ sut.submit_query_for_string("find dogs")
141
+
142
+ #assert
143
+ verify(searches_system).execute(capture(query_captor))
144
+ query_captor.value.table_name.should == "Dogs"
145
+
146
+
147
+ ### Suppressing NoMethodError
148
+
149
+ You may be reading this section because you got this message:
150
+
151
+ The Test Double of <Class Name> may not know how to respond to the '<Method Name>' method.
152
+ If you're confident that a real Kernel will know how to respond to '<Method Name>', then you can
153
+ invoke give! or verify! to suppress this error.
154
+
155
+ Whenever you stub or verify a method against a test double on a class, gimme will first verify that the method can be found on the class being
156
+ doubled. Since the vast majority of methods can be verified in this way, this default behavior is designed to provide fast failure.
157
+ This can be really handy, whether the cause is as simple as a transcription error of a method name from irb or as convoluted as an incorrect version of a dependency that lacks the method you expected.
158
+
159
+ However, because classes can be reopened and edited at runtime, often you'll outsmart gimme by knowing that a particular
160
+ method *will* be available on the class being doubled, even though it isn't *right now*.
161
+
162
+ For these situations, you could either (1) declare your double without a class argument (e.g. `gimme()` instead of `gimme(Dog)`), or (2) use `give!` and `verify!` to suppress the check that triggers the NoMethodError from being raised.
163
+
164
+ Here's an example where our Dog is again being doubled to facilitate some test, and even though the Dog class lacks a public `meow()` method, we happen to know that at runtime, the newest version of the `bananimals` gem will reopen Dog and add `meow()` to it.
165
+
166
+ dog = gimme(Dog)
167
+ give!(dog).meow { :purr }
168
+
169
+ dog.meow #=> :purr
170
+
171
+ We cam accomplish the same thing using `verify!`:
172
+
173
+ dog = gimme(Dog)
174
+
175
+ dog.meow
176
+
177
+ verify!(dog).meow #=> verification passes, even though gimme can't see the meow method.
178
+
179
+ ### gimme_next
180
+
181
+ To my knowledge, there isn't an established pattern or name for this next feature. Sometimes you may want your SUT to instantiate its own dependency. However, if you also want to achieve isolation from the implementation details of that dependency, you can use `gimme_next`.
182
+
183
+ Take this example method from the RSpec book:
184
+
185
+ def guess(guess)
186
+ marker = Marker.new(@secret,guess)
187
+ @output.puts '+'*marker.exact_match_count + '-'*marker.number_match_count
188
+ end
189
+
190
+ This can be tested with gimme in isolation (meaning that a real Marker object is never instantiated or invoked) like so:
191
+
192
+ describe '#guess' do
193
+ let(:marker) { gimme_next(Marker) }
194
+ before do
195
+ give(marker).exact_match_count { 4 }
196
+ give(marker).number_match_count { 0 }
197
+
198
+ game.guess('1234')
199
+ end
200
+
201
+ it 'instantiates a marker with the secret and guess' do
202
+ verify!(marker).initialize('1234','1234')
203
+ end
204
+
205
+ it 'outputs the exact matches followed by the number matches' do
206
+ verify(output).puts('++++')
207
+ end
208
+ end
209
+
210
+ As you can see above, `gimme_next(Marker)` will create a double just like `gimme()` would have, but it will also temporarily redefine the passed class's `new` method such that the next instantiation of that class (presumably by the SUT) will return the same double.*
211
+
212
+ This way we can clearly specify the SUT's interaction with the Marker class while maintaining its isolation.
213
+
214
+ *Subsequent instantiations of the passed class will continue to return normal instances.
215
+
216
+ ## About
217
+
218
+ ### Maintainers
219
+ * [Justin Searls](http://about.emw/searls), [Pillar Technology](http://pillartechnology.com)
data/README.rdoc ADDED
@@ -0,0 +1,22 @@
1
+ = gimme
2
+
3
+ gimme is a lightweight test double library for ruby
4
+
5
+ Project site: http://github.com/searls/gimme
6
+ Gimme features: http://relishapp.com/searls/gimme
7
+
8
+ == Contributing to gimme
9
+
10
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
11
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
12
+ * Fork the project
13
+ * Start a feature/bugfix branch
14
+ * Commit and push until you are happy with your contribution
15
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
16
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
17
+
18
+ == Copyright
19
+
20
+ Copyright (c) 2010 Justin Searls. See LICENSE.txt for
21
+ further details.
22
+
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "gimme"
16
+ gem.homepage = "http://github.com/searls/gimme"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{gimme — a low-specification test double library for Ruby}
19
+ gem.description = %Q{gimme attempts to bring to Ruby a test double workflow akin to Mockito in Java. Major distinctions include preserving arrange-act-assert in tests, fast feedback for methods the double's real counterpart may not know how to respond to, no string/symbolic representations of methods, argument captors, and strong opinions (weakly held). }
20
+ gem.email = "searls@gmail.com"
21
+ gem.authors = ["Justin Searls"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ gem.add_development_dependency "rspec", ">= 1.3.1"
26
+ gem.add_development_dependency "cucumber", ">= 0.10.0"
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'cucumber/rake/task'
31
+ Cucumber::Rake::Task.new do |t|
32
+ t.cucumber_opts = %w{--format pretty}
33
+ end
34
+
35
+ task :default => :cucumber
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "gimme #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.6
@@ -0,0 +1,12 @@
1
+ Feature: Capturing Arguments
2
+
3
+ As a test author
4
+ I want to capture the value of an argument passed to my test double
5
+ So that I can assert things about arguments my system under test passes to its collaborators
6
+
7
+ Scenario: capturing an argument
8
+ Given a new Dog test double
9
+ And a new argument captor
10
+ When I invoke holler_at(:panda)
11
+ Then I can verify holler_at(capture(@captor)) has been invoked 1 time
12
+ And the captor's value is :panda
@@ -0,0 +1,13 @@
1
+ Feature: Gimme Next
2
+
3
+ As a test author
4
+ I want a test double to stand-in for the next new'ing of a given class
5
+ so that I can isolate my SUT and stub & verify behavior of collaborators instantiated by the SUT
6
+
7
+ Scenario:
8
+ Given I create a double via gimme_next(Turtle)
9
+ When my SUT tries creating a real Turtle.new(:shell)
10
+ And I invoke swim
11
+ Then both the double and real object reference the same object
12
+ And I can verify! initialize(:shell) has been invoked 1 time
13
+ And I can verify swim has been invoked 1 time
@@ -0,0 +1,118 @@
1
+ include Gimme
2
+ METHOD_PATTERN = /([^\(]*)(\(.*\))?/
3
+
4
+ # Creating
5
+
6
+ Given /^a new (.*)\s?test double$/ do | type |
7
+ @double = type.empty? ? gimme : gimme(eval(type))
8
+ end
9
+
10
+ Given /^I create a double via gimme_next\((.*)\)$/ do |klass|
11
+ @double = gimme_next(eval(klass))
12
+ end
13
+
14
+
15
+ # Stubbing
16
+
17
+ When /^I stub #{METHOD_PATTERN} to return (.*)$/ do |method,args,result|
18
+ send_and_trap_error(NoMethodError,give(@double),method,args,result)
19
+ end
20
+
21
+ When /^I stub! #{METHOD_PATTERN} to return (.*)$/ do |method,args,result|
22
+ send_and_trap_error(NoMethodError,give!(@double),method,args,result)
23
+ end
24
+
25
+ When /^I stub #{METHOD_PATTERN} to raise (.*)$/ do |method,args,error_type|
26
+ sendish(give(@double),method,args,"raise #{error_type}")
27
+ end
28
+
29
+ # Invoking
30
+
31
+ Then /^invoking #{METHOD_PATTERN} returns (.*)$/ do |method,args,result|
32
+ sendish(@double,method,args).should == eval(result)
33
+ end
34
+
35
+ When /^I invoke #{METHOD_PATTERN}$/ do |method,args|
36
+ sendish(@double,method,args)
37
+ end
38
+
39
+ Given /^I do not invoke #{METHOD_PATTERN}$/ do |method,args|
40
+ end
41
+
42
+ Then /^invoking (.*) raises a (.*)$/ do |method,error_type|
43
+ expect_error(eval(error_type)) { sendish(@double,method) }
44
+ end
45
+
46
+ # Verifying
47
+
48
+ Then /^verifying #{METHOD_PATTERN} raises a (.*)$/ do |method,args,error_type|
49
+ expect_error(eval(error_type)) { verify(@double).send(method.to_sym) }
50
+ end
51
+
52
+ Then /^I can verify #{METHOD_PATTERN} has been invoked$/ do |method,args|
53
+ sendish(verify(@double),method,args)
54
+ end
55
+
56
+ Then /^I can verify #{METHOD_PATTERN} has been invoked (\d+) times?$/ do |method,args,times|
57
+ sendish(verify(@double,times.to_i),method,args)
58
+ end
59
+
60
+ Then /^I can verify! #{METHOD_PATTERN} has been invoked (\d+) times?$/ do |method,args,times|
61
+ sendish(verify!(@double,times.to_i),method,args)
62
+ end
63
+
64
+ #Captors
65
+
66
+ Given /^a new argument captor$/ do
67
+ @captor = Captor.new
68
+ end
69
+
70
+ Then /^the captor's value is (.*)$/ do |value|
71
+ @captor.value.should == eval(value)
72
+ end
73
+
74
+ # Exceptions
75
+ Then /^a (.*) is raised$/ do |error_type|
76
+ @error.should be_a_kind_of eval(error_type)
77
+ @error = nil
78
+ end
79
+
80
+ Then /^no error is raised$/ do
81
+ @error.should be nil
82
+ end
83
+
84
+ # Gimme Next
85
+
86
+ When /^my SUT tries creating a real (.*)$/ do |instantiation|
87
+ @real = eval(instantiation)
88
+ end
89
+
90
+ Then /^both the double and real object reference the same object$/ do
91
+ @real.__id__ == @double.__id__
92
+ end
93
+
94
+ # private
95
+
96
+ def send_and_trap_error(error_type,target,method,args=nil,result=nil)
97
+ begin
98
+ sendish(target,method,args,result)
99
+ rescue error_type => e
100
+ @error = e
101
+ end
102
+ end
103
+
104
+ def sendish(target,method,args=nil,result=nil)
105
+ s = "target.#{method}#{args}"
106
+ s += "{ #{result} }" if result
107
+ eval(s)
108
+ end
109
+
110
+ def expect_error(type,&block)
111
+ rescued = false
112
+ begin
113
+ yield
114
+ rescue type
115
+ rescued = true
116
+ end
117
+ rescued.should be true
118
+ end
@@ -0,0 +1,34 @@
1
+ Feature: basic stubbing
2
+
3
+ As a test author
4
+ I want to create a test double
5
+ so that I can stub method returns
6
+
7
+ Scenario Outline: stubbing
8
+ Given a new Dog test double
9
+ When I stub <method> to return <gives>
10
+ Then invoking <invocation> returns <returns>
11
+
12
+ Scenarios: no-arg methods
13
+ | method | gives | invocation | returns |
14
+ | to_s | 'something' | to_s | 'something' |
15
+ | purebred? | true | purebred? | true |
16
+
17
+ Scenarios: one-arg methods
18
+ | method | gives | invocation | returns |
19
+ | holler_at(true) | :ruff | holler_at(true) | :ruff |
20
+ | holler_at(true) | :ruff | holler_at(false) | nil |
21
+ | holler_at(true) | :ruff | holler_at(:panda) | nil |
22
+ | holler_at(true) | :ruff | holler_at(nil) | nil |
23
+
24
+ Scenarios: two-arg methods
25
+ | method | gives | invocation | returns |
26
+ | walk_to(1,2) | :park | walk_to(1,2) | :park |
27
+ | walk_to(1,2) | :park | walk_to(0.9,2) | nil |
28
+ | walk_to(1,2) | :park | walk_to(1,2.1) | nil |
29
+ | walk_to([1,5],[2,7]) | :park | walk_to([1],[5,2,7]) | nil |
30
+
31
+ Scenario:
32
+ Given a new Dog test double
33
+ When I stub purebred? to raise StandardError
34
+ Then invoking purebred? raises a StandardError
@@ -0,0 +1,60 @@
1
+ Feature: stubbing with matchers
2
+
3
+ As a test author
4
+ I want to be able to stub an invocation based on matchers' evaluations of the arguments
5
+ so that I don't need to redundantly stub things I don't care about
6
+
7
+ Scenario Outline: stubbing
8
+ Given a new Dog test double
9
+ When I stub <method> to return <gives>
10
+ Then invoking <invocation> returns <returns>
11
+
12
+ Scenarios: the anything matcher with a one-argument method
13
+ | method | gives | invocation | returns |
14
+ | introduce_to(anything) | 'Why Hello!' | introduce_to(Cat.new) | 'Why Hello!' |
15
+ | introduce_to(anything) | 'Why Hello!' | introduce_to(Dog.new) | 'Why Hello!' |
16
+ | introduce_to(anything) | 'Why Hello!' | introduce_to(nil) | 'Why Hello!' |
17
+
18
+ Scenarios: the anything matcher with a two-argument method
19
+ | method | gives | invocation | returns |
20
+ | walk_to(anything,5) | 'Park' | walk_to(5,5) | 'Park' |
21
+ | walk_to(anything,5) | 'Park' | walk_to('pants',5) | 'Park' |
22
+ | walk_to(anything,5) | 'Park' | walk_to(nil,5) | 'Park' |
23
+ | walk_to(anything,5) | 'Park' | walk_to(3,5.1) | nil |
24
+ | walk_to(3.123,anything) | 'Park' | walk_to(3.123,nil) | 'Park' |
25
+ | walk_to(anything,anything) | 'Park' | walk_to(3,5.1) | 'Park' |
26
+
27
+ Scenarios: the anything matcher with a variable-argument method (argument size must match; but I don't know if I like some of these…)
28
+ | method | gives | invocation | returns |
29
+ | eat(anything,:fish,anything) | :yum | eat(:cat,:fish,:mouse) | :yum |
30
+ | eat(anything,:fish,anything) | :yum | eat(:cat,:pants,:mouse) | nil |
31
+ | eat(anything) | :yum | eat(:cat,:pants) | nil |
32
+ | eat(:cat,anything) | :yum | eat(:cat) | nil |
33
+ | eat(:cat,anything) | :yum | eat(:cat,nil) | :yum |
34
+
35
+ Scenarios: the is_a matcher
36
+ | method | gives | invocation | returns |
37
+ | introduce_to(is_a(Animal)) | :howdy | introduce_to(Animal.new) | :howdy |
38
+ | introduce_to(is_a(Animal)) | :howdy | introduce_to(Cat.new) | :howdy |
39
+ | introduce_to(is_a(Animal)) | :howdy | introduce_to(Object.new) | nil |
40
+ | introduce_to(is_a(Animal)) | :howdy | introduce_to(nil) | nil |
41
+
42
+ Scenarios: the any matcher (like is_a but also matches nil)
43
+ | method | gives | invocation | returns |
44
+ | introduce_to(any(Animal)) | :howdy | introduce_to(Animal.new) | :howdy |
45
+ | introduce_to(any(Animal)) | :howdy | introduce_to(Cat.new) | :howdy |
46
+ | introduce_to(any(Animal)) | :howdy | introduce_to(Object.new) | nil |
47
+ | introduce_to(any(Animal)) | :howdy | introduce_to(nil) | :howdy |
48
+
49
+ Scenarios: the numeric matcher
50
+ | method | gives | invocation | returns |
51
+ | walk_to(numeric,numeric) | :hydrant | walk_to(1.498,8) | :hydrant |
52
+ | walk_to(numeric,numeric) | :hydrant | walk_to(1.498,'string') | nil |
53
+ | walk_to(numeric,numeric) | :hydrant | walk_to(1.498,nil) | nil |
54
+
55
+ Scenarios: the boolean matcher
56
+ | method | gives | invocation | returns |
57
+ | holler_at(boolean) | :ruff | holler_at(true) | :ruff |
58
+ | holler_at(boolean) | :ruff | holler_at(false) | :ruff |
59
+ | holler_at(boolean) | :ruff | holler_at('woof') | nil |
60
+ | holler_at(boolean) | :ruff | holler_at(nil) | nil |
@@ -0,0 +1,10 @@
1
+ Feature: Default returns
2
+
3
+ As a test author
4
+ I want my test double to have some sensible defaults
5
+ so that I do not find myself writing redundant/obvious stub code
6
+
7
+ Scenario: query? methods' default stubbing is false
8
+ Given a new Dog test double
9
+ Then invoking purebred? returns false
10
+ And invoking walk_to(1,1) returns nil