gimme 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -4,6 +4,8 @@ source "http://rubygems.org"
4
4
  # Add dependencies to develop your gem here.
5
5
  # Include everything needed to run rake, tests, features, etc.
6
6
  group :development, :test do
7
+ gem 'pry'
8
+
7
9
  gem 'rdoc'
8
10
 
9
11
  gem "jeweler", "~> 1.5.2"
@@ -14,7 +16,7 @@ group :development, :test do
14
16
  gem "guard-cucumber", :require => false
15
17
  gem "simplecov", :require => false
16
18
  if RUBY_PLATFORM =~ /darwin/i
17
- gem "growl_notify"
19
+ gem "growl"
18
20
  gem "rb-fsevent", :require => false
19
21
  end
20
22
  end
@@ -2,6 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  builder (3.0.0)
5
+ coderay (1.0.5)
5
6
  cucumber (1.1.9)
6
7
  builder (>= 2.1.2)
7
8
  diff-lcs (>= 1.1.2)
@@ -13,8 +14,7 @@ GEM
13
14
  gherkin (2.9.0)
14
15
  json (>= 1.4.6)
15
16
  git (1.2.5)
16
- growl_notify (0.0.3)
17
- rb-appscript
17
+ growl (1.0.3)
18
18
  guard (1.0.0)
19
19
  ffi (>= 0.5.0)
20
20
  thor (~> 0.14.6)
@@ -28,9 +28,13 @@ GEM
28
28
  git (>= 1.2.5)
29
29
  rake
30
30
  json (1.6.5)
31
+ method_source (0.7.0)
31
32
  multi_json (1.1.0)
33
+ pry (0.9.8)
34
+ coderay (~> 1.0.5)
35
+ method_source (~> 0.7)
36
+ slop (>= 2.4.3, < 3)
32
37
  rake (0.9.2.2)
33
- rb-appscript (0.6.1)
34
38
  rb-fsevent (0.9.0)
35
39
  rdoc (3.12)
36
40
  json (~> 1.4)
@@ -48,6 +52,7 @@ GEM
48
52
  multi_json (~> 1.0)
49
53
  simplecov-html (~> 0.5.3)
50
54
  simplecov-html (0.5.3)
55
+ slop (2.4.3)
51
56
  term-ansicolor (1.0.7)
52
57
  thor (0.14.6)
53
58
 
@@ -56,10 +61,11 @@ PLATFORMS
56
61
 
57
62
  DEPENDENCIES
58
63
  cucumber
59
- growl_notify
64
+ growl
60
65
  guard-cucumber
61
66
  guard-rspec
62
67
  jeweler (~> 1.5.2)
68
+ pry
63
69
  rb-fsevent
64
70
  rdoc
65
71
  rspec
@@ -8,7 +8,7 @@ And here's a [blog post outlining the case for gimme](http://searls.test-double.
8
8
 
9
9
  ## Basics (or "What does it Gimme?" ... har.)
10
10
 
11
- 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").
11
+ 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").
12
12
 
13
13
  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.
14
14
 
@@ -44,35 +44,35 @@ Once you're in your test or spec, to create a test double.
44
44
  If you know what what class your SUT will be depending on, you can specify it:
45
45
 
46
46
  double = gimme(Object)
47
-
47
+
48
48
  Or you could just create a generic double can stub/verify any method you need:
49
49
 
50
50
  double = gimme()
51
-
52
- ### Stubbing
53
-
51
+
52
+ ### Stubbing
53
+
54
54
  Once you have your double, you can stub methods:
55
55
 
56
56
  give(double).to_s { 'Pants' }
57
57
  double.to_s #=> 'Pants'
58
-
58
+
59
59
  give(double).equal?(:ninja) { true }
60
- give(double).equal?(:fruit) { false }
60
+ give(double).equal?(:fruit) { false }
61
61
  double.equal?(:ninja) #=> true
62
-
62
+
63
63
  You can also stub your double to raise an exception (or really, do anything in the passed block):
64
64
 
65
65
  dog = gimme(Dog)
66
66
  give(dog).holler_at(:mail_man) { raise LeashLawError }
67
-
67
+
68
68
  dog.holler_at(:mail_man) # raises LeashLawError
69
69
 
70
- ### Verifying
71
-
72
- You can also verify interactions with your double
70
+ ### Verifying
71
+
72
+ You can also verify interactions with your double
73
73
 
74
74
  double.equal?(:fruit)
75
-
75
+
76
76
  verify(double).equal?(:fruit) # passes verification (read: does nothing)
77
77
  verify(double).equal?(:what_the) # fails verification (raises a Gimme::VerifyFailedError)
78
78
 
@@ -80,9 +80,9 @@ You can also specify how many times a specific invocation should have occurred (
80
80
 
81
81
  double.equal?(:fruit)
82
82
  double.equal?(:fruit)
83
-
83
+
84
84
  verify(double,2).equal?(:fruit)
85
-
85
+
86
86
  ### Using Argument Matchers
87
87
 
88
88
  Gimme includes several argument matchers which can be used to control which invocations will satisfy a particular stubbing or verification.
@@ -92,24 +92,24 @@ Gimme includes several argument matchers which can be used to control which invo
92
92
  Replacing an argument with `anything` will instantiate a `Gimme::Matchers::Anything` matcher, which always returns true, regardless of what gets passed in.
93
93
 
94
94
  give(dog).walk_to(anything,5) { 'Park' }
95
-
95
+
96
96
  walk_to(3,5) #=> 'Park'
97
97
  walk_to('pants',5) #=> 'Park'
98
- walk_to(nil,5) #=> 'Park'
98
+ walk_to(nil,5) #=> 'Park'
99
99
  walk_to(3,5.1) #=> nil
100
-
100
+
101
101
  Matchers can be used when both stubbing and verifying a method. To verify on anything, you could:
102
102
 
103
103
  dog.holler_at(true)
104
-
105
- verify(dog).holler_at(anything) #=> passes verification
106
-
107
- Other matchers:
108
-
104
+
105
+ verify(dog).holler_at(anything) #=> passes verification
106
+
107
+ Other matchers:
108
+
109
109
  * **is_a(class)** — matches any arguments that are `kind_of?` the provided class
110
110
  * **any(class)** — same as `is_a`, but also matches nil
111
111
  * **boolean** — matches true or false arguments
112
- * **numeric** — matches numeric arguments
112
+ * **numeric** — matches numeric arguments
113
113
 
114
114
  See the [cucumber feature for examples using these matchers](http://relishapp.com/searls/gimme/stubbing-with-matchers)
115
115
 
@@ -125,7 +125,7 @@ that can respond to `matches?(arg)`. Maybe something like this would work (even
125
125
  end
126
126
 
127
127
  give(dog).introduce_to(Nothing.new) { :meow } #b/c Nothing.matches? always returns false, :meow will never returned by the double.
128
-
128
+
129
129
 
130
130
  ### Using Argument Captors
131
131
 
@@ -140,23 +140,23 @@ In cases like these, a captor can be used to "capture" the real argument value t
140
140
 
141
141
  #act
142
142
  sut.submit_query_for_string("find dogs")
143
-
143
+
144
144
  #assert
145
145
  verify(searches_system).execute(capture(query_captor))
146
146
  query_captor.value.table_name.should == "Dogs"
147
147
 
148
-
148
+
149
149
  ### Suppressing NoMethodError
150
150
 
151
151
  You may be reading this section because you got this message:
152
152
 
153
- The Test Double of <Class Name> may not know how to respond to the '<Method Name>' method.
153
+ The Test Double of <Class Name> may not know how to respond to the '<Method Name>' method.
154
154
  If you're confident that a real Kernel will know how to respond to '<Method Name>', then you can
155
155
  invoke give! or verify! to suppress this error.
156
-
156
+
157
157
  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
158
158
  doubled. Since the vast majority of methods can be verified in this way, this default behavior is designed to provide fast failure.
159
- 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.
159
+ 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.
160
160
 
161
161
  However, because classes can be reopened and edited at runtime, often you'll outsmart gimme by knowing that a particular
162
162
  method *will* be available on the class being doubled, even though it isn't *right now*.
@@ -167,15 +167,15 @@ Here's an example where our Dog is again being doubled to facilitate some test,
167
167
 
168
168
  dog = gimme(Dog)
169
169
  give!(dog).meow { :purr }
170
-
170
+
171
171
  dog.meow #=> :purr
172
-
172
+
173
173
  We cam accomplish the same thing using `verify!`:
174
174
 
175
175
  dog = gimme(Dog)
176
-
176
+
177
177
  dog.meow
178
-
178
+
179
179
  verify!(dog).meow #=> verification passes, even though gimme can't see the meow method.
180
180
 
181
181
  ### gimme_next
@@ -185,7 +185,7 @@ To my knowledge, there isn't an established pattern or name for this next featur
185
185
  Take this example method from the RSpec book:
186
186
 
187
187
  def guess(guess)
188
- marker = Marker.new(@secret,guess)
188
+ marker = Marker.new(@secret,guess)
189
189
  @output.puts '+'*marker.exact_match_count + '-'*marker.number_match_count
190
190
  end
191
191
 
@@ -195,21 +195,21 @@ This can be tested with gimme in isolation (meaning that a real Marker object is
195
195
  let(:marker) { gimme_next(Marker) }
196
196
  before do
197
197
  give(marker).exact_match_count { 4 }
198
- give(marker).number_match_count { 0 }
198
+ give(marker).number_match_count { 0 }
199
199
 
200
200
  game.guess('1234')
201
201
  end
202
-
202
+
203
203
  it 'instantiates a marker with the secret and guess' do
204
204
  verify!(marker).initialize('1234','1234')
205
205
  end
206
-
206
+
207
207
  it 'outputs the exact matches followed by the number matches' do
208
208
  verify(output).puts('++++')
209
- end
209
+ end
210
210
  end
211
211
 
212
- 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.*
212
+ 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.*
213
213
 
214
214
  This way we can clearly specify the SUT's interaction with the Marker class while maintaining its isolation.
215
215
 
@@ -218,4 +218,4 @@ This way we can clearly specify the SUT's interaction with the Marker class whil
218
218
  ## About
219
219
 
220
220
  ### Maintainers
221
- * [Justin Searls](http://about.emw/searls), [Pillar Technology](http://pillartechnology.com)
221
+ * [Justin Searls](http://about.emw/searls), [test double](http://test-double.com)
data/Rakefile CHANGED
@@ -43,6 +43,11 @@ Cucumber::Rake::Task.new do |t|
43
43
  t.cucumber_opts = %w{--format progress}
44
44
  end
45
45
 
46
+ Cucumber::Rake::Task.new('cucumber:wip') do |t|
47
+ t.cucumber_opts = %w{--format progress --wip --tags @wip}
48
+ end
49
+
50
+
46
51
  require 'rspec/core/rake_task'
47
52
  RSpec::Core::RakeTask.new
48
53
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.2.0
@@ -26,7 +26,21 @@ When /^I stub #{METHOD_PATTERN} to raise (.*)$/ do |method,args,error_type|
26
26
  sendish(give(@double),method,args,"raise #{error_type}")
27
27
  end
28
28
 
29
- # Invoking
29
+ ## class stubbing
30
+ Given /^the (.*) class$/ do |cls|
31
+ @double = eval(cls)
32
+ end
33
+
34
+ When /^I reset Gimme$/ do
35
+ Gimme.reset
36
+ end
37
+
38
+ Then /^#{METHOD_PATTERN} no longer returns (.*)$/ do |method,args,result|
39
+ sendish(@double,method,args).should_not == eval(result)
40
+ end
41
+
42
+
43
+ # stubbing invocation
30
44
 
31
45
  Then /^invoking #{METHOD_PATTERN} returns (.*)$/ do |method,args,result|
32
46
  sendish(@double,method,args).should == eval(result)
@@ -0,0 +1,21 @@
1
+ @wip
2
+ Feature: stubbing class methods
3
+
4
+ In order to spec code that depends on Rails or other APIs that make
5
+ liberal use of class methods, I want to stub class methods
6
+ and see that the classes are restored after each spec run.
7
+
8
+
9
+ Scenario Outline: stubbing class method
10
+ Given the Possum class
11
+ When I stub <method> to return <gives>
12
+ Then invoking <invocation> returns <returns>
13
+
14
+ When I reset Gimme
15
+ Then <method> no longer returns <gives>
16
+
17
+ Scenarios: the anything matcher with a one-argument method
18
+ | method | gives | invocation | returns |
19
+ | crawl_to(anything) | '…' | crawl_to(Cat.new) | '…' |
20
+ | crawl_to(anything) | '…' | crawl_to(Dog.new) | '…' |
21
+ | crawl_to(anything) | '…' | crawl_to(nil) | '…' |
@@ -10,12 +10,20 @@ end
10
10
  class Animal
11
11
  end
12
12
 
13
+ class Possum
14
+ def self.sleep
15
+ end
16
+
17
+ def self.crawl_to(location)
18
+ end
19
+ end
20
+
13
21
  class Dog < Animal
14
22
  include Eater
15
-
23
+
16
24
  # to exercise stub & verify of attributes: matching(regex)
17
25
  attr_accessor :name
18
-
26
+
19
27
  def walk_to(x,y)
20
28
  'use me to exercise numeric matchers: numeric, less_than, greater_than, within_range'
21
29
  end
@@ -23,23 +31,23 @@ class Dog < Animal
23
31
  def introduce_to(animal)
24
32
  'use me to exercise identity matchers: anything, is_a(Animal), is_a(Cat), any(Animal), any(Dog)'
25
33
  end
26
-
34
+
27
35
  def holler_at(loudly)
28
36
  'use me to exercise: boolean'
29
37
  end
30
-
38
+
31
39
  def use_toys(hash_of_toys_and_actions)
32
40
  'use me to exercise: hash_including'
33
41
  end
34
-
42
+
35
43
  def clean_toys(array_of_toys)
36
44
  'use me to exercise: including'
37
45
  end
38
-
46
+
39
47
  def purebred?
40
48
  'stub me to return a boolean'
41
49
  end
42
-
50
+
43
51
  end
44
52
 
45
53
  class Cat < Animal
@@ -49,7 +57,7 @@ class Turtle < Animal
49
57
  def initialize(shell)
50
58
  @shell = shell
51
59
  end
52
-
60
+
53
61
  def swim
54
62
  end
55
63
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{gimme}
8
- s.version = "0.1.8"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Justin Searls}]
12
- s.date = %q{2012-02-25}
12
+ s.date = %q{2012-02-27}
13
13
  s.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). }
14
14
  s.email = %q{searls@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  "features/gimme_next.feature",
33
33
  "features/step_definitions/gimme_steps.rb",
34
34
  "features/stub_basic.feature",
35
+ "features/stub_class_methods.feature",
35
36
  "features/stub_matchers.feature",
36
37
  "features/stub_sensible_defaults.feature",
37
38
  "features/support/animals.rb",
@@ -44,17 +45,25 @@ Gem::Specification.new do |s|
44
45
  "lib/gimme-double.rb",
45
46
  "lib/gimme.rb",
46
47
  "lib/gimme/captor.rb",
48
+ "lib/gimme/dsl.rb",
47
49
  "lib/gimme/errors.rb",
48
50
  "lib/gimme/gives.rb",
51
+ "lib/gimme/gives_class_methods.rb",
52
+ "lib/gimme/invokes_satisfied_stubbing.rb",
49
53
  "lib/gimme/matchers.rb",
50
- "lib/gimme/method_resolver.rb",
54
+ "lib/gimme/reset.rb",
55
+ "lib/gimme/resolves_methods.rb",
51
56
  "lib/gimme/rspec_adapter.rb",
52
57
  "lib/gimme/test_double.rb",
53
58
  "lib/gimme/verifies.rb",
54
59
  "spec/gimme/captor_spec.rb",
55
60
  "spec/gimme/errors_spec.rb",
61
+ "spec/gimme/gives_class_methods_spec.rb",
56
62
  "spec/gimme/gives_spec.rb",
57
63
  "spec/gimme/matchers_spec.rb",
64
+ "spec/gimme/resolves_methods_spec.rb",
65
+ "spec/gimme/rspec_adapter_spec.rb",
66
+ "spec/gimme/shared_examples/shared_gives_examples.rb",
58
67
  "spec/gimme/test_double_spec.rb",
59
68
  "spec/gimme/verifies_spec.rb",
60
69
  "spec/spec_helper.rb"
@@ -67,8 +76,12 @@ Gem::Specification.new do |s|
67
76
  s.test_files = [
68
77
  "spec/gimme/captor_spec.rb",
69
78
  "spec/gimme/errors_spec.rb",
79
+ "spec/gimme/gives_class_methods_spec.rb",
70
80
  "spec/gimme/gives_spec.rb",
71
81
  "spec/gimme/matchers_spec.rb",
82
+ "spec/gimme/resolves_methods_spec.rb",
83
+ "spec/gimme/rspec_adapter_spec.rb",
84
+ "spec/gimme/shared_examples/shared_gives_examples.rb",
72
85
  "spec/gimme/test_double_spec.rb",
73
86
  "spec/gimme/verifies_spec.rb",
74
87
  "spec/spec_helper.rb"
@@ -78,6 +91,7 @@ Gem::Specification.new do |s|
78
91
  s.specification_version = 3
79
92
 
80
93
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
94
+ s.add_development_dependency(%q<pry>, [">= 0"])
81
95
  s.add_development_dependency(%q<rdoc>, [">= 0"])
82
96
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
83
97
  s.add_development_dependency(%q<rspec>, [">= 0"])
@@ -86,11 +100,12 @@ Gem::Specification.new do |s|
86
100
  s.add_development_dependency(%q<cucumber>, [">= 0"])
87
101
  s.add_development_dependency(%q<guard-cucumber>, [">= 0"])
88
102
  s.add_development_dependency(%q<simplecov>, [">= 0"])
89
- s.add_development_dependency(%q<growl_notify>, [">= 0"])
103
+ s.add_development_dependency(%q<growl>, [">= 0"])
90
104
  s.add_development_dependency(%q<rb-fsevent>, [">= 0"])
91
105
  s.add_development_dependency(%q<rspec>, [">= 1.3.1"])
92
106
  s.add_development_dependency(%q<cucumber>, [">= 0.10.0"])
93
107
  else
108
+ s.add_dependency(%q<pry>, [">= 0"])
94
109
  s.add_dependency(%q<rdoc>, [">= 0"])
95
110
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
96
111
  s.add_dependency(%q<rspec>, [">= 0"])
@@ -99,12 +114,13 @@ Gem::Specification.new do |s|
99
114
  s.add_dependency(%q<cucumber>, [">= 0"])
100
115
  s.add_dependency(%q<guard-cucumber>, [">= 0"])
101
116
  s.add_dependency(%q<simplecov>, [">= 0"])
102
- s.add_dependency(%q<growl_notify>, [">= 0"])
117
+ s.add_dependency(%q<growl>, [">= 0"])
103
118
  s.add_dependency(%q<rb-fsevent>, [">= 0"])
104
119
  s.add_dependency(%q<rspec>, [">= 1.3.1"])
105
120
  s.add_dependency(%q<cucumber>, [">= 0.10.0"])
106
121
  end
107
122
  else
123
+ s.add_dependency(%q<pry>, [">= 0"])
108
124
  s.add_dependency(%q<rdoc>, [">= 0"])
109
125
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
110
126
  s.add_dependency(%q<rspec>, [">= 0"])
@@ -113,7 +129,7 @@ Gem::Specification.new do |s|
113
129
  s.add_dependency(%q<cucumber>, [">= 0"])
114
130
  s.add_dependency(%q<guard-cucumber>, [">= 0"])
115
131
  s.add_dependency(%q<simplecov>, [">= 0"])
116
- s.add_dependency(%q<growl_notify>, [">= 0"])
132
+ s.add_dependency(%q<growl>, [">= 0"])
117
133
  s.add_dependency(%q<rb-fsevent>, [">= 0"])
118
134
  s.add_dependency(%q<rspec>, [">= 1.3.1"])
119
135
  s.add_dependency(%q<cucumber>, [">= 0.10.0"])