gimme 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +6 -4
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/gimme.gemspec +2 -2
- data/lib/gimme/captor.rb +2 -2
- data/lib/gimme/gives.rb +9 -9
- data/lib/gimme/matchers.rb +8 -8
- data/lib/gimme/method_resolver.rb +17 -7
- data/lib/gimme/test_double.rb +14 -11
- data/lib/gimme/verifies.rb +3 -3
- metadata +16 -16
data/README.markdown
CHANGED
@@ -4,6 +4,8 @@ Gimme is a very lightweight test double library for ruby. Written to be an opini
|
|
4
4
|
|
5
5
|
You can read the (possibly stale) documentation below or the (fresh) [gimme Cucumber features on Relish](http://relishapp.com/searls/gimme)
|
6
6
|
|
7
|
+
And here's a [blog post outlining the case for gimme](http://dougu.tumblr.com/post/6144302027/whats-wrong-with-rubys-test-doubles).
|
8
|
+
|
7
9
|
## Basics (or "What does it Gimme?" ... har.)
|
8
10
|
|
9
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").
|
@@ -104,10 +106,10 @@ Matchers can be used when both stubbing and verifying a method. To verify on any
|
|
104
106
|
|
105
107
|
Other matchers:
|
106
108
|
|
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
|
109
|
+
* **is_a(class)** — matches any arguments that are `kind_of?` the provided class
|
110
|
+
* **any(class)** — same as `is_a`, but also matches nil
|
111
|
+
* **boolean** — matches true or false arguments
|
112
|
+
* **numeric** — matches numeric arguments
|
111
113
|
|
112
114
|
See the [cucumber feature for examples using these matchers](http://relishapp.com/searls/gimme/stubbing-with-matchers)
|
113
115
|
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|
data/gimme.gemspec
CHANGED
@@ -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
|
+
s.version = "0.1.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Searls"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-06-04}
|
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 = [
|
data/lib/gimme/captor.rb
CHANGED
data/lib/gimme/gives.rb
CHANGED
@@ -9,19 +9,19 @@ module Gimme
|
|
9
9
|
|
10
10
|
def method_missing(sym, *args, &block)
|
11
11
|
sym = MethodResolver.resolve_sent_method(@double,sym,args,@raises_no_method_error)
|
12
|
-
|
12
|
+
|
13
13
|
@double.stubbings[sym] ||= {}
|
14
14
|
@double.stubbings[sym][args] = block if block
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def give(double)
|
19
|
-
|
20
|
-
|
19
|
+
Gimme::Gives.new(double)
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
22
|
+
def give!(double)
|
23
|
+
give = give(double)
|
24
|
+
give.raises_no_method_error = false
|
25
|
+
give
|
26
|
+
end
|
27
|
+
end
|
data/lib/gimme/matchers.rb
CHANGED
@@ -14,7 +14,7 @@ module Gimme
|
|
14
14
|
def anything
|
15
15
|
Gimme::Matchers::Anything.new
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
class IsA < Matcher
|
19
19
|
def initialize(cls)
|
20
20
|
@cls = cls
|
@@ -32,11 +32,11 @@ module Gimme
|
|
32
32
|
def matches?(arg)
|
33
33
|
arg == nil || arg.kind_of?(@cls)
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end
|
36
36
|
def any(cls)
|
37
37
|
Gimme::Matchers::Any.new(cls)
|
38
|
-
end
|
39
|
-
|
38
|
+
end
|
39
|
+
|
40
40
|
class Numeric < Matcher
|
41
41
|
def matches?(arg)
|
42
42
|
arg.kind_of?(Fixnum) || arg.kind_of?(Numeric) || arg.kind_of?(Float)
|
@@ -44,15 +44,15 @@ module Gimme
|
|
44
44
|
end
|
45
45
|
def numeric
|
46
46
|
Gimme::Matchers::Numeric.new
|
47
|
-
end
|
48
|
-
|
47
|
+
end
|
48
|
+
|
49
49
|
class Boolean < Matcher
|
50
50
|
def matches?(arg)
|
51
51
|
arg.kind_of?(TrueClass) || arg.kind_of?(FalseClass)
|
52
|
-
end
|
52
|
+
end
|
53
53
|
end
|
54
54
|
def boolean
|
55
55
|
Gimme::Matchers::Boolean.new
|
56
56
|
end
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end
|
@@ -3,21 +3,31 @@ module Gimme
|
|
3
3
|
class MethodResolver
|
4
4
|
def self.resolve_sent_method(double,sym,args,raises_no_method_error=true)
|
5
5
|
cls = double.cls
|
6
|
-
sym = args.shift if sym == :send
|
6
|
+
sym = args.shift if sym == :send
|
7
7
|
if cls && raises_no_method_error
|
8
|
-
if cls.private_methods.include?(sym
|
8
|
+
if cls.private_methods.include?(named(sym))
|
9
9
|
raise NoMethodError.new("#{sym} is a private method of your #{cls} test double, so stubbing/verifying it
|
10
10
|
might not be a great idea. If you want to try to stub or verify this method anyway, then you can
|
11
|
-
invoke give! or verify! to suppress this error.")
|
12
|
-
elsif !cls.instance_methods.include?(sym
|
13
|
-
raise NoMethodError.new("Your test double of #{cls} may not know how to respond to the '#{sym}' method.
|
11
|
+
invoke give! or verify! to suppress this error.")
|
12
|
+
elsif !cls.instance_methods.include?(named(sym))
|
13
|
+
raise NoMethodError.new("Your test double of #{cls} may not know how to respond to the '#{sym}' method.
|
14
14
|
If you're confident that a real #{cls} will know how to respond to '#{sym}', then you can
|
15
|
-
invoke give! or verify! to suppress this error.")
|
15
|
+
invoke give! or verify! to suppress this error.")
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
sym
|
20
20
|
end
|
21
|
+
|
22
|
+
if RUBY_VERSION >= "1.9.2"
|
23
|
+
def self.named(sym)
|
24
|
+
sym
|
25
|
+
end
|
26
|
+
else
|
27
|
+
def self.named(sym)
|
28
|
+
sym.to_s
|
29
|
+
end
|
30
|
+
end
|
21
31
|
end
|
22
32
|
|
23
|
-
end
|
33
|
+
end
|
data/lib/gimme/test_double.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Gimme
|
2
2
|
class BlankSlate
|
3
|
+
warning_level = $VERBOSE
|
4
|
+
$VERBOSE = nil
|
3
5
|
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
6
|
+
$VERBOSE = warning_level
|
4
7
|
end
|
5
8
|
|
6
9
|
class TestDouble < BlankSlate
|
@@ -16,24 +19,24 @@ module Gimme
|
|
16
19
|
|
17
20
|
def method_missing(sym, *args, &block)
|
18
21
|
sym = MethodResolver.resolve_sent_method(self,sym,args,false)
|
19
|
-
|
20
|
-
@invocations[sym] ||= {}
|
22
|
+
|
23
|
+
@invocations[sym] ||= {}
|
21
24
|
@stubbings[sym] ||= {}
|
22
|
-
|
25
|
+
|
23
26
|
@invocations[sym][args] = 1 + (@invocations[sym][args]||0)
|
24
27
|
|
25
28
|
matching_stub_block = nil
|
26
29
|
@stubbings[sym].each do |stub_args,stub_block|
|
27
30
|
matching = args.size == stub_args.size
|
28
|
-
args.each_index do |i|
|
31
|
+
args.each_index do |i|
|
29
32
|
unless args[i] == stub_args[i] || (stub_args[i].respond_to?(:matches?) && stub_args[i].matches?(args[i]))
|
30
33
|
matching = false
|
31
34
|
break
|
32
35
|
end
|
33
|
-
end
|
36
|
+
end
|
34
37
|
matching_stub_block = stub_block if matching
|
35
38
|
end
|
36
|
-
|
39
|
+
|
37
40
|
if matching_stub_block
|
38
41
|
matching_stub_block.call
|
39
42
|
elsif sym.to_s[-1,1] == '?'
|
@@ -43,21 +46,21 @@ module Gimme
|
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
46
|
-
|
49
|
+
|
47
50
|
def gimme(cls=nil)
|
48
51
|
Gimme::TestDouble.new(cls)
|
49
52
|
end
|
50
|
-
|
53
|
+
|
51
54
|
def gimme_next(cls)
|
52
55
|
double = Gimme::TestDouble.new(cls)
|
53
|
-
meta_class = class << cls; self; end
|
56
|
+
meta_class = class << cls; self; end
|
54
57
|
real_new = cls.method(:new)
|
55
58
|
meta_class.send(:define_method,:new) do |*args|
|
56
59
|
double.send(:initialize,*args)
|
57
60
|
meta_class.send(:define_method,:new,real_new) #restore :new on the class
|
58
61
|
double
|
59
|
-
end
|
62
|
+
end
|
60
63
|
double
|
61
64
|
end
|
62
65
|
|
63
|
-
end
|
66
|
+
end
|
data/lib/gimme/verifies.rb
CHANGED
@@ -10,7 +10,7 @@ module Gimme
|
|
10
10
|
|
11
11
|
def method_missing(sym, *args, &block)
|
12
12
|
sym = MethodResolver.resolve_sent_method(@double,sym,args,@raises_no_method_error)
|
13
|
-
|
13
|
+
|
14
14
|
#gosh, this loop sure looks familiar. just like another ugly loop I know. TODO.
|
15
15
|
invoked = 0
|
16
16
|
if @double.invocations[sym]
|
@@ -25,7 +25,7 @@ module Gimme
|
|
25
25
|
invoked += count if matching
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
if invoked != @times
|
30
30
|
raise Errors::VerificationFailedError.new("expected #{sym} to have been called with #{args}")
|
31
31
|
end
|
@@ -41,4 +41,4 @@ module Gimme
|
|
41
41
|
verify.raises_no_method_error = false
|
42
42
|
verify
|
43
43
|
end
|
44
|
-
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gimme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 7
|
10
|
+
version: 0.1.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Justin Searls
|
@@ -15,12 +15,12 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-06-04 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
prerelease: false
|
23
|
-
|
23
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
25
25
|
requirements:
|
26
26
|
- - ~>
|
@@ -32,11 +32,11 @@ dependencies:
|
|
32
32
|
- 0
|
33
33
|
version: 1.0.0
|
34
34
|
type: :development
|
35
|
+
requirement: *id001
|
35
36
|
name: bundler
|
36
|
-
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
prerelease: false
|
39
|
-
|
39
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -48,11 +48,11 @@ dependencies:
|
|
48
48
|
- 2
|
49
49
|
version: 1.5.2
|
50
50
|
type: :development
|
51
|
+
requirement: *id002
|
51
52
|
name: jeweler
|
52
|
-
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
prerelease: false
|
55
|
-
|
55
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
56
56
|
none: false
|
57
57
|
requirements:
|
58
58
|
- - ">="
|
@@ -64,11 +64,11 @@ dependencies:
|
|
64
64
|
- 1
|
65
65
|
version: 1.3.1
|
66
66
|
type: :development
|
67
|
+
requirement: *id003
|
67
68
|
name: rspec
|
68
|
-
version_requirements: *id003
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
prerelease: false
|
71
|
-
|
71
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ">="
|
@@ -80,11 +80,11 @@ dependencies:
|
|
80
80
|
- 0
|
81
81
|
version: 0.10.0
|
82
82
|
type: :development
|
83
|
+
requirement: *id004
|
83
84
|
name: cucumber
|
84
|
-
version_requirements: *id004
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
86
|
prerelease: false
|
87
|
-
|
87
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
88
88
|
none: false
|
89
89
|
requirements:
|
90
90
|
- - ">="
|
@@ -96,11 +96,11 @@ dependencies:
|
|
96
96
|
- 1
|
97
97
|
version: 1.3.1
|
98
98
|
type: :development
|
99
|
+
requirement: *id005
|
99
100
|
name: rspec
|
100
|
-
version_requirements: *id005
|
101
101
|
- !ruby/object:Gem::Dependency
|
102
102
|
prerelease: false
|
103
|
-
|
103
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
104
104
|
none: false
|
105
105
|
requirements:
|
106
106
|
- - ">="
|
@@ -112,8 +112,8 @@ dependencies:
|
|
112
112
|
- 0
|
113
113
|
version: 0.10.0
|
114
114
|
type: :development
|
115
|
+
requirement: *id006
|
115
116
|
name: cucumber
|
116
|
-
version_requirements: *id006
|
117
117
|
description: "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). "
|
118
118
|
email: searls@gmail.com
|
119
119
|
executables: []
|