verified_double 0.4.3 → 0.5.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d5009534213dea01c257cd3ae51146bc3b851074
4
+ data.tar.gz: 2fdb0e7501414b89f06ea63c886736b615a47604
5
+ SHA512:
6
+ metadata.gz: 415c67746889f7cb267f8f792ec33c6dffd106b361c6bf72ecfca91a7f9625e2f8813c3ef0c9d5314ba1500dbf393f12bab591ae651641c0017ad662b867673f
7
+ data.tar.gz: 56740f7d553a0ee07f42dce4f6b7bc2844228046d5640c207421585a8f0effe8401f717b20358241822c20c7b3b781cb2a7484e79a919ccdeceaac621687d9af
@@ -0,0 +1,67 @@
1
+ # Refer to https://github.com/bbatsov/rubocop/blob/master/config/default.yml
2
+ # for the default rubocop configuration.
3
+
4
+ AllCops:
5
+ Excludes:
6
+ - db/schema.rb
7
+ - db/fixtures/development/cooking_methods.rb
8
+ - db/fixtures/development/food_categories.rb
9
+ - db/fixtures/development/kitcategories.rb
10
+ - db/fixtures/development/kitsubcats.rb
11
+ - db/fixtures/development/main_ingredients.rb
12
+ - db/fixtures/development/recipe_categories.rb
13
+ - db/fixtures/development/special_occasions.rb
14
+ - db/fixtures/development/states.rb
15
+ Includes:
16
+ - '*.rake'
17
+ - Capfile
18
+ - Gemfile
19
+ - Guardfile
20
+
21
+ AlignHash:
22
+ Enabled: false
23
+
24
+ AlignParameters:
25
+ Enabled: false
26
+
27
+ AsciiComments:
28
+ Enabled: false
29
+
30
+ ClassLength:
31
+ Enabled: false
32
+
33
+ Documentation:
34
+ Enabled: false
35
+
36
+ EmptyLines:
37
+ Enabled: false
38
+
39
+ Encoding:
40
+ Enabled: false
41
+
42
+ FavorUnlessOverNegatedIf:
43
+ Enabled: false
44
+
45
+ IfUnlessModifier:
46
+ Enabled: false
47
+
48
+ LineLength:
49
+ Max: 89
50
+
51
+ MethodLength:
52
+ Max: 30
53
+
54
+ MethodCalledOnDoEndBlock:
55
+ Enabled: true
56
+
57
+ RedundantReturn:
58
+ AllowMultipleReturnValues: true
59
+
60
+ RedundantSelf:
61
+ Enabled: false
62
+
63
+ SignalException:
64
+ Enabled: false
65
+
66
+ StringLiterals:
67
+ Enabled: false
@@ -1,3 +1,11 @@
1
+ 0.5.0 - 2013-12-24
2
+ ------------------
3
+
4
+ * [#27] Implement describe "contract" feature.
5
+
6
+ * [#22] Add VerifiedDouble.any_instance_of(klass). Warning: only works with
7
+ should_receive. Doesn't work with expect/allow syntax.
8
+
1
9
  0.4.3 - 2013-10-22
2
10
  ------------------
3
11
 
@@ -0,0 +1,11 @@
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
6
+
7
+ guard 'cucumber' do
8
+ watch(%r{^features/.+\.feature$})
9
+ watch(%r{^features/support/.+$}) { 'features' }
10
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
11
+ end
data/README.md CHANGED
@@ -2,58 +2,169 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/gsmendoza/verified_double.png)](https://travis-ci.org/gsmendoza/verified_double)
4
4
 
5
- VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if the doubled classes respond to the methods, the gem looks for tests confirming if those mocks are valid.
5
+ VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if a doubled class responds to the methods, the gem looks for tests confirming the signatures of the mocks.
6
6
 
7
- For example, let's say I mocked the created_at method of a model like this:
7
+ For example, if I mock the created_at method of a model like this:
8
8
 
9
- item = VerifiedDouble.of_instance(Item)
10
- expect(item).to receive(:created_at).and_return(Time.now)
9
+ ```ruby
10
+ item = VerifiedDouble.of_instance(Item)
11
+ expect(item).to receive(:created_at).and_return(Time.now)
12
+ ```
11
13
 
12
- When running the tests, the gem looks for a "contract test" tagged with the method's signature. This test should ensure that calling #created_at on Item will return a Time object.
14
+ When I run the tests, the gem will look for a "contract test" tagged with the method's signature. This test should ensure that calling `#created_at` on Item will return a Time object.
13
15
 
14
- it "tests something", verifies_contract: 'Item#created_at()=>Time' do
16
+ ```ruby
17
+ describe Item do
18
+ describe '#created_at()=>Time', verifies_contract: true do
19
+ it "tests something" do
15
20
  #...
16
21
  end
22
+ end
23
+ end
24
+ ```
17
25
 
18
26
  If this test does not exist, the gem will complain that the mock is not verified.
19
27
 
20
28
  I got the idea from http://www.infoq.com/presentations/integration-tests-scam, an old (2009) talk that still has some fresh insights on dealing with API changes in your mocked tests.
21
29
 
22
- Usage
23
- -----
30
+ ## Setup
24
31
 
25
32
  Require `verified_double/rspec_configuration` in your spec_helper.rb to integrate VerifiedDouble with rspec. If you want verified_double to be run only as needed, create a separate verified_spec_helper.rb:
26
33
 
27
- # spec/verified_spec_helper.rb
28
- require 'spec_helper'
29
- require 'verified_double/rspec_configuration'
34
+ ```
35
+ # spec/verified_spec_helper.rb
36
+ require 'spec_helper'
37
+ require 'verified_double/rspec_configuration'
38
+ ```
30
39
 
31
40
  And require it when running rspec:
32
41
 
33
42
  rspec -r ./spec/verified_spec_helper.rb
34
43
 
35
- You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
44
+ ## Usage
36
45
 
37
- Actively tested against
38
- -----------------------
46
+ Let's look again at the example above:
39
47
 
40
- * Ruby 1.9.3
41
- * RSpec 2.14
48
+ ```ruby
49
+ item = VerifiedDouble.of_instance(Item)
50
+ expect(item).to receive(:created_at).and_return(Time.now)
51
+ ```
52
+
53
+ When you run this test, you'll see a warning saying that there's no test verifying the mock `Item#created_at()=>Time`:
54
+
55
+ ```
56
+ The following mocks are not verified:
57
+
58
+ 1. Item#created_at()=>Time
59
+ ...
60
+
61
+ ```
62
+
63
+ You can then tag the test for `Item#created_at()=>Time` with the method signature:
64
+
65
+ ```ruby
66
+ describe Item do
67
+ describe '#created_at()=>Time', verifies_contract: true do
68
+ it "tests something" do
69
+ #...
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ Take note that:
76
+
77
+ 1. The described class must be a class, not a string.
78
+ 2. The described method must start with `#` if its an instance method and `.` if it's a class method.
79
+ 3. You need to add the add the `verifies_contract: true` tag to the test.
80
+
81
+ If your testing style doesn't follow these conventions, you can tag the test with the whole method signature:
82
+
83
+ ```ruby
84
+ describe 'Item' do
85
+ it "has a creation timestamp", verifies_contract: `Item#created_at()=>Time` do
86
+ #...
87
+ end
88
+ end
89
+ ```
90
+
91
+ Since VerifiedDouble relies on tags to link mocks and contracts together, you'll
92
+ need to run the tests containing the contracts along with tests with the mocks in
93
+ order to clear the VerifiedDouble warnings.
94
+
95
+ ## Booleans
96
+
97
+ Since Ruby doesn't have Boolean class covering both `TrueClass` and `FalseClass`,
98
+ VerifiedDouble supplies its own `VerifiedDouble::Boolean` class. Thus if your method
99
+ accepts or returns a boolean value, you'll see `VerifiedDouble::Boolean` in its
100
+ method signature e.g. `Student.late?()=>VerifiedDouble::Boolean`.
42
101
 
102
+ ## Helpers
43
103
 
44
- Alternatives
45
- ------------
104
+ Most of the time, you'll be mocking accessor methods. VerifiedDouble provides some
105
+ helpers to make them easy to verify.
46
106
 
47
- [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
107
+ For reader methods, there's the `verify_reader_contract` matcher. The matcher checks
108
+ if the method will return an object matching the class specified by the contract:
48
109
 
49
- Caveats
50
- -------
110
+ ```ruby
111
+ class Collaborator
112
+ attr_reader :value
113
+
114
+ def initialize(value)
115
+ @value = value
116
+ end
117
+ end
118
+
119
+ class SomeValue
120
+ end
121
+
122
+ describe Collaborator do
123
+ subject { described_class.new(SomeValue.new) }
124
+ it { should verify_reader_contract('Collaborator#value=>SomeValue') }
125
+ end
126
+ ```
127
+
128
+ For accessor methods, there's the `verify_accessor_contract` matcher. The matcher
129
+ instantiates the return class and tries to pass and retrieve the value
130
+ to the method:
131
+
132
+ ```ruby
133
+ class Collaborator
134
+ attr_accessor :value
135
+ end
136
+
137
+ describe Collaborator do
138
+ it { should verify_accessor_contract('Collaborator#value=>SomeValue') }
139
+ end
140
+ ```
141
+
142
+ ## Any Instance mocks
143
+
144
+ Aside for instance and class doubles, VerifiedDouble also supports `any_instance` mocks:
145
+
146
+ ```
147
+ VerifiedDouble.any_instance_of(Collaborator)
148
+ .should_receive(:some_method).with(input).and_return(output)
149
+ ```
150
+
151
+ You'll need to use should_receive for `any_instance` mocks. I still have to figure
152
+ out how to make it work with RSpec's `expect_any_instance_of` syntax :p
153
+
154
+ ## Complete documentation
155
+
156
+ You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
157
+
158
+ ## Actively tested against
159
+
160
+ * Ruby 2.0
161
+ * RSpec 2.14
51
162
 
52
- * With 0.3.0, doubles created with VerifiedDouble.of_instance() and VerifiedDouble.of_class() are now VerifiedDouble-extended RSpec doubles. As a result, they should function like regular RSpec doubles. However, VerifiedDouble still doesn't have support for [RSpec mock argument matchers](https://github.com/rspec/rspec-mocks#argument-matchers). Please post an issue at http://github.com/gsmendoza/verified_double if you need support for any particular rspec-mock API.
163
+ ## Alternatives
53
164
 
54
- * The [method documentation](http://rubydoc.info/gems/verified_double) is pretty empty at this point :p I'm planning to use yard-spec to document the methods but that gem doesn't support rspec context blocks. I'll try to work on that soon.
165
+ [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem I know to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
55
166
 
56
- Special thanks
57
- --------------
167
+ ## Special thanks
58
168
 
59
- To [Thomas Sinclair](https://twitter.com/anathematic) of [Inner Core Designs](http://icdesign.com.au) for initially sponsoring this gem.
169
+ * [Inner Core Designs](http://icdesign.com.au)
170
+ * [Love With Food](https://lovewithfood.com)
@@ -1,3 +1,11 @@
1
+ 0.5.0 - 2013-12-24
2
+ ------------------
3
+
4
+ * [#27] Implement describe "contract" feature.
5
+
6
+ * [#22] Add VerifiedDouble.any_instance_of(klass). Warning: only works with
7
+ should_receive. Doesn't work with expect/allow syntax.
8
+
1
9
  0.4.3 - 2013-10-22
2
10
  ------------------
3
11
 
@@ -1,4 +1,4 @@
1
- Feature: 05. Accessor method contracts
1
+ Feature: 40. Accessor method contracts
2
2
  As a developer
3
3
  I want it to easy to verify contracts for accessor methods
4
4
 
@@ -0,0 +1,95 @@
1
+ Feature: 60. Any instance
2
+
3
+ Background:
4
+ Given the following classes:
5
+ """
6
+ class ObjectUnderTest
7
+ def do_something(collaborator, input)
8
+ collaborator.some_method(input)
9
+ end
10
+
11
+ def self.do_something(input)
12
+ Collaborator.some_method(input)
13
+ end
14
+ end
15
+
16
+ class Collaborator
17
+ def self.some_method(input)
18
+ end
19
+
20
+ def some_method(input)
21
+ end
22
+ end
23
+
24
+ class SomeInput
25
+ end
26
+
27
+ class SomeOutput
28
+ end
29
+ """
30
+
31
+ And the test suite is configured to use VerifiedDouble:
32
+ """
33
+ require 'verified_double'
34
+ require 'verified_double/rspec_configuration'
35
+ require 'main'
36
+ """
37
+
38
+ Scenario: Verify any instance of a class
39
+
40
+ Given a test that uses VerifiedDouble to mock any instance of the class:
41
+ """
42
+ require 'spec_helper'
43
+ describe ObjectUnderTest do
44
+ let(:input) { SomeInput.new }
45
+ let(:output) { SomeOutput.new }
46
+
47
+ it "tests something" do
48
+ VerifiedDouble.any_instance_of(Collaborator)
49
+ .should_receive(:some_method).with(input).and_return(output)
50
+
51
+ ObjectUnderTest.new.do_something(Collaborator.new, input)
52
+ end
53
+ end
54
+ """
55
+
56
+ And the test suite has a contract test for the mock:
57
+ """
58
+ require 'spec_helper'
59
+
60
+ describe 'Collaborator' do
61
+ it "tests something",
62
+ verifies_contract: 'Collaborator#some_method(SomeInput)=>SomeOutput' do
63
+ # do nothing
64
+ end
65
+ end
66
+ """
67
+
68
+ When I run the test suite
69
+ Then I should not see any output saying the mock is unverified
70
+
71
+ Scenario: Unverified any_instance mock
72
+ Given a test that uses VerifiedDouble to mock any instance of the class:
73
+ """
74
+ require 'spec_helper'
75
+ describe ObjectUnderTest do
76
+ let(:input) { SomeInput.new }
77
+ let(:output) { SomeOutput.new }
78
+
79
+ it "tests something" do
80
+ VerifiedDouble.any_instance_of(Collaborator)
81
+ .should_receive(:some_method).with(input).and_return(output)
82
+
83
+ ObjectUnderTest.new.do_something(Collaborator.new, input)
84
+ end
85
+ end
86
+ """
87
+
88
+ And the test suite does not have a contract test for the mock
89
+ When I run the test suite
90
+ Then I should be informed that the mock is unverified:
91
+ """
92
+ The following mocks are not verified:
93
+
94
+ 1. Collaborator#some_method(SomeInput)=>SomeOutput
95
+ """
@@ -1,4 +1,4 @@
1
- Feature: 04. Customizing arguments and return values
1
+ Feature: 50. 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
 
@@ -0,0 +1,67 @@
1
+ Feature: 30. Describe contract
2
+ Scenario: Specify contact in describe string
3
+ Given the following classes:
4
+
5
+ """
6
+ class ObjectUnderTest
7
+ def do_something(collaborator, input)
8
+ collaborator.some_method(input)
9
+ end
10
+ end
11
+
12
+ class Collaborator
13
+ def some_method(input)
14
+ end
15
+ end
16
+
17
+ class SomeInput
18
+ end
19
+
20
+ class SomeOutput
21
+ end
22
+ """
23
+
24
+ And the test suite is configured to use VerifiedDouble:
25
+
26
+ """
27
+ require 'verified_double'
28
+ require 'verified_double/rspec_configuration'
29
+ require 'main'
30
+ """
31
+
32
+ And a test that uses VerifiedDouble to mock an object:
33
+
34
+ """
35
+ require 'spec_helper'
36
+ describe ObjectUnderTest do
37
+ let(:input) { SomeInput.new }
38
+ let(:output) { SomeOutput.new }
39
+ let(:collaborator) { VerifiedDouble.of_instance('Collaborator') }
40
+
41
+ it "tests something" do
42
+ expect(collaborator)
43
+ .to receive(:some_method).with(input).and_return(output)
44
+
45
+ ObjectUnderTest.new.do_something(collaborator, input)
46
+ end
47
+ end
48
+ """
49
+
50
+ And the test suite has a contract test for the mock:
51
+
52
+ """
53
+ require 'spec_helper'
54
+
55
+ describe Collaborator do
56
+ context 'with some context' do
57
+ describe '#some_method(SomeInput)=>SomeOutput', verifies_contract: true do
58
+ it "tests something" do
59
+ # do nothing
60
+ end
61
+ end
62
+ end
63
+ end
64
+ """
65
+
66
+ When I run the test suite
67
+ Then I should not see any output saying the mock is unverified
@@ -2,58 +2,169 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/gsmendoza/verified_double.png)](https://travis-ci.org/gsmendoza/verified_double)
4
4
 
5
- VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if the doubled classes respond to the methods, the gem looks for tests confirming if those mocks are valid.
5
+ VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if a doubled class responds to the methods, the gem looks for tests confirming the signatures of the mocks.
6
6
 
7
- For example, let's say I mocked the created_at method of a model like this:
7
+ For example, if I mock the created_at method of a model like this:
8
8
 
9
- item = VerifiedDouble.of_instance(Item)
10
- expect(item).to receive(:created_at).and_return(Time.now)
9
+ ```ruby
10
+ item = VerifiedDouble.of_instance(Item)
11
+ expect(item).to receive(:created_at).and_return(Time.now)
12
+ ```
11
13
 
12
- When running the tests, the gem looks for a "contract test" tagged with the method's signature. This test should ensure that calling #created_at on Item will return a Time object.
14
+ When I run the tests, the gem will look for a "contract test" tagged with the method's signature. This test should ensure that calling `#created_at` on Item will return a Time object.
13
15
 
14
- it "tests something", verifies_contract: 'Item#created_at()=>Time' do
16
+ ```ruby
17
+ describe Item do
18
+ describe '#created_at()=>Time', verifies_contract: true do
19
+ it "tests something" do
15
20
  #...
16
21
  end
22
+ end
23
+ end
24
+ ```
17
25
 
18
26
  If this test does not exist, the gem will complain that the mock is not verified.
19
27
 
20
28
  I got the idea from http://www.infoq.com/presentations/integration-tests-scam, an old (2009) talk that still has some fresh insights on dealing with API changes in your mocked tests.
21
29
 
22
- Usage
23
- -----
30
+ ## Setup
24
31
 
25
32
  Require `verified_double/rspec_configuration` in your spec_helper.rb to integrate VerifiedDouble with rspec. If you want verified_double to be run only as needed, create a separate verified_spec_helper.rb:
26
33
 
27
- # spec/verified_spec_helper.rb
28
- require 'spec_helper'
29
- require 'verified_double/rspec_configuration'
34
+ ```
35
+ # spec/verified_spec_helper.rb
36
+ require 'spec_helper'
37
+ require 'verified_double/rspec_configuration'
38
+ ```
30
39
 
31
40
  And require it when running rspec:
32
41
 
33
42
  rspec -r ./spec/verified_spec_helper.rb
34
43
 
35
- You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
44
+ ## Usage
36
45
 
37
- Actively tested against
38
- -----------------------
46
+ Let's look again at the example above:
39
47
 
40
- * Ruby 1.9.3
41
- * RSpec 2.14
48
+ ```ruby
49
+ item = VerifiedDouble.of_instance(Item)
50
+ expect(item).to receive(:created_at).and_return(Time.now)
51
+ ```
52
+
53
+ When you run this test, you'll see a warning saying that there's no test verifying the mock `Item#created_at()=>Time`:
54
+
55
+ ```
56
+ The following mocks are not verified:
57
+
58
+ 1. Item#created_at()=>Time
59
+ ...
60
+
61
+ ```
62
+
63
+ You can then tag the test for `Item#created_at()=>Time` with the method signature:
64
+
65
+ ```ruby
66
+ describe Item do
67
+ describe '#created_at()=>Time', verifies_contract: true do
68
+ it "tests something" do
69
+ #...
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ Take note that:
76
+
77
+ 1. The described class must be a class, not a string.
78
+ 2. The described method must start with `#` if its an instance method and `.` if it's a class method.
79
+ 3. You need to add the add the `verifies_contract: true` tag to the test.
80
+
81
+ If your testing style doesn't follow these conventions, you can tag the test with the whole method signature:
82
+
83
+ ```ruby
84
+ describe 'Item' do
85
+ it "has a creation timestamp", verifies_contract: `Item#created_at()=>Time` do
86
+ #...
87
+ end
88
+ end
89
+ ```
90
+
91
+ Since VerifiedDouble relies on tags to link mocks and contracts together, you'll
92
+ need to run the tests containing the contracts along with tests with the mocks in
93
+ order to clear the VerifiedDouble warnings.
94
+
95
+ ## Booleans
96
+
97
+ Since Ruby doesn't have Boolean class covering both `TrueClass` and `FalseClass`,
98
+ VerifiedDouble supplies its own `VerifiedDouble::Boolean` class. Thus if your method
99
+ accepts or returns a boolean value, you'll see `VerifiedDouble::Boolean` in its
100
+ method signature e.g. `Student.late?()=>VerifiedDouble::Boolean`.
42
101
 
102
+ ## Helpers
43
103
 
44
- Alternatives
45
- ------------
104
+ Most of the time, you'll be mocking accessor methods. VerifiedDouble provides some
105
+ helpers to make them easy to verify.
46
106
 
47
- [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
107
+ For reader methods, there's the `verify_reader_contract` matcher. The matcher checks
108
+ if the method will return an object matching the class specified by the contract:
48
109
 
49
- Caveats
50
- -------
110
+ ```ruby
111
+ class Collaborator
112
+ attr_reader :value
113
+
114
+ def initialize(value)
115
+ @value = value
116
+ end
117
+ end
118
+
119
+ class SomeValue
120
+ end
121
+
122
+ describe Collaborator do
123
+ subject { described_class.new(SomeValue.new) }
124
+ it { should verify_reader_contract('Collaborator#value=>SomeValue') }
125
+ end
126
+ ```
127
+
128
+ For accessor methods, there's the `verify_accessor_contract` matcher. The matcher
129
+ instantiates the return class and tries to pass and retrieve the value
130
+ to the method:
131
+
132
+ ```ruby
133
+ class Collaborator
134
+ attr_accessor :value
135
+ end
136
+
137
+ describe Collaborator do
138
+ it { should verify_accessor_contract('Collaborator#value=>SomeValue') }
139
+ end
140
+ ```
141
+
142
+ ## Any Instance mocks
143
+
144
+ Aside for instance and class doubles, VerifiedDouble also supports `any_instance` mocks:
145
+
146
+ ```
147
+ VerifiedDouble.any_instance_of(Collaborator)
148
+ .should_receive(:some_method).with(input).and_return(output)
149
+ ```
150
+
151
+ You'll need to use should_receive for `any_instance` mocks. I still have to figure
152
+ out how to make it work with RSpec's `expect_any_instance_of` syntax :p
153
+
154
+ ## Complete documentation
155
+
156
+ You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
157
+
158
+ ## Actively tested against
159
+
160
+ * Ruby 2.0
161
+ * RSpec 2.14
51
162
 
52
- * With 0.3.0, doubles created with VerifiedDouble.of_instance() and VerifiedDouble.of_class() are now VerifiedDouble-extended RSpec doubles. As a result, they should function like regular RSpec doubles. However, VerifiedDouble still doesn't have support for [RSpec mock argument matchers](https://github.com/rspec/rspec-mocks#argument-matchers). Please post an issue at http://github.com/gsmendoza/verified_double if you need support for any particular rspec-mock API.
163
+ ## Alternatives
53
164
 
54
- * The [method documentation](http://rubydoc.info/gems/verified_double) is pretty empty at this point :p I'm planning to use yard-spec to document the methods but that gem doesn't support rspec context blocks. I'll try to work on that soon.
165
+ [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem I know to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
55
166
 
56
- Special thanks
57
- --------------
167
+ ## Special thanks
58
168
 
59
- To [Thomas Sinclair](https://twitter.com/anathematic) of [Inner Core Designs](http://icdesign.com.au) for initially sponsoring this gem.
169
+ * [Inner Core Designs](http://icdesign.com.au)
170
+ * [Love With Food](https://lovewithfood.com)
@@ -1,4 +1,4 @@
1
- Feature: 03. Rspec Mock compatibility
1
+ Feature: 70. Rspec Mock compatibility
2
2
  As a developer
3
3
  I want VerifiedDouble to work with Rspec Mock API
4
4
 
@@ -6,6 +6,10 @@ Given /^a test that uses VerifiedDouble to mock an object:$/ do |string|
6
6
  write_file 'spec/main_spec.rb', string
7
7
  end
8
8
 
9
+ Given(/^a test that uses VerifiedDouble to mock any instance of the class:$/) do |string|
10
+ write_file 'spec/main_spec.rb', string
11
+ end
12
+
9
13
  Given /^a test that uses VerifiedDouble to stub an object:$/ do |string|
10
14
  write_file 'spec/main_spec.rb', string
11
15
  end
@@ -1,4 +1,4 @@
1
- Feature: 01. Verified mocks
1
+ Feature: 10. Verified mocks
2
2
  As a developer
3
3
  I want to be informed if the mocks I use are verified by contract tests
4
4
 
@@ -206,3 +206,4 @@ Feature: 01. Verified mocks
206
206
 
207
207
  1. Collaborator.some_method(SomeInput)=>SomeOutput
208
208
  """
209
+
@@ -1,4 +1,4 @@
1
- Feature: 02. Verified stubs
1
+ Feature: 20. Verified stubs
2
2
  As a developer
3
3
  I want to be informed if the stubs I use are verified by contract tests
4
4
 
@@ -3,6 +3,7 @@ require 'rspec/mocks'
3
3
 
4
4
  require 'verified_double/boolean'
5
5
  require 'verified_double/can_record_interactions'
6
+ require 'verified_double/example_metadata'
6
7
  require 'verified_double/is_a_class_double'
7
8
  require 'verified_double/is_an_instance_double'
8
9
  require 'verified_double/matchers'
@@ -23,6 +24,12 @@ require 'verified_double/stack_frame'
23
24
  module VerifiedDouble
24
25
  extend RSpec::Mocks::ExampleMethods
25
26
 
27
+ def self.any_instance_of(klass)
28
+ d = klass.any_instance
29
+ d.extend(VerifiedDouble::IsAnInstanceDouble)
30
+ VerifiedDouble.record(d)
31
+ end
32
+
26
33
  def self.of_class(class_value, options = {})
27
34
  options[:transfer_nested_constants] = true if options[:transfer_nested_constants].nil?
28
35
  d = stub_const(class_value.to_s, Class.new, options)
@@ -0,0 +1,31 @@
1
+ module VerifiedDouble
2
+ class ExampleMetadata < Struct.new(:metadata)
3
+ def described_class
4
+ if description.is_a?(Module)
5
+ description
6
+ elsif description.is_a?(String)
7
+ ExampleMetadata.new(metadata[:example_group]).described_class
8
+ else
9
+ raise
10
+ end
11
+ end
12
+
13
+ def description
14
+ metadata[:description_args][0]
15
+ end
16
+
17
+ def method_signature_string
18
+ if description =~ /^[\.\#]/
19
+ description
20
+ elsif description.nil?
21
+ raise
22
+ else
23
+ ExampleMetadata.new(metadata[:example_group]).method_signature_string
24
+ end
25
+ end
26
+
27
+ def verified_signature
28
+ "#{described_class}#{method_signature_string}"
29
+ end
30
+ end
31
+ end
@@ -49,13 +49,23 @@ module VerifiedDouble
49
49
  end
50
50
 
51
51
  def set_verified_signatures_from_tags(nested_example_group)
52
- @verified_signatures_from_tags = nested_example_group
52
+ examples = nested_example_group
53
53
  .class
54
54
  .descendant_filtered_examples
55
- .map{|example| example.metadata[:verifies_contract] }
55
+
56
+ verified_signatures = examples.map do |example|
57
+ if example.metadata[:verifies_contract] == true
58
+ ExampleMetadata.new(example.metadata).verified_signature
59
+ else
60
+ example.metadata[:verifies_contract]
61
+ end
62
+ end
63
+
64
+ @verified_signatures_from_tags = verified_signatures
56
65
  .compact
57
66
  .uniq
58
67
  .map{|method_signature_string| ParseMethodSignature.new(method_signature_string).execute }
68
+
59
69
  self
60
70
  end
61
71
  end
@@ -11,7 +11,14 @@ module VerifiedDouble
11
11
 
12
12
  def expect(*args)
13
13
  if args[0].respond_to?(:can_record_interactions?)
14
- VerifiedDouble.registry.current_double = args[0]
14
+ if args[0].is_a?(RSpec::Mocks::AnyInstance::Recorder)
15
+ raise "VerifiedDouble.any_instance_of doesn't support yet Rspec's " \
16
+ "expect/allow syntax. Please use should_receive."
17
+ else
18
+ VerifiedDouble.registry.current_double = args[0]
19
+ end
20
+
21
+
15
22
  else
16
23
  VerifiedDouble.registry.current_double = nil
17
24
  end
@@ -15,13 +15,29 @@ module VerifiedDouble
15
15
 
16
16
 
17
17
  def class_name
18
- class_double? ? internal.name : internal.instance_variable_get('@name').to_s
18
+ if class_double?
19
+ internal.name
20
+ elsif instance_double?
21
+ internal.instance_variable_get('@name').to_s
22
+ elsif any_instance_double?
23
+ internal.instance_variable_get('@klass').to_s
24
+ else
25
+ raise
26
+ end
27
+ end
28
+
29
+ def any_instance_double?
30
+ !! internal.instance_variable_get('@klass')
19
31
  end
20
32
 
21
33
  def class_double?
22
34
  internal.respond_to?(:verified_class_double?)
23
35
  end
24
36
 
37
+ def instance_double?
38
+ !! internal.instance_variable_get('@name')
39
+ end
40
+
25
41
  def method_operator
26
42
  class_double? ? '.' : '#'
27
43
  end
@@ -1,3 +1,3 @@
1
1
  module VerifiedDouble
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe VerifiedDouble::ExampleMetadata do
4
+ let(:klass) { Object }
5
+ let(:method_signature_string) { '#to_s()=>String' }
6
+ let(:metadata) do
7
+ {
8
+ description_args: ['is a string representing the object'],
9
+ example_group: {
10
+ description_args: [method_signature_string],
11
+
12
+ example_group: {
13
+ description_args: ['with some context'],
14
+
15
+ example_group: {
16
+ description_args: [klass]
17
+ }
18
+ }
19
+ }
20
+ }
21
+ end
22
+
23
+ subject { described_class.new(metadata) }
24
+
25
+ describe '#verified_signature' do
26
+ it 'is the class_name and method_signature_string' do
27
+ expect(subject.verified_signature).to eq("#{klass}#{method_signature_string}")
28
+ end
29
+ end
30
+
31
+ describe '#described_class' do
32
+ it "is the described class of the metadata's test source" do
33
+ expect(subject.described_class).to eq(klass)
34
+ end
35
+
36
+ context "where the described class is a string" do
37
+ let(:metadata) do
38
+ {
39
+ example_group: {
40
+ description_args: [klass.to_s]
41
+ }
42
+ }
43
+ end
44
+
45
+ it "should raise an error" do
46
+ expect(-> { subject.described_class }).to raise_error
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#method_signature_string' do
52
+ it "is the signature of the method being tested" do
53
+ expect(subject.method_signature_string).to eq(method_signature_string)
54
+ end
55
+
56
+ context "where there is no description arg that looks like a method signature" do
57
+ let(:metadata) do
58
+ {
59
+ example_group: {
60
+ description_args: [klass.to_s]
61
+ }
62
+ }
63
+ end
64
+
65
+ it "should raise an error" do
66
+ expect(-> { subject.method_signature_string }).to raise_error
67
+ end
68
+ end
69
+ end
70
+ end
71
+
@@ -15,6 +15,15 @@ describe VerifiedDouble::RSpecMocksSyntaxOverrides do
15
15
  end
16
16
  end
17
17
 
18
+ context "where the double arg is an RSpec::Mocks::AnyInstance::Recorder" do
19
+ let(:a_double) { VerifiedDouble.of_instance('Object') }
20
+
21
+ it "should tell the user to use should_receive instead" do
22
+ expect(lambda { expect(VerifiedDouble.any_instance_of(Object)) })
23
+ .to raise_error
24
+ end
25
+ end
26
+
18
27
  context "where the double arg does not record VerifiedDouble interactions" do
19
28
  let(:a_double) { double('Object') }
20
29
 
@@ -76,4 +85,4 @@ describe VerifiedDouble::RSpecMocksSyntaxOverrides do
76
85
  end
77
86
  end
78
87
  end
79
- end
88
+ end
@@ -22,5 +22,9 @@ Gem::Specification.new do |gem|
22
22
 
23
23
  gem.add_development_dependency "aruba"
24
24
  gem.add_development_dependency "cucumber"
25
+ gem.add_development_dependency "guard"
26
+ gem.add_development_dependency "guard-cucumber"
27
+ gem.add_development_dependency "guard-rspec"
25
28
  gem.add_development_dependency "pry"
29
+ gem.add_development_dependency "rubocop"
26
30
  end
metadata CHANGED
@@ -1,96 +1,141 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verified_double
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.4.3
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - George Mendoza
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-10-22 00:00:00.000000000 Z
11
+ date: 2013-12-24 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- type: :runtime
14
+ name: activesupport
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
20
+ type: :runtime
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
- none: false
25
23
  requirements:
26
- - - ! '>='
24
+ - - '>='
27
25
  - !ruby/object:Gem::Version
28
26
  version: '0'
29
- name: activesupport
30
27
  - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
31
34
  type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: aruba
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
- - - ! '>='
45
+ - - '>='
36
46
  - !ruby/object:Gem::Version
37
47
  version: '0'
48
+ type: :development
38
49
  prerelease: false
39
50
  version_requirements: !ruby/object:Gem::Requirement
40
- none: false
41
51
  requirements:
42
- - - ! '>='
52
+ - - '>='
43
53
  - !ruby/object:Gem::Version
44
54
  version: '0'
45
- name: rspec
46
55
  - !ruby/object:Gem::Dependency
56
+ name: cucumber
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
48
71
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
72
  requirements:
51
- - - ! '>='
73
+ - - '>='
52
74
  - !ruby/object:Gem::Version
53
75
  version: '0'
76
+ type: :development
54
77
  prerelease: false
55
78
  version_requirements: !ruby/object:Gem::Requirement
56
- none: false
57
79
  requirements:
58
- - - ! '>='
80
+ - - '>='
59
81
  - !ruby/object:Gem::Version
60
82
  version: '0'
61
- name: aruba
62
83
  - !ruby/object:Gem::Dependency
84
+ name: guard-cucumber
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
63
90
  type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
64
99
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
100
  requirements:
67
- - - ! '>='
101
+ - - '>='
68
102
  - !ruby/object:Gem::Version
69
103
  version: '0'
104
+ type: :development
70
105
  prerelease: false
71
106
  version_requirements: !ruby/object:Gem::Requirement
72
- none: false
73
107
  requirements:
74
- - - ! '>='
108
+ - - '>='
75
109
  - !ruby/object:Gem::Version
76
110
  version: '0'
77
- name: cucumber
78
111
  - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
79
118
  type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
80
127
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
128
  requirements:
83
- - - ! '>='
129
+ - - '>='
84
130
  - !ruby/object:Gem::Version
85
131
  version: '0'
132
+ type: :development
86
133
  prerelease: false
87
134
  version_requirements: !ruby/object:Gem::Requirement
88
- none: false
89
135
  requirements:
90
- - - ! '>='
136
+ - - '>='
91
137
  - !ruby/object:Gem::Version
92
138
  version: '0'
93
- name: pry
94
139
  description: Contract tests for rspec
95
140
  email:
96
141
  - gsmendoza@gmail.com
@@ -99,15 +144,19 @@ extensions: []
99
144
  extra_rdoc_files: []
100
145
  files:
101
146
  - .gitignore
147
+ - .rubocop.yml
102
148
  - .travis.yml
103
149
  - CHANGELOG.markdown
104
150
  - Gemfile
151
+ - Guardfile
105
152
  - LICENSE.txt
106
153
  - README.md
107
154
  - Rakefile
108
155
  - features/CHANGELOG.markdown
109
156
  - features/accessor_method_contracts.feature
157
+ - features/any_instance.feature
110
158
  - features/customizing_arguments_and_return_values.feature
159
+ - features/describe_contract.feature
111
160
  - features/readme.md
112
161
  - features/rspec_mock_compatibility.feature
113
162
  - features/step_definitions/verified_double_steps.rb
@@ -117,6 +166,7 @@ files:
117
166
  - lib/verified_double.rb
118
167
  - lib/verified_double/boolean.rb
119
168
  - lib/verified_double/can_record_interactions.rb
169
+ - lib/verified_double/example_metadata.rb
120
170
  - lib/verified_double/is_a_class_double.rb
121
171
  - lib/verified_double/is_an_instance_double.rb
122
172
  - lib/verified_double/matchers.rb
@@ -138,6 +188,7 @@ files:
138
188
  - spec/spec_helper.rb
139
189
  - spec/support/shared_examples.rb
140
190
  - spec/verified_double/can_record_interactions_spec.rb
191
+ - spec/verified_double/example_metadata_spec.rb
141
192
  - spec/verified_double/matchers_spec.rb
142
193
  - spec/verified_double/method_signature/boolean_value_spec.rb
143
194
  - spec/verified_double/method_signature/class_value_spec.rb
@@ -156,33 +207,34 @@ files:
156
207
  - verified_double.gemspec
157
208
  homepage: https://www.relishapp.com/gsmendoza/verified-double
158
209
  licenses: []
210
+ metadata: {}
159
211
  post_install_message:
160
212
  rdoc_options: []
161
213
  require_paths:
162
214
  - lib
163
215
  required_ruby_version: !ruby/object:Gem::Requirement
164
- none: false
165
216
  requirements:
166
- - - ! '>='
217
+ - - '>='
167
218
  - !ruby/object:Gem::Version
168
219
  version: '0'
169
220
  required_rubygems_version: !ruby/object:Gem::Requirement
170
- none: false
171
221
  requirements:
172
- - - ! '>='
222
+ - - '>='
173
223
  - !ruby/object:Gem::Version
174
224
  version: '0'
175
225
  requirements: []
176
226
  rubyforge_project:
177
- rubygems_version: 1.8.24
227
+ rubygems_version: 2.1.11
178
228
  signing_key:
179
- specification_version: 3
229
+ specification_version: 4
180
230
  summary: VerifiedDouble would record any mock made in the test suite. It would then
181
231
  verify if the mock is valid by checking if there is a test against it.
182
232
  test_files:
183
233
  - features/CHANGELOG.markdown
184
234
  - features/accessor_method_contracts.feature
235
+ - features/any_instance.feature
185
236
  - features/customizing_arguments_and_return_values.feature
237
+ - features/describe_contract.feature
186
238
  - features/readme.md
187
239
  - features/rspec_mock_compatibility.feature
188
240
  - features/step_definitions/verified_double_steps.rb
@@ -192,6 +244,7 @@ test_files:
192
244
  - spec/spec_helper.rb
193
245
  - spec/support/shared_examples.rb
194
246
  - spec/verified_double/can_record_interactions_spec.rb
247
+ - spec/verified_double/example_metadata_spec.rb
195
248
  - spec/verified_double/matchers_spec.rb
196
249
  - spec/verified_double/method_signature/boolean_value_spec.rb
197
250
  - spec/verified_double/method_signature/class_value_spec.rb
@@ -207,4 +260,3 @@ test_files:
207
260
  - spec/verified_double/simple_double_spec.rb
208
261
  - spec/verified_double/stack_frame_spec.rb
209
262
  - spec/verified_double_spec.rb
210
- has_rdoc: