verified_double 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/CHANGELOG.markdown +8 -0
  2. data/README.md +21 -49
  3. data/features/CHANGELOG.markdown +8 -0
  4. data/features/accessor_method_contracts.feature +107 -0
  5. data/features/customizing_arguments_and_return_values.feature +2 -2
  6. data/features/readme.md +21 -49
  7. data/features/rspec_mock_compatibility.feature +230 -0
  8. data/features/step_definitions/verified_double_steps.rb +17 -0
  9. data/features/{verified_double.feature → verified_mocks.feature} +5 -6
  10. data/features/verified_stubs.feature +94 -0
  11. data/lib/verified_double.rb +25 -10
  12. data/lib/verified_double/matchers.rb +35 -0
  13. data/lib/verified_double/method_signature_value.rb +15 -1
  14. data/lib/verified_double/method_signatures_report.rb +55 -0
  15. data/lib/verified_double/recording_double.rb +33 -12
  16. data/lib/verified_double/relays_to_internal_double_returning_self.rb +12 -0
  17. data/lib/verified_double/version.rb +1 -1
  18. data/spec/spec_helper.rb +3 -4
  19. data/spec/unit_helper.rb +3 -2
  20. data/spec/verified_double/matchers_spec.rb +96 -0
  21. data/spec/verified_double/method_signature_value_spec.rb +35 -0
  22. data/spec/verified_double/method_signatures_report_spec.rb +214 -0
  23. data/spec/verified_double/parse_method_signature_spec.rb +5 -1
  24. data/spec/verified_double/recording_double_spec.rb +103 -30
  25. data/spec/verified_double_spec.rb +70 -7
  26. data/verified_double.gemspec +0 -2
  27. metadata +17 -38
  28. data/lib/verified_double/get_registered_signatures.rb +0 -11
  29. data/lib/verified_double/get_unverified_signatures.rb +0 -13
  30. data/lib/verified_double/get_verified_signatures.rb +0 -17
  31. data/lib/verified_double/output_unverified_signatures.rb +0 -18
  32. data/lib/verified_double/report_unverified_signatures.rb +0 -16
  33. data/lib/verified_double/verify_doubles_service.rb +0 -15
  34. data/spec/verified_double/get_registered_signatures_spec.rb +0 -42
  35. data/spec/verified_double/get_unverified_signatures_spec.rb +0 -52
  36. data/spec/verified_double/get_verified_signatures_spec.rb +0 -63
  37. data/spec/verified_double/output_unverified_signatures_spec.rb +0 -58
  38. data/spec/verified_double/report_unverified_signatures_spec.rb +0 -57
  39. data/spec/verified_double/verify_doubles_service_spec.rb +0 -24
@@ -1,3 +1,11 @@
1
+ 0.1.0 - 2013-06-24
2
+ ------------------
3
+
4
+ * [#3] Pass Scenario: Verifying mocks for accessors.
5
+ * [#3] Pass Scenario: Verifying mocks for readers
6
+ * [#5] Remove rspec-fire dependency.
7
+ * [#5] Use VerifiedDouble to mock and stub doubles in own tests.
8
+
1
9
  0.0.2 - 2013-06-22
2
10
  ------------------
3
11
 
data/README.md CHANGED
@@ -1,65 +1,37 @@
1
1
  # VerifiedDouble
2
2
 
3
- VerifiedDouble would record any mock made in the test suite. It
4
- would then verify if the mock is valid by checking if there is a test
5
- against it.
3
+ [![Build Status](https://travis-ci.org/gsmendoza/verified_double.png)](https://travis-ci.org/gsmendoza/verified_double)
6
4
 
7
- For example, let's say I mocked the save method of a model like so:
5
+ VerifiedDouble verifies mocks made in the test suite by checking if there are tests against them.
6
+
7
+ For example, let's say I mocked the created_at method of a model like this:
8
8
 
9
9
  item = VerifiedDouble.of_instance(Item)
10
- item.should_receive(:save).and_return(true)
10
+ item.should_receive(:created_at).and_return(Time.now)
11
11
 
12
- Calling `VerifiedDouble.of_instance` would record the :save interaction on
13
- item. When running the tests, the gem would look for a test that
14
- confirms if you can indeed call #save on Item. The test should also
15
- ensure that the method indeed returns a boolean value. Since this is hard
16
- to automate, the gem would just look for a test with the tag saying it
17
- verifies that contract:
12
+ The item double records its :created_at call. When
13
+ running the tests, the gem looks for a test that confirms if you can
14
+ indeed call #created_at on Item. The test should also ensure that the method
15
+ returns a Time object. Since this is hard to automate, the gem just looks
16
+ for a test with a tag saying it verifies that contract:
18
17
 
19
- it "tests something", verifies_contract: 'Item#save => Boolean' do
18
+ it "tests something", verifies_contract: 'Item#created_at()=>Time' do
20
19
  #...
21
20
  end
22
21
 
23
- If this test does not exist, the gem would complain that the mock is not
22
+ If this test does not exist, the gem will complain that the mock is not
24
23
  verified.
25
24
 
26
- This is an implementation of [contract tests](http://www.infoq.com/presentations/integration-tests-scam).
27
- Notes about the presentation [here](http://www.beletsky.net/2010/10/agileee-2010-j-b-rainsberger-integrated.html).
28
-
29
- There's already a gem that implements contract tests
30
- ([bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/contract-tests)).
31
- However, I think there's room for an alternative because:
32
-
33
- 1. It's not clear from the Bogus [documentation](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/contract-tests/contract-tests-with-mocks)
34
- whether the gem verifies actual arguments/return values or just the types of those
35
- values. While the argument/return types are enough in most cases, sometimes
36
- the actual argument/return values are important. For example, if I mock
37
- Item.where(conditions), the actual conditions are important in
38
- verifying the validity of the where call.
39
-
40
- 2. [By design](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/fakes/faking-existing-classes#fakes-have-null-object-semantics),
41
- a Bogus fake would return itself to all its methods. I prefer rspec-mock's
42
- approach of raising an error if a method is not declared as part of the
43
- double, since this raises errors earlier than later.
44
-
45
- ## Installation
46
-
47
- Add this line to your application's Gemfile:
48
-
49
- gem 'verified_double'
50
-
51
- And then execute:
52
-
53
- $ bundle
25
+ More information at https://www.relishapp.com/gsmendoza/verified-double.
54
26
 
55
- Or install it yourself as:
27
+ References
28
+ ----------
56
29
 
57
- $ gem install verified_double
30
+ 1. http://www.confreaks.com/videos/2452-railsconf2013-the-magic-tricks-of-testing
31
+ 2. https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/contract-tests
32
+ 3. http://www.infoq.com/presentations/integration-tests-scam
58
33
 
59
- ## Contributing
34
+ Special thanks
35
+ --------------
60
36
 
61
- 1. Fork it
62
- 2. Create your feature branch (`git checkout -b my-new-feature`)
63
- 3. Commit your changes (`git commit -am 'Add some feature'`)
64
- 4. Push to the branch (`git push origin my-new-feature`)
65
- 5. Create new Pull Request
37
+ To @anathematic and [Inner Core Designs](http://icdesign.com.au) for sponsoring this gem :)
@@ -1,3 +1,11 @@
1
+ 0.1.0 - 2013-06-24
2
+ ------------------
3
+
4
+ * [#3] Pass Scenario: Verifying mocks for accessors.
5
+ * [#3] Pass Scenario: Verifying mocks for readers
6
+ * [#5] Remove rspec-fire dependency.
7
+ * [#5] Use VerifiedDouble to mock and stub doubles in own tests.
8
+
1
9
  0.0.2 - 2013-06-22
2
10
  ------------------
3
11
 
@@ -0,0 +1,107 @@
1
+ Feature: 05. Accessor method contracts
2
+ As a developer
3
+ I want it to easy to verify contracts for accessor methods
4
+
5
+ Background:
6
+ Given the following classes:
7
+ """
8
+ class ObjectUnderTest
9
+ def do_something(collaborator)
10
+ collaborator.value
11
+ end
12
+ end
13
+
14
+ class Collaborator
15
+ attr_accessor :value
16
+ end
17
+
18
+ class SomeValue
19
+ end
20
+ """
21
+
22
+ And the test suite includes VerifiedDouble to verify doubles with accessor methods:
23
+ """
24
+ require 'verified_double'
25
+ require 'main'
26
+
27
+ RSpec.configure do |config|
28
+ config.include VerifiedDouble::Matchers
29
+
30
+ config.after :suite do
31
+ VerifiedDouble.report_unverified_signatures(self)
32
+ end
33
+ end
34
+ """
35
+
36
+ Scenario: Verifying mocks for accessors
37
+ Given a test that uses VerifiedDouble to stub an object:
38
+ """
39
+ require 'spec_helper'
40
+ describe ObjectUnderTest do
41
+ let(:value) { SomeValue.new }
42
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator', value: value) }
43
+
44
+ it "tests something" do
45
+ ObjectUnderTest.new.do_something(instance_double)
46
+ end
47
+ end
48
+ """
49
+
50
+ And the test suite has a contract test for the stub:
51
+ """
52
+ require 'spec_helper'
53
+
54
+ describe Collaborator do
55
+ it { should verify_accessor_contract('Collaborator#value=>SomeValue') }
56
+ end
57
+ """
58
+
59
+ When I run the test suite
60
+ Then I should not see any output saying the stub is unverified
61
+
62
+ Scenario: Verifying mocks for readers
63
+ Given the following classes:
64
+ """
65
+ class ObjectUnderTest
66
+ def do_something(collaborator)
67
+ collaborator.value
68
+ end
69
+ end
70
+
71
+ class Collaborator
72
+ attr_reader :value
73
+
74
+ def initialize(value)
75
+ @value = value
76
+ end
77
+ end
78
+
79
+ class SomeValue
80
+ end
81
+ """
82
+
83
+ And a test that uses VerifiedDouble to stub an object:
84
+ """
85
+ require 'spec_helper'
86
+ describe ObjectUnderTest do
87
+ let(:value) { SomeValue.new }
88
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator', value: value) }
89
+
90
+ it "tests something" do
91
+ ObjectUnderTest.new.do_something(instance_double)
92
+ end
93
+ end
94
+ """
95
+
96
+ And the test suite has a contract test for the stub:
97
+ """
98
+ require 'spec_helper'
99
+
100
+ describe Collaborator do
101
+ subject { described_class.new(SomeValue.new) }
102
+ it { should verify_reader_contract('Collaborator#value=>SomeValue') }
103
+ end
104
+ """
105
+
106
+ When I run the test suite
107
+ Then I should not see any output saying the stub is unverified
@@ -1,4 +1,4 @@
1
- Feature: Customizing arguments and return values
1
+ Feature: 04. Customizing arguments and return values
2
2
  As a developer
3
3
  I want the ability to make contract arguments and return values more or less specific
4
4
 
@@ -24,7 +24,7 @@ Feature: Customizing arguments and return values
24
24
 
25
25
  RSpec.configure do |config|
26
26
  config.after :suite do
27
- VerifiedDouble::ReportUnverifiedSignatures.new(VerifiedDouble.registry, self).execute
27
+ VerifiedDouble.report_unverified_signatures(self)
28
28
  end
29
29
  end
30
30
  """
@@ -1,65 +1,37 @@
1
1
  # VerifiedDouble
2
2
 
3
- VerifiedDouble would record any mock made in the test suite. It
4
- would then verify if the mock is valid by checking if there is a test
5
- against it.
3
+ [![Build Status](https://travis-ci.org/gsmendoza/verified_double.png)](https://travis-ci.org/gsmendoza/verified_double)
6
4
 
7
- For example, let's say I mocked the save method of a model like so:
5
+ VerifiedDouble verifies mocks made in the test suite by checking if there are tests against them.
6
+
7
+ For example, let's say I mocked the created_at method of a model like this:
8
8
 
9
9
  item = VerifiedDouble.of_instance(Item)
10
- item.should_receive(:save).and_return(true)
10
+ item.should_receive(:created_at).and_return(Time.now)
11
11
 
12
- Calling `VerifiedDouble.of_instance` would record the :save interaction on
13
- item. When running the tests, the gem would look for a test that
14
- confirms if you can indeed call #save on Item. The test should also
15
- ensure that the method indeed returns a boolean value. Since this is hard
16
- to automate, the gem would just look for a test with the tag saying it
17
- verifies that contract:
12
+ The item double records its :created_at call. When
13
+ running the tests, the gem looks for a test that confirms if you can
14
+ indeed call #created_at on Item. The test should also ensure that the method
15
+ returns a Time object. Since this is hard to automate, the gem just looks
16
+ for a test with a tag saying it verifies that contract:
18
17
 
19
- it "tests something", verifies_contract: 'Item#save => Boolean' do
18
+ it "tests something", verifies_contract: 'Item#created_at()=>Time' do
20
19
  #...
21
20
  end
22
21
 
23
- If this test does not exist, the gem would complain that the mock is not
22
+ If this test does not exist, the gem will complain that the mock is not
24
23
  verified.
25
24
 
26
- This is an implementation of [contract tests](http://www.infoq.com/presentations/integration-tests-scam).
27
- Notes about the presentation [here](http://www.beletsky.net/2010/10/agileee-2010-j-b-rainsberger-integrated.html).
28
-
29
- There's already a gem that implements contract tests
30
- ([bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/contract-tests)).
31
- However, I think there's room for an alternative because:
32
-
33
- 1. It's not clear from the Bogus [documentation](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/contract-tests/contract-tests-with-mocks)
34
- whether the gem verifies actual arguments/return values or just the types of those
35
- values. While the argument/return types are enough in most cases, sometimes
36
- the actual argument/return values are important. For example, if I mock
37
- Item.where(conditions), the actual conditions are important in
38
- verifying the validity of the where call.
39
-
40
- 2. [By design](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/fakes/faking-existing-classes#fakes-have-null-object-semantics),
41
- a Bogus fake would return itself to all its methods. I prefer rspec-mock's
42
- approach of raising an error if a method is not declared as part of the
43
- double, since this raises errors earlier than later.
44
-
45
- ## Installation
46
-
47
- Add this line to your application's Gemfile:
48
-
49
- gem 'verified_double'
50
-
51
- And then execute:
52
-
53
- $ bundle
25
+ More information at https://www.relishapp.com/gsmendoza/verified-double.
54
26
 
55
- Or install it yourself as:
27
+ References
28
+ ----------
56
29
 
57
- $ gem install verified_double
30
+ 1. http://www.confreaks.com/videos/2452-railsconf2013-the-magic-tricks-of-testing
31
+ 2. https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/contract-tests
32
+ 3. http://www.infoq.com/presentations/integration-tests-scam
58
33
 
59
- ## Contributing
34
+ Special thanks
35
+ --------------
60
36
 
61
- 1. Fork it
62
- 2. Create your feature branch (`git checkout -b my-new-feature`)
63
- 3. Commit your changes (`git commit -am 'Add some feature'`)
64
- 4. Push to the branch (`git push origin my-new-feature`)
65
- 5. Create new Pull Request
37
+ To @anathematic and [Inner Core Designs](http://icdesign.com.au) for sponsoring this gem :)
@@ -0,0 +1,230 @@
1
+ Feature: 03. Rspec Mock compatibility
2
+ As a developer
3
+ I want VerifiedDouble to work with Rspec Mock API
4
+
5
+ Background:
6
+ Given the following classes:
7
+ """
8
+ class ObjectUnderTest
9
+ def do_something(collaborator, input)
10
+ collaborator.some_method(input)
11
+ end
12
+
13
+ def do_something_twice(collaborator, input)
14
+ collaborator.some_method(input)
15
+ collaborator.some_method(input)
16
+ end
17
+ end
18
+
19
+ class Collaborator
20
+ def some_method(input)
21
+ end
22
+ end
23
+
24
+ class SomeError < Exception
25
+ end
26
+
27
+ class SomeInput
28
+ end
29
+
30
+ class SomeOutput
31
+ end
32
+ """
33
+
34
+ And the test suite has a contract test for the mock:
35
+ """
36
+ require 'spec_helper'
37
+
38
+ describe 'Collaborator' do
39
+ it "tests something", verifies_contract: 'Collaborator#some_method(SomeInput)=>SomeOutput' do
40
+ # do nothing
41
+ end
42
+ end
43
+ """
44
+
45
+ And the test suite has an after(:suite) callback asking VerifiedDouble to report unverified doubles:
46
+ """
47
+ require 'verified_double'
48
+ require 'main'
49
+
50
+ RSpec.configure do |config|
51
+ config.after :suite do
52
+ VerifiedDouble.report_unverified_signatures(self)
53
+ end
54
+ end
55
+ """
56
+
57
+ Scenario: once
58
+ Given a test that uses VerifiedDouble to mock an object:
59
+ """
60
+ require 'spec_helper'
61
+ describe ObjectUnderTest do
62
+ let(:input) { SomeInput.new }
63
+ let(:output) { SomeOutput.new }
64
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
65
+
66
+ it "tests something" do
67
+ instance_double.should_receive(:some_method).with(input).once.and_return(output)
68
+ ObjectUnderTest.new.do_something(instance_double, input)
69
+ end
70
+ end
71
+ """
72
+
73
+ When I run the test suite
74
+ Then I should not see any output saying the stub is unverified
75
+
76
+ Scenario: twice
77
+ Given a test that uses VerifiedDouble to mock an object:
78
+ """
79
+ require 'spec_helper'
80
+ describe ObjectUnderTest do
81
+ let(:input) { SomeInput.new }
82
+ let(:output) { SomeOutput.new }
83
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
84
+
85
+ it "tests something" do
86
+ instance_double.should_receive(:some_method).with(input).twice.and_return(output)
87
+ ObjectUnderTest.new.do_something_twice(instance_double, input)
88
+ end
89
+ end
90
+ """
91
+
92
+ When I run the test suite
93
+ Then I should not see any output saying the stub is unverified
94
+
95
+ Scenario: exactly
96
+ Given a test that uses VerifiedDouble to mock an object:
97
+ """
98
+ require 'spec_helper'
99
+ describe ObjectUnderTest do
100
+ let(:input) { SomeInput.new }
101
+ let(:output) { SomeOutput.new }
102
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
103
+
104
+ it "tests something" do
105
+ instance_double.should_receive(:some_method).with(input).exactly(1).and_return(output)
106
+ ObjectUnderTest.new.do_something(instance_double, input)
107
+ end
108
+ end
109
+ """
110
+
111
+ When I run the test suite
112
+ Then I should not see any output saying the stub is unverified
113
+
114
+ Scenario: at_least
115
+ Given a test that uses VerifiedDouble to mock an object:
116
+ """
117
+ require 'spec_helper'
118
+ describe ObjectUnderTest do
119
+ let(:input) { SomeInput.new }
120
+ let(:output) { SomeOutput.new }
121
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
122
+
123
+ it "tests something" do
124
+ instance_double.should_receive(:some_method).with(input).at_least(:once).and_return(output)
125
+ ObjectUnderTest.new.do_something(instance_double, input)
126
+ end
127
+ end
128
+ """
129
+
130
+ When I run the test suite
131
+ Then I should not see any output saying the stub is unverified
132
+
133
+ Scenario: at_most
134
+ Given a test that uses VerifiedDouble to mock an object:
135
+ """
136
+ require 'spec_helper'
137
+ describe ObjectUnderTest do
138
+ let(:input) { SomeInput.new }
139
+ let(:output) { SomeOutput.new }
140
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
141
+
142
+ it "tests something" do
143
+ instance_double.should_receive(:some_method).with(input).at_most(:once).and_return(output)
144
+ ObjectUnderTest.new.do_something(instance_double, input)
145
+ end
146
+ end
147
+ """
148
+
149
+ When I run the test suite
150
+ Then I should not see any output saying the stub is unverified
151
+
152
+ Scenario: any_number_of_times
153
+ Given a test that uses VerifiedDouble to mock an object:
154
+ """
155
+ require 'spec_helper'
156
+ describe ObjectUnderTest do
157
+ let(:input) { SomeInput.new }
158
+ let(:output) { SomeOutput.new }
159
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
160
+
161
+ it "tests something" do
162
+ instance_double.should_receive(:some_method).with(input).any_number_of_times.and_return(output)
163
+ ObjectUnderTest.new.do_something(instance_double, input)
164
+ end
165
+ end
166
+ """
167
+
168
+ When I run the test suite
169
+ Then I should not see any output saying the stub is unverified
170
+
171
+ Scenario: and_raise
172
+ Given a test that uses VerifiedDouble to mock an object:
173
+ """
174
+ require 'spec_helper'
175
+ describe ObjectUnderTest do
176
+ let(:error) { SomeError.new }
177
+ let(:input) { SomeInput.new }
178
+ let(:output) { SomeOutput.new }
179
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
180
+
181
+ it "tests something" do
182
+ instance_double.should_receive(:some_method).with(input).and_raise(error)
183
+ expect { ObjectUnderTest.new.do_something(instance_double, input) }.to raise_error(error)
184
+ end
185
+ end
186
+ """
187
+
188
+ And the test suite has a contract test for the mock:
189
+ """
190
+ require 'spec_helper'
191
+
192
+ describe 'Collaborator' do
193
+ it "tests something", verifies_contract: 'Collaborator#some_method(SomeInput)' do
194
+ # do nothing
195
+ end
196
+ end
197
+ """
198
+
199
+ When I run the test suite
200
+ Then I should not see any output saying the stub is unverified
201
+ Scenario: and_throw
202
+ Given a test that uses VerifiedDouble to mock an object:
203
+ """
204
+ require 'spec_helper'
205
+ describe ObjectUnderTest do
206
+ let(:error_symbol) { :error_symbol }
207
+ let(:input) { SomeInput.new }
208
+ let(:output) { SomeOutput.new }
209
+ let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
210
+
211
+ it "tests something" do
212
+ instance_double.should_receive(:some_method).with(input).and_throw(error_symbol)
213
+ expect { ObjectUnderTest.new.do_something(instance_double, input) }.to throw_symbol(error_symbol)
214
+ end
215
+ end
216
+ """
217
+
218
+ And the test suite has a contract test for the mock:
219
+ """
220
+ require 'spec_helper'
221
+
222
+ describe 'Collaborator' do
223
+ it "tests something", verifies_contract: 'Collaborator#some_method(SomeInput)' do
224
+ # do nothing
225
+ end
226
+ end
227
+ """
228
+
229
+ When I run the test suite
230
+ Then I should not see any output saying the stub is unverified