developwithpassion_fakes 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib",__FILE__)
3
+ require "developwithpassion_fakes/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "developwithpassion_fakes"
7
+ s.version = DevelopWithPassion::Fakes::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Develop With Passion®"]
10
+ s.email = ["open_source@developwithpassion.com"]
11
+ s.homepage = "http://www.developwithpassion.com"
12
+ s.summary = %q{Simple faking library}
13
+ s.description = %q{Faking library that allows inspection of received calls after they have been made. Also supports tracking calls with multiple argument sets.}
14
+ s.rubyforge_project = "developwithpassion_fakes"
15
+
16
+ s.files = `git ls-files | grep -P "^(dev|lib)"`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec-core"
23
+ s.add_development_dependency "rspec-expectations"
24
+ s.add_development_dependency "rake"
25
+ s.add_development_dependency "guard"
26
+ # s.add_runtime_dependency "rest-client"
27
+ end
@@ -0,0 +1,24 @@
1
+ module DevelopWithPassion
2
+ module Fakes
3
+ module ArgBehaviour
4
+ attr_accessor :return_value,:times_called
5
+
6
+ def and_return(item)
7
+ @return_value = item
8
+ end
9
+
10
+ def capture_args(args)
11
+ @times_called += 1
12
+ @called_args = args
13
+ end
14
+
15
+ def matches?(args)
16
+ return @args == args
17
+ end
18
+
19
+ def was_called_with?(args)
20
+ return @called_args == args
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ module DevelopWithPassion
2
+ module Fakes
3
+ class ArgSet
4
+ include ArgBehaviour
5
+
6
+ def initialize(args)
7
+ @args = args
8
+ @times_called = 0
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ module DevelopWithPassion
2
+ module Fakes
3
+ class Fake
4
+ def initialize(invocation_set = {})
5
+ @method_invocations = invocation_set
6
+ end
7
+
8
+ def method_missing(name,*args,&block)
9
+ return @method_invocations.has_key?(name.to_sym) ? @method_invocations[name.to_sym].invoke(args) : handle_unexpected_method_invocation(name,args,block)
10
+ end
11
+
12
+ def handle_unexpected_method_invocation(name,args,block)
13
+ method = stub(name.to_sym)
14
+ method.ignore_arg
15
+ return method.invoke(args)
16
+ end
17
+
18
+ def stub(symbol)
19
+ return @method_invocations[symbol] || @method_invocations[symbol] = MethodStub.new
20
+ end
21
+
22
+ def received(symbol)
23
+ return @method_invocations[symbol]
24
+ end
25
+
26
+ def never_received?(symbol)
27
+ return !@method_invocations.has_key?(symbol)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module DevelopWithPassion
2
+ module Fakes
3
+ class IgnoreSet
4
+ include ArgBehaviour
5
+ attr_reader :arg_sets
6
+
7
+ def initialize
8
+ @times_called = 0
9
+ @arg_sets = []
10
+ end
11
+
12
+ def matches?(args)
13
+ return true
14
+ end
15
+
16
+ def capture_args(args)
17
+ @times_called += 1
18
+ @arg_sets << args
19
+ end
20
+
21
+ def was_called_with?(args)
22
+ return @arg_sets.select{|set| set == args}.count > 0
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ module DevelopWithPassion
2
+ module Fakes
3
+ class MethodStub
4
+ def initialize(arg_sets = [])
5
+ @arg_sets = arg_sets
6
+ end
7
+
8
+ def with(*args)
9
+ return add_new_set(ArgSet.new(args))
10
+ end
11
+
12
+ def add_new_set(set)
13
+ @arg_sets << set
14
+ return set
15
+ end
16
+
17
+ def ignore_arg
18
+ return add_new_set(IgnoreSet.new)
19
+ end
20
+
21
+ def and_return(item)
22
+ ignore_arg.and_return(item)
23
+ end
24
+
25
+
26
+ def invoke(args)
27
+ set = @arg_sets.find{|item| item.matches?(args)} || ignore_arg
28
+ set.capture_args(args)
29
+ return set.return_value
30
+ end
31
+
32
+ def called_with(*args)
33
+ return @arg_sets.find{|item| item.was_called_with?(args)}
34
+ end
35
+
36
+ def times?(value)
37
+ total = @arg_sets.inject(0){|sum,item|sum += item.times_called}
38
+ return total == value
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,5 @@
1
+ module DevelopWithPassion
2
+ module Fakes
3
+ VERSION = "0.0.9"
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ require 'developwithpassion_fakes/arg_behaviour'
2
+ require 'developwithpassion_fakes/arg_set'
3
+ require 'developwithpassion_fakes/fake'
4
+ require 'developwithpassion_fakes/ignore_set'
5
+ require 'developwithpassion_fakes/method_stub'
6
+
7
+ module Kernel
8
+ def fake
9
+ return DevelopWithPassion::Fakes::Fake.new
10
+ end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: developwithpassion_fakes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-03-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec-core
16
- requirement: &70351808026040 !ruby/object:Gem::Requirement
16
+ requirement: &70230798759920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70351808026040
24
+ version_requirements: *70230798759920
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec-expectations
27
- requirement: &70351808025520 !ruby/object:Gem::Requirement
27
+ requirement: &70230798759400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70351808025520
35
+ version_requirements: *70230798759400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70351808025040 !ruby/object:Gem::Requirement
38
+ requirement: &70230798758940 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70351808025040
46
+ version_requirements: *70230798758940
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard
49
- requirement: &70351808024600 !ruby/object:Gem::Requirement
49
+ requirement: &70230798758500 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70351808024600
57
+ version_requirements: *70230798758500
58
58
  description: Faking library that allows inspection of received calls after they have
59
59
  been made. Also supports tracking calls with multiple argument sets.
60
60
  email:
@@ -63,12 +63,14 @@ executables: []
63
63
  extensions: []
64
64
  extra_rdoc_files: []
65
65
  files:
66
- - .gitignore
67
- - .rvmrc
68
- - Gemfile
69
- - Guardfile
70
- - README.md
71
- - Rakefile
66
+ - developwithpassion_fakes.gemspec
67
+ - lib/developwithpassion_fakes.rb
68
+ - lib/developwithpassion_fakes/arg_behaviour.rb
69
+ - lib/developwithpassion_fakes/arg_set.rb
70
+ - lib/developwithpassion_fakes/fake.rb
71
+ - lib/developwithpassion_fakes/ignore_set.rb
72
+ - lib/developwithpassion_fakes/method_stub.rb
73
+ - lib/developwithpassion_fakes/version.rb
72
74
  - spec/spec_helper.rb
73
75
  - spec/specs/arg_behaviour_spec.rb
74
76
  - spec/specs/arg_set_spec.rb
data/.gitignore DELETED
@@ -1,5 +0,0 @@
1
- blah.rb
2
- *.gem
3
- .bundle
4
- Gemfile.lock
5
- pkg/*
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm 1.9.3@developwithpassion_fakes --create
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec
data/Guardfile DELETED
@@ -1,5 +0,0 @@
1
- guard 'rspec' do
2
- watch(%r{^spec/.+_spec\.rb$})
3
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { "spec" }
5
- end
data/README.md DELETED
@@ -1,229 +0,0 @@
1
- #developwithpassion_fakes
2
-
3
- This is a really simple library to aid in AAA style testing. The primary driver for using this is to be able to make assertions on method calls to collaborators in actual assertions and not as part of setup. It is meant to be used to complement the current testing framework that you are using to aid in the creation of interaction based tests.
4
-
5
- Here is a simple example
6
-
7
- ```ruby
8
- class SomeClass
9
- def initialize(collaborator)
10
- @collaborator = collaborator
11
- end
12
- def run()
13
- @collaborator.send_message("Hi")
14
- end
15
- end
16
-
17
- describe SomeClass do
18
- context "when run" do
19
- let(:collaborator){DevelopWithPassion::Fakes::Fake.new}
20
- let(:sut){SomeClass.new(collaborator)}
21
-
22
- before(:each) do
23
- sut.run
24
- end
25
-
26
- it "should trigger its collaborator with the correct message" do
27
- collaborator.received(:send_message).called_with("Hi").should_not be_nil
28
- end
29
- end
30
- end
31
- ```
32
-
33
- ##Creating a new fake
34
-
35
- To create a new fake, simply leverage the fake method that is mixed into the Kernel module.
36
-
37
- ```ruby
38
- require 'developwithpassion_fakes'
39
-
40
- item = fake
41
- ```
42
-
43
- ##Specifying the behaviour of a fake
44
-
45
- When scaffolding fake return values, the library behaves almost identically to the way RSpec stubs work.
46
-
47
- ###Setup a method to return a value for a particular set of arguments
48
- ```ruby
49
- collaborator = fake
50
-
51
- collaborator.stub(:name_of_method).with(arg1,arg2,arg3).and_return(return_value)
52
- ```
53
-
54
- ###Setup a method to return a value regardless of the arguments it is called with
55
- ```ruby
56
- collaborator = fake
57
-
58
- #long handed way
59
- collaborator.stub(:name_of_method).ignore_arg.and_return(return_value)
60
-
61
- #preferred way
62
- collaborator.stub(:name_of_method).and_return(return_value)
63
- ```
64
-
65
- ###Setup different return values for different argument sets
66
- ```ruby
67
- collaborator = fake
68
-
69
- #Setup a return value for 1
70
- collaborator.stub(:method).with(1).and_return(first_return_value)
71
-
72
- #Setup a return value for 2
73
- collaborator.stub(:method).with(2).and_return(second_return_value)
74
-
75
- #Setup a return value when called with everything else
76
- #if you are going to use this, make sure it is used after
77
- #setting up return values for specific arguments
78
- collaborator.stub(:method).and_return(value_to_return_with_arguments_other_than_1_and_2)
79
- ```
80
-
81
- ##Verifying calls made to the fake
82
-
83
-
84
- ###Verifying when a call was made
85
-
86
- The primary purpose of the library is to help you in doing interaction style testing in a AAA style. Assume the following class is one you would like to test:
87
-
88
- ```ruby
89
- class ItemToTest
90
- def initialize(collaborator)
91
- @collaborator = collaborator
92
- end
93
-
94
- def run
95
- @collaborator.send_message("Hello World")
96
- end
97
- end
98
- ```
99
-
100
- ItemToTest is supposed to leverage its collaborator and calls its send_message method with the argument "Hello World". To verify this using AAA style, interaction testing you can do the following (I am using rspec, but you can use this with any testing library you wish):
101
-
102
- ```ruby
103
- describe ItemToTest do
104
- context "when run" do
105
- let(:collaborator){fake}
106
- let(:sut){ItemToTest.new(collaborator)}
107
-
108
- #I typically use a before block to specifically trigger the method that I am testing, so it cleanly
109
- #separates it from the assertions I will make later
110
- before(:each) do
111
- sut.run
112
- end
113
-
114
- it "should trigger its collaborator with the correct message" do
115
- collaborator.received(:send_message).called_with("Hello World").should_not be_nil
116
- end
117
- end
118
- end
119
- ```
120
- From the example above, you can see that we created the fake and did not need to scaffold it with any behaviour.
121
-
122
- ```ruby
123
- let(:collaborator){fake}
124
- ```
125
-
126
- You can also see that we are create our System Under Test (sut) and provide it the collaborator:
127
-
128
- ```ruby
129
- let(:sut){ItemToTest.new(collaborator)}
130
- ```
131
-
132
- We then proceed to invoke the method on the component we are testing
133
-
134
- ```ruby
135
- before(:each) do
136
- sut.run
137
- end
138
- ```
139
-
140
- Last but not least, we verify that our collaborator was invoked and with the right arguments:
141
-
142
- ```ruby
143
- it "should trigger its collaborator with the correct message" do
144
- collaborator.received(:send_message).called_with("Hello World").should_not be_nil
145
- end
146
- ```
147
-
148
- The nice thing is we can make the assertions after the fact, as opposed to needing to do them as part of setup, which I find is a much more natural way to read things, when you need to do this style of test. Notice that the called_with method return a method_invocation that will be nil if the call was not received. My recommendation would be to create a test utility method that allows you to leverage your testing frameworks assertion library to make the above assertion more terse. The
149
- following rspec sample demonstrates:
150
-
151
- ```ruby
152
- module RSpec
153
- Matchers.define :have_received do|symbol,*args|
154
- match do|fake|
155
- fake.received(symbol).called_with(*args) != nil
156
- end
157
- end
158
- end
159
- ```
160
-
161
- Using the above utility method turns the previous assertion:
162
-
163
- ```ruby
164
- collaborator.received(:send_message).called_with("Hello World").should_not be_nil
165
- ```
166
-
167
- To this:
168
-
169
- ```ruby
170
- collaborator.should have_received(:send_message,"Hello World")
171
- ```
172
-
173
- ###Verifying that a call should not have been made
174
-
175
- Currently verifying that a call was not made does not take the arguments into consideration. It just ensures that no calls to a particular named method were made. Here is an example:
176
-
177
- ```ruby
178
- class FirstCollaborator
179
- def send_message(message)
180
- end
181
- end
182
- class SecondCollaborator
183
- def send_message(message)
184
- end
185
- end
186
-
187
- class SomeItem
188
- def initialize
189
- @first = FirstCollaborator.new
190
- @second = SecondCollaborator.new
191
- end
192
-
193
- def first_behaviour
194
- @first.send_message("Hello")
195
- end
196
-
197
- def second_behaviour
198
- @second.send_message("World")
199
- end
200
- end
201
-
202
- describe SomeItem do
203
- context "when run" do
204
- let(:first){fake}
205
- let(:second){fake}
206
-
207
- before(:each) do
208
- FirstCollaborator.stub(:new).and_return(first)
209
- SecondCollaborator.stub(:new).and_return(second)
210
- @sut = SomeItem.new
211
- end
212
-
213
- before(:each) do
214
- @sut.first_behaviour
215
- end
216
-
217
- it "should trigger its collaborator with the correct message" do
218
- first.should have_received(:send_message,"Hello")
219
- end
220
-
221
- it "should not trigger its second collaborator" do
222
- #again, here would be another option to use a convienience test utility method
223
- second.never_received?(:send_message).should be_true
224
- end
225
- end
226
- end
227
- ```
228
-
229
- As you can see, in this test we want to verify that one collaborator was triggered and the other not.
data/Rakefile DELETED
@@ -1 +0,0 @@
1
- require "bundler/gem_tasks"