verified_double 0.0.1
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.
- data/.gitignore +21 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +65 -0
- data/Rakefile +1 -0
- data/features/readme.md +65 -0
- data/features/step_definitions/verified_double_steps.rb +37 -0
- data/features/support/requires.rb +1 -0
- data/features/verified_double.feature +152 -0
- data/lib/verified_double/get_registered_signatures.rb +11 -0
- data/lib/verified_double/get_unverified_signatures.rb +11 -0
- data/lib/verified_double/get_verified_signatures.rb +16 -0
- data/lib/verified_double/method_signature.rb +16 -0
- data/lib/verified_double/output_unverified_signatures.rb +18 -0
- data/lib/verified_double/recording_double.rb +58 -0
- data/lib/verified_double/report_unverified_signatures.rb +16 -0
- data/lib/verified_double/verify_doubles_service.rb +15 -0
- data/lib/verified_double/version.rb +3 -0
- data/lib/verified_double.rb +28 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/unit_helper.rb +7 -0
- data/spec/verified_double/get_registered_signatures_spec.rb +42 -0
- data/spec/verified_double/get_unverified_signatures_spec.rb +28 -0
- data/spec/verified_double/get_verified_signatures_spec.rb +33 -0
- data/spec/verified_double/method_signature_spec.rb +50 -0
- data/spec/verified_double/output_unverified_signatures_spec.rb +38 -0
- data/spec/verified_double/recording_double_spec.rb +133 -0
- data/spec/verified_double/report_unverified_signatures_spec.rb +57 -0
- data/spec/verified_double/verify_doubles_service_spec.rb +24 -0
- data/spec/verified_double_spec.rb +52 -0
- data/verified_double.gemspec +28 -0
- metadata +190 -0
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.geany
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
.rspec
|
7
|
+
.switch_file
|
8
|
+
.yardoc
|
9
|
+
Gemfile.lock
|
10
|
+
InstalledFiles
|
11
|
+
_yardoc
|
12
|
+
coverage
|
13
|
+
doc/
|
14
|
+
gsmendoza/
|
15
|
+
lib/bundler/man
|
16
|
+
pkg
|
17
|
+
rdoc
|
18
|
+
spec/reports
|
19
|
+
test/tmp
|
20
|
+
test/version_tmp
|
21
|
+
tmp
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 George Mendoza
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# VerifiedDouble
|
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.
|
6
|
+
|
7
|
+
For example, let's say I mocked the save method of a model like so:
|
8
|
+
|
9
|
+
item = VerifiedDouble.of_instance(Item)
|
10
|
+
item.should_receive(:save).and_return(true)
|
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:
|
18
|
+
|
19
|
+
it "tests something", verifies_contract: 'Item#save => Boolean' do
|
20
|
+
#...
|
21
|
+
end
|
22
|
+
|
23
|
+
If this test does not exist, the gem would complain that the mock is not
|
24
|
+
verified.
|
25
|
+
|
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
|
54
|
+
|
55
|
+
Or install it yourself as:
|
56
|
+
|
57
|
+
$ gem install verified_double
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
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
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/features/readme.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# VerifiedDouble
|
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.
|
6
|
+
|
7
|
+
For example, let's say I mocked the save method of a model like so:
|
8
|
+
|
9
|
+
item = VerifiedDouble.of_instance(Item)
|
10
|
+
item.should_receive(:save).and_return(true)
|
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:
|
18
|
+
|
19
|
+
it "tests something", verifies_contract: 'Item#save => Boolean' do
|
20
|
+
#...
|
21
|
+
end
|
22
|
+
|
23
|
+
If this test does not exist, the gem would complain that the mock is not
|
24
|
+
verified.
|
25
|
+
|
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
|
54
|
+
|
55
|
+
Or install it yourself as:
|
56
|
+
|
57
|
+
$ gem install verified_double
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
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
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Given /^the following classes:$/ do |string|
|
2
|
+
write_file 'lib/main.rb', string
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^the test suite has an after\(:suite\) callback asking VerifiedDouble to report unverified doubles:$/ do |string|
|
6
|
+
write_file 'spec/spec_helper.rb', string
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^a test that uses VerifiedDouble to mock an object:$/ do |string|
|
10
|
+
write_file 'spec/main_spec.rb', string
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^a test that uses VerifiedDouble to mock a class:$/ do |string|
|
14
|
+
write_file 'spec/main_spec.rb', string
|
15
|
+
end
|
16
|
+
|
17
|
+
Given /^the test suite has a contract test for the mock:$/ do |string|
|
18
|
+
write_file 'spec/contract_test_for_main_spec.rb', string
|
19
|
+
end
|
20
|
+
|
21
|
+
Given /^the test suite does not have a contract test for the mock$/ do
|
22
|
+
# do nothing
|
23
|
+
end
|
24
|
+
|
25
|
+
When /^I run the test suite$/ do
|
26
|
+
run_simple(unescape("rspec"), false)
|
27
|
+
end
|
28
|
+
|
29
|
+
Then /^I should be informed that the mock is unverified:$/ do |string|
|
30
|
+
assert_partial_output(string, all_output)
|
31
|
+
assert_success('pass')
|
32
|
+
end
|
33
|
+
|
34
|
+
Then /^I should not see any output saying the mock is unverified$/ do
|
35
|
+
assert_no_partial_output("The following mocks are not verified", all_output)
|
36
|
+
assert_success('pass')
|
37
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'aruba/cucumber'
|
@@ -0,0 +1,152 @@
|
|
1
|
+
Feature: Verified double
|
2
|
+
As a developer
|
3
|
+
I want to be informed if the mocks I use are verified by contract tests
|
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 self.do_something(collaborator, input)
|
14
|
+
collaborator.some_method(input)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Collaborator
|
19
|
+
def self.some_method(input)
|
20
|
+
end
|
21
|
+
|
22
|
+
def some_method(input)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class SomeInput
|
27
|
+
end
|
28
|
+
|
29
|
+
class SomeOutput
|
30
|
+
end
|
31
|
+
"""
|
32
|
+
|
33
|
+
And the test suite has an after(:suite) callback asking VerifiedDouble to report unverified doubles:
|
34
|
+
"""
|
35
|
+
require 'pry'
|
36
|
+
require 'verified_double'
|
37
|
+
require 'main'
|
38
|
+
|
39
|
+
RSpec.configure do |config|
|
40
|
+
config.after :suite do
|
41
|
+
VerifiedDouble::ReportUnverifiedSignatures.new(VerifiedDouble.registry, self).execute
|
42
|
+
end
|
43
|
+
end
|
44
|
+
"""
|
45
|
+
|
46
|
+
Scenario: Verified instance doubles
|
47
|
+
Given a test that uses VerifiedDouble to mock an object:
|
48
|
+
"""
|
49
|
+
require 'spec_helper'
|
50
|
+
describe ObjectUnderTest do
|
51
|
+
let(:input) { SomeInput.new }
|
52
|
+
let(:output) { SomeOutput.new }
|
53
|
+
let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
|
54
|
+
|
55
|
+
it "tests something" do
|
56
|
+
instance_double.should_receive(:some_method).with(input).and_return(output)
|
57
|
+
ObjectUnderTest.new.do_something(instance_double, input)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
"""
|
61
|
+
|
62
|
+
And the test suite has a contract test for the mock:
|
63
|
+
"""
|
64
|
+
require 'spec_helper'
|
65
|
+
|
66
|
+
describe 'Collaborator' do
|
67
|
+
it "tests something", verifies_contract: 'Collaborator#some_method(SomeInput)=>SomeOutput' do
|
68
|
+
# do nothing
|
69
|
+
end
|
70
|
+
end
|
71
|
+
"""
|
72
|
+
|
73
|
+
When I run the test suite
|
74
|
+
Then I should not see any output saying the mock is unverified
|
75
|
+
|
76
|
+
Scenario: Unverified instance doubles
|
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).and_return(output)
|
87
|
+
ObjectUnderTest.new.do_something(instance_double, input)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
"""
|
91
|
+
|
92
|
+
And the test suite does not have a contract test for the mock
|
93
|
+
When I run the test suite
|
94
|
+
Then I should be informed that the mock is unverified:
|
95
|
+
"""
|
96
|
+
The following mocks are not verified:
|
97
|
+
Collaborator#some_method(SomeInput)=>SomeOutput
|
98
|
+
"""
|
99
|
+
|
100
|
+
Scenario: Verified class doubles
|
101
|
+
Given a test that uses VerifiedDouble to mock a class:
|
102
|
+
"""
|
103
|
+
require 'spec_helper'
|
104
|
+
describe ObjectUnderTest do
|
105
|
+
let(:input) { SomeInput.new }
|
106
|
+
let(:output) { SomeOutput.new }
|
107
|
+
let(:class_double) { VerifiedDouble.of_class('Collaborator') }
|
108
|
+
|
109
|
+
it "tests something" do
|
110
|
+
class_double.should_receive(:some_method).with(input).and_return(output)
|
111
|
+
ObjectUnderTest.new.do_something(class_double, input)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
"""
|
115
|
+
|
116
|
+
And the test suite has a contract test for the mock:
|
117
|
+
"""
|
118
|
+
require 'spec_helper'
|
119
|
+
|
120
|
+
describe 'Collaborator' do
|
121
|
+
it "tests something", verifies_contract: 'Collaborator.some_method(SomeInput)=>SomeOutput' do
|
122
|
+
# do nothing
|
123
|
+
end
|
124
|
+
end
|
125
|
+
"""
|
126
|
+
|
127
|
+
When I run the test suite
|
128
|
+
Then I should not see any output saying the mock is unverified
|
129
|
+
|
130
|
+
Scenario: Unverified class doubles
|
131
|
+
Given a test that uses VerifiedDouble to mock an object:
|
132
|
+
"""
|
133
|
+
require 'spec_helper'
|
134
|
+
describe ObjectUnderTest do
|
135
|
+
let(:input) { SomeInput.new }
|
136
|
+
let(:output) { SomeOutput.new }
|
137
|
+
let(:class_double) { VerifiedDouble.of_class('Collaborator') }
|
138
|
+
|
139
|
+
it "tests something" do
|
140
|
+
class_double.should_receive(:some_method).with(input).and_return(output)
|
141
|
+
ObjectUnderTest.new.do_something(class_double, input)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
"""
|
145
|
+
|
146
|
+
And the test suite does not have a contract test for the mock
|
147
|
+
When I run the test suite
|
148
|
+
Then I should be informed that the mock is unverified:
|
149
|
+
"""
|
150
|
+
The following mocks are not verified:
|
151
|
+
Collaborator.some_method(SomeInput)=>SomeOutput
|
152
|
+
"""
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class GetUnverifiedSignatures
|
3
|
+
def initialize(get_registered_signatures, get_verified_signatures)
|
4
|
+
@get_registered_signatures, @get_verified_signatures = get_registered_signatures, get_verified_signatures
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
@get_registered_signatures.execute - @get_verified_signatures.execute
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class GetVerifiedSignatures
|
3
|
+
def initialize(nested_example_group)
|
4
|
+
@nested_example_group = nested_example_group
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
results = @nested_example_group
|
9
|
+
.class
|
10
|
+
.descendant_filtered_examples
|
11
|
+
.map{|example| example.metadata[:verifies_contract] }
|
12
|
+
.compact
|
13
|
+
.uniq
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class MethodSignature
|
3
|
+
attr_accessor :args, :method, :recording_double, :return_value
|
4
|
+
|
5
|
+
def initialize(recording_double)
|
6
|
+
@recording_double = recording_double
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
result = [
|
11
|
+
"#{recording_double.class_name}#{recording_double.method_operator}#{method}(#{args && args.map(&:class).join(', ')})",
|
12
|
+
return_value && return_value.class]
|
13
|
+
result.compact.join("=>")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class OutputUnverifiedSignatures
|
3
|
+
def initialize(get_unverified_signatures)
|
4
|
+
@get_unverified_signatures = get_unverified_signatures
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
if unverified_signatures.any?
|
9
|
+
output = ["The following mocks are not verified:" ] + unverified_signatures
|
10
|
+
puts output.join("\n")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def unverified_signatures
|
15
|
+
@unverified_signatures ||= @get_unverified_signatures.execute
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module VerifiedDouble
|
4
|
+
class RecordingDouble < ::SimpleDelegator
|
5
|
+
def initialize(double)
|
6
|
+
@double = double
|
7
|
+
super(@double)
|
8
|
+
end
|
9
|
+
|
10
|
+
def and_return(return_value)
|
11
|
+
self.method_signatures.last.return_value = return_value
|
12
|
+
@double_call.and_return(return_value)
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def class_double?
|
17
|
+
! double.is_a?(RSpec::Fire::FireObjectDouble)
|
18
|
+
end
|
19
|
+
|
20
|
+
def class_name
|
21
|
+
double.instance_variable_get('@name')
|
22
|
+
end
|
23
|
+
|
24
|
+
def double
|
25
|
+
__getobj__
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_operator
|
33
|
+
class_double? ? '.' : '#'
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_signatures
|
37
|
+
@method_signatures ||= []
|
38
|
+
end
|
39
|
+
|
40
|
+
def should_receive(method)
|
41
|
+
method_signature = MethodSignature.new(self)
|
42
|
+
method_signature.method = method
|
43
|
+
self.method_signatures << method_signature
|
44
|
+
@double_call = super(method)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
"#{VerifiedDouble}.of_#{class_double? ? 'class' : 'instance' }('#{class_name}')"
|
50
|
+
end
|
51
|
+
|
52
|
+
def with(*args)
|
53
|
+
self.method_signatures.last.args = args
|
54
|
+
@double_call.with(*args)
|
55
|
+
self
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class ReportUnverifiedSignatures
|
3
|
+
attr_accessor :double_registry, :nested_example_group
|
4
|
+
|
5
|
+
def initialize(double_registry, nested_example_group)
|
6
|
+
@double_registry, @nested_example_group = double_registry, nested_example_group
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute
|
10
|
+
VerifiedDouble::OutputUnverifiedSignatures.new(
|
11
|
+
VerifiedDouble::GetUnverifiedSignatures.new(
|
12
|
+
VerifiedDouble::GetRegisteredSignatures.new(double_registry),
|
13
|
+
VerifiedDouble::GetVerifiedSignatures.new(nested_example_group))).execute
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class VerifyDoublesService
|
3
|
+
def initialize(world)
|
4
|
+
@world = world
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
unverified_method_signatures = @world.unverified_method_signatures
|
9
|
+
if unverified_method_signatures.any?
|
10
|
+
output = ["The following mocks are not verified:" ] + unverified_method_signatures
|
11
|
+
puts output.join("\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec/fire'
|
2
|
+
|
3
|
+
require 'verified_double/get_registered_signatures'
|
4
|
+
require 'verified_double/get_unverified_signatures'
|
5
|
+
require 'verified_double/get_verified_signatures'
|
6
|
+
require 'verified_double/method_signature'
|
7
|
+
require 'verified_double/output_unverified_signatures'
|
8
|
+
require 'verified_double/recording_double'
|
9
|
+
require 'verified_double/report_unverified_signatures'
|
10
|
+
|
11
|
+
module VerifiedDouble
|
12
|
+
def self.of_class(class_name)
|
13
|
+
RecordingDouble.new(RSpec::Fire::FireClassDoubleBuilder.build(class_name).as_replaced_constant).tap do |double|
|
14
|
+
registry << double
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.of_instance(class_name)
|
19
|
+
RecordingDouble.new(RSpec::Fire::FireObjectDouble.new(class_name)).tap do |double|
|
20
|
+
registry << double
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.registry
|
25
|
+
@registry ||= []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'verified_double'
|
2
|
+
|
3
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
6
|
+
# loaded once.
|
7
|
+
#
|
8
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.include(RSpec::Fire)
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
21
|
+
|
22
|
+
RSpec::Fire.configure do |config|
|
23
|
+
config.verify_constant_names = true
|
24
|
+
end
|
data/spec/unit_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/get_registered_signatures'
|
3
|
+
|
4
|
+
describe VerifiedDouble::GetRegisteredSignatures do
|
5
|
+
let(:method_signature_1) {
|
6
|
+
fire_double('VerifiedDouble::MethodSignature', to_s: 'method_signature_1') }
|
7
|
+
|
8
|
+
let(:method_signature_2) {
|
9
|
+
fire_double('VerifiedDouble::MethodSignature', to_s: 'method_signature_2') }
|
10
|
+
|
11
|
+
let(:recording_double_1) {
|
12
|
+
fire_double('VerifiedDouble::RecordingDouble',
|
13
|
+
method_signatures: [method_signature_1]) }
|
14
|
+
|
15
|
+
let(:recording_double_2) {
|
16
|
+
fire_double('VerifiedDouble::RecordingDouble',
|
17
|
+
method_signatures: [method_signature_2]) }
|
18
|
+
|
19
|
+
subject { described_class.new(double_registry) }
|
20
|
+
|
21
|
+
describe "#execute" do
|
22
|
+
context "with multiple recording doubles in the registry" do
|
23
|
+
let(:double_registry){ [recording_double_1, recording_double_2] }
|
24
|
+
|
25
|
+
it "maps and flattens the method signatures of the recording doubles" do
|
26
|
+
expect(subject.execute).to eq(['method_signature_1', 'method_signature_2'])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with recording doubles with duplicate signatures" do
|
31
|
+
let(:recording_double_2) {
|
32
|
+
fire_double('VerifiedDouble::RecordingDouble',
|
33
|
+
method_signatures: [method_signature_1]) }
|
34
|
+
|
35
|
+
let(:double_registry){ [recording_double_1, recording_double_2] }
|
36
|
+
|
37
|
+
it "returns distinct method signatures" do
|
38
|
+
expect(subject.execute).to eq(['method_signature_1'])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/get_unverified_signatures'
|
3
|
+
|
4
|
+
describe VerifiedDouble::GetUnverifiedSignatures do
|
5
|
+
let(:get_registered_signatures_service){
|
6
|
+
fire_double('VerifiedDouble::GetRegisteredSignatures') }
|
7
|
+
|
8
|
+
let(:get_verified_signatures_service){
|
9
|
+
fire_double('VerifiedDouble::GetVerifiedSignatures') }
|
10
|
+
|
11
|
+
subject { described_class.new(get_registered_signatures_service, get_verified_signatures_service) }
|
12
|
+
|
13
|
+
describe "#execute" do
|
14
|
+
it "subtracts verified_signatures from registered_signatures" do
|
15
|
+
get_registered_signatures_service
|
16
|
+
.should_receive(:execute)
|
17
|
+
.and_return([:verified_signature, :unverified_signature])
|
18
|
+
|
19
|
+
get_verified_signatures_service
|
20
|
+
.should_receive(:execute)
|
21
|
+
.and_return([:verified_signature])
|
22
|
+
|
23
|
+
expect(subject.execute).to eq([:unverified_signature])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/get_verified_signatures'
|
3
|
+
|
4
|
+
describe VerifiedDouble::GetVerifiedSignatures do
|
5
|
+
let(:nested_example_group){ double(:nested_example_group) }
|
6
|
+
subject { described_class.new(nested_example_group) }
|
7
|
+
|
8
|
+
describe "#execute" do
|
9
|
+
let(:example_with_verified_contract_tag){
|
10
|
+
double(:example_with_verified_contract_tag,
|
11
|
+
metadata: { verifies_contract: 'signature' }) }
|
12
|
+
|
13
|
+
let(:example_without_verified_contract_tag){
|
14
|
+
double(:example_without_verified_contract_tag,
|
15
|
+
metadata: { focus: true }) }
|
16
|
+
|
17
|
+
it "filters rspec examples with the tag 'verifies_contract'" do
|
18
|
+
nested_example_group
|
19
|
+
.stub_chain(:class, :descendant_filtered_examples)
|
20
|
+
.and_return([example_with_verified_contract_tag, example_without_verified_contract_tag])
|
21
|
+
expect(subject.execute).to eq([example_with_verified_contract_tag.metadata[:verifies_contract]])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns unique signatures" do
|
25
|
+
nested_example_group
|
26
|
+
.stub_chain(:class, :descendant_filtered_examples)
|
27
|
+
.and_return([example_with_verified_contract_tag, example_with_verified_contract_tag])
|
28
|
+
expect(subject.execute).to eq([example_with_verified_contract_tag.metadata[:verifies_contract]])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/method_signature'
|
3
|
+
|
4
|
+
describe VerifiedDouble::MethodSignature do
|
5
|
+
describe "#to_s" do
|
6
|
+
let(:recording_double) {
|
7
|
+
fire_double('VerifiedDouble::RecordingDouble',
|
8
|
+
class_name: 'Dummy',
|
9
|
+
method_operator: '#') }
|
10
|
+
|
11
|
+
subject {
|
12
|
+
described_class.new(recording_double).tap {|method_signature|
|
13
|
+
method_signature.method = 'do_something' } }
|
14
|
+
|
15
|
+
context "when there are args" do
|
16
|
+
it "includes the args in the result" do
|
17
|
+
subject.args = [1, {}]
|
18
|
+
expect(subject.to_s).to eq("Dummy#do_something(Fixnum, Hash)")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when there are no args" do
|
23
|
+
it "displays an empty parenthesis for the args of the result" do
|
24
|
+
expect(subject.return_value).to be_nil
|
25
|
+
expect(subject.to_s).to eq("Dummy#do_something()")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when there is a nil arg" do
|
30
|
+
it "displays a nil class for the arg of the result" do
|
31
|
+
subject.args = [nil]
|
32
|
+
expect(subject.to_s).to eq("Dummy#do_something(NilClass)")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "where there is a return value" do
|
37
|
+
it "displays the return value" do
|
38
|
+
subject.return_value = true
|
39
|
+
expect(subject.to_s).to eq("Dummy#do_something()=>TrueClass")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "where there is no return value" do
|
44
|
+
it "does not include the hash rocket in the result" do
|
45
|
+
expect(subject.return_value).to be_nil
|
46
|
+
expect(subject.to_s).to eq("Dummy#do_something()")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/output_unverified_signatures'
|
3
|
+
|
4
|
+
describe VerifiedDouble::OutputUnverifiedSignatures do
|
5
|
+
let(:get_unverified_signatures_service){
|
6
|
+
fire_double('VerifiedDouble::GetUnverifiedSignatures') }
|
7
|
+
|
8
|
+
let(:unverified_signatures){ %w(UNVERIFIED_SIGNATURES_1 UNVERIFIED_SIGNATURES_2) }
|
9
|
+
|
10
|
+
subject { described_class.new(get_unverified_signatures_service) }
|
11
|
+
|
12
|
+
describe "#execute" do
|
13
|
+
context "where there are no unverified_signatures" do
|
14
|
+
it "should not output anything" do
|
15
|
+
get_unverified_signatures_service.should_receive(:execute).and_return([])
|
16
|
+
subject.should_not_receive(:puts)
|
17
|
+
|
18
|
+
subject.execute
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "where there are unverified_signatures" do
|
23
|
+
it "should output the unverified_signatures" do
|
24
|
+
get_unverified_signatures_service.should_receive(:execute).and_return(unverified_signatures)
|
25
|
+
subject.should_receive(:puts).with("The following mocks are not verified:\nUNVERIFIED_SIGNATURES_1\nUNVERIFIED_SIGNATURES_2")
|
26
|
+
|
27
|
+
subject.execute
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#unverified_signatures" do
|
33
|
+
it "are the results of get_unverified_signatures.execute" do
|
34
|
+
get_unverified_signatures_service.should_receive(:execute).and_return(unverified_signatures)
|
35
|
+
expect(subject.unverified_signatures).to eq(unverified_signatures)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require "verified_double/recording_double"
|
3
|
+
|
4
|
+
describe VerifiedDouble::RecordingDouble do
|
5
|
+
let(:class_name) { 'Object' }
|
6
|
+
let(:internal_double) { double(class_name) }
|
7
|
+
|
8
|
+
subject { VerifiedDouble::RecordingDouble.new(internal_double) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "requires a double" do
|
12
|
+
expect(subject.double).to eq(internal_double)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "delegates all unknown calls to its internal double" do
|
17
|
+
internal_double.should_receive(:do_something)
|
18
|
+
subject.do_something
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#to_s" do
|
22
|
+
class Dummy
|
23
|
+
end
|
24
|
+
|
25
|
+
context "where the internal double is a class" do
|
26
|
+
let(:class_name) { 'Dummy' }
|
27
|
+
let(:internal_double) { fire_class_double(class_name).as_replaced_constant }
|
28
|
+
|
29
|
+
it { expect(subject.to_s).to eq("VerifiedDouble.of_class('#{class_name}')") }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "where the internal double is an instance" do
|
33
|
+
let(:class_name) { 'Dummy' }
|
34
|
+
let(:internal_double) { fire_double(class_name) }
|
35
|
+
|
36
|
+
it { expect(subject.to_s).to eq("VerifiedDouble.of_instance('#{class_name}')") }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#inspect" do
|
41
|
+
it "is human-readable representation of the recording double, NOT the internal double" do
|
42
|
+
expect(subject.inspect).to match("VerifiedDouble")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#class_name" do
|
47
|
+
context "where the internal double is an RSpec::Fire::FireObjectDouble" do
|
48
|
+
it "is the name of the class represented by the FireObjectDouble" do
|
49
|
+
internal_double = fire_double('Object')
|
50
|
+
subject = described_class.new(internal_double)
|
51
|
+
expect(subject.class_name).to eq('Object')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "where the internal double is an rspec fire class double" do
|
56
|
+
it "is the name of the class represented by the rspec fire class double" do
|
57
|
+
internal_double = fire_class_double('Object').as_replaced_constant
|
58
|
+
subject = described_class.new(internal_double)
|
59
|
+
expect(subject.class_name).to eq('Object')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#class_double?" do
|
65
|
+
it "should be true if the internal double is an rspec fire class double" do
|
66
|
+
internal_double = fire_double('Object')
|
67
|
+
subject = described_class.new(internal_double)
|
68
|
+
expect(subject).to_not be_class_double
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should be false if the internal double is not an rspec fire class double" do
|
72
|
+
internal_double = fire_class_double('Object').as_replaced_constant
|
73
|
+
subject = described_class.new(internal_double)
|
74
|
+
expect(subject).to be_class_double
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#method_operator" do
|
79
|
+
context "when the subject wraps an instance double" do
|
80
|
+
let(:internal_double) { fire_double('Object') }
|
81
|
+
|
82
|
+
subject { VerifiedDouble::RecordingDouble.new(internal_double) }
|
83
|
+
|
84
|
+
it "is #" do
|
85
|
+
expect(subject.method_operator).to eq("#")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when the subject wraps a class double" do
|
90
|
+
let(:internal_double) { fire_class_double('Object') }
|
91
|
+
|
92
|
+
subject { VerifiedDouble::RecordingDouble.new(internal_double) }
|
93
|
+
|
94
|
+
it "is '.'" do
|
95
|
+
expect(subject.method_operator).to eq(".")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#should_receive(method)" do
|
101
|
+
it "appends a new method signature with the method to the recording double's method signatures" do
|
102
|
+
expect(subject.method_signatures).to be_empty
|
103
|
+
|
104
|
+
subject.should_receive(:to_s)
|
105
|
+
subject.should_receive(:inspect)
|
106
|
+
|
107
|
+
expect(subject.method_signatures.map(&:method)).to eq([:to_s, :inspect])
|
108
|
+
|
109
|
+
subject.to_s
|
110
|
+
subject.inspect
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#with(*args)" do
|
115
|
+
it "sets the args of the last method signature" do
|
116
|
+
subject.should_receive(:to_s).with(:arg_1, :arg_2)
|
117
|
+
|
118
|
+
expect(subject.method_signatures[0].args).to eq([:arg_1, :arg_2])
|
119
|
+
|
120
|
+
subject.to_s(:arg_1, :arg_2)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#and_return(return_value)" do
|
125
|
+
it "sets the return value of the last method signature" do
|
126
|
+
subject.should_receive(:to_s).with(:arg_1, :arg_2).and_return(:return_value)
|
127
|
+
|
128
|
+
expect(subject.method_signatures[0].return_value).to eq(:return_value)
|
129
|
+
|
130
|
+
subject.to_s(:arg_1, :arg_2)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/report_unverified_signatures'
|
3
|
+
|
4
|
+
describe VerifiedDouble::ReportUnverifiedSignatures do
|
5
|
+
let(:double_registry) { Set.new }
|
6
|
+
let(:nested_example_group) { double('nested_example_group') }
|
7
|
+
|
8
|
+
subject { described_class.new(double_registry, nested_example_group) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "requires a double registry and a nested example group" do
|
12
|
+
expect(subject.double_registry).to eq(double_registry)
|
13
|
+
expect(subject.nested_example_group).to eq(nested_example_group)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#execute" do
|
18
|
+
service_names = [
|
19
|
+
:get_registered_signatures,
|
20
|
+
:get_verified_signatures,
|
21
|
+
:get_unverified_signatures,
|
22
|
+
:output_unverified_signatures]
|
23
|
+
|
24
|
+
service_names.each do |service_name|
|
25
|
+
service_class_name = "#{VerifiedDouble}::#{service_name.to_s.classify.pluralize}"
|
26
|
+
let("#{service_name}_class") { fire_class_double(service_class_name).as_replaced_constant }
|
27
|
+
let("#{service_name}_service") { fire_double(service_class_name) }
|
28
|
+
end
|
29
|
+
|
30
|
+
it "gets registered and verified signatures and then outputs the unverified signatures" do
|
31
|
+
get_registered_signatures_class
|
32
|
+
.should_receive(:new)
|
33
|
+
.with(double_registry)
|
34
|
+
.and_return(get_registered_signatures_service)
|
35
|
+
|
36
|
+
get_verified_signatures_class
|
37
|
+
.should_receive(:new)
|
38
|
+
.with(nested_example_group)
|
39
|
+
.and_return(get_verified_signatures_service)
|
40
|
+
|
41
|
+
get_unverified_signatures_class
|
42
|
+
.should_receive(:new)
|
43
|
+
.with(get_registered_signatures_service, get_verified_signatures_service)
|
44
|
+
.and_return(get_unverified_signatures_service)
|
45
|
+
|
46
|
+
output_unverified_signatures_class
|
47
|
+
.should_receive(:new)
|
48
|
+
.with(get_unverified_signatures_service)
|
49
|
+
.and_return(output_unverified_signatures_service)
|
50
|
+
|
51
|
+
output_unverified_signatures_service.should_receive(:execute)
|
52
|
+
|
53
|
+
subject.execute
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'verified_double/verify_doubles_service'
|
2
|
+
|
3
|
+
describe VerifiedDouble::VerifyDoublesService do
|
4
|
+
let(:world) { double('VerifiedDouble::World') }
|
5
|
+
|
6
|
+
subject { described_class.new(world) }
|
7
|
+
|
8
|
+
describe "#execute" do
|
9
|
+
it "should output the unverified_method_signatures of the world if there are any" do
|
10
|
+
world.should_receive(:unverified_method_signatures).and_return(["Flight.find(Hash)=>Flight"])
|
11
|
+
subject.should_receive("puts")
|
12
|
+
|
13
|
+
subject.execute
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should do nothing if there are no unverified_method_signatures" do
|
17
|
+
world.should_receive(:unverified_method_signatures).and_return([])
|
18
|
+
subject.should_not_receive("puts")
|
19
|
+
|
20
|
+
subject.execute
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double'
|
3
|
+
|
4
|
+
describe VerifiedDouble do
|
5
|
+
describe ".registry" do
|
6
|
+
it "is a array by default" do
|
7
|
+
registry = VerifiedDouble.registry
|
8
|
+
expect(registry).to be_a(Array)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is memoized" do
|
12
|
+
expect(VerifiedDouble.registry).to equal(VerifiedDouble.registry)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".of_instance(class_name)" do
|
17
|
+
let(:class_name){ 'Object' }
|
18
|
+
|
19
|
+
let(:subject) { described_class.of_instance(class_name) }
|
20
|
+
|
21
|
+
it "creates an instance recording double" do
|
22
|
+
expect(subject).to be_a(VerifiedDouble::RecordingDouble)
|
23
|
+
expect(subject).to_not be_class_double
|
24
|
+
expect(subject.class_name).to eq(class_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "adds the double to the registry" do
|
28
|
+
described_class.registry.clear
|
29
|
+
recording_double = subject
|
30
|
+
expect(described_class.registry).to eq([recording_double])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".of_class(class_name)" do
|
35
|
+
let(:class_name){ 'Object' }
|
36
|
+
|
37
|
+
let(:subject) { described_class.of_class(class_name) }
|
38
|
+
|
39
|
+
it "creates a class recording double" do
|
40
|
+
expect(subject).to be_a(VerifiedDouble::RecordingDouble)
|
41
|
+
expect(subject).to be_class_double
|
42
|
+
expect(subject.double).to be_a(Module)
|
43
|
+
expect(subject.class_name).to eq(class_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "adds the double to the registry" do
|
47
|
+
described_class.registry.clear
|
48
|
+
recording_double = subject
|
49
|
+
expect(described_class.registry).to eq([recording_double])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'verified_double/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "verified_double"
|
8
|
+
gem.version = VerifiedDouble::VERSION
|
9
|
+
gem.authors = ["George Mendoza"]
|
10
|
+
gem.email = ["gsmendoza@gmail.com"]
|
11
|
+
gem.description = %q{Contract tests for rspec}
|
12
|
+
gem.summary = %q{VerifiedDouble would record any mock made in the test suite. It would then verify if the mock is valid by checking if there is a test against it.}
|
13
|
+
gem.homepage = "https://www.relishapp.com/gsmendoza/verified-double"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_runtime_dependency "rspec"
|
21
|
+
gem.add_runtime_dependency "rspec-fire"
|
22
|
+
|
23
|
+
gem.add_development_dependency "aruba"
|
24
|
+
gem.add_development_dependency "cucumber"
|
25
|
+
gem.add_development_dependency "pry"
|
26
|
+
gem.add_development_dependency "activesupport"
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: verified_double
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- George Mendoza
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
type: :runtime
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ! '>='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
name: rspec
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
type: :runtime
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
name: rspec-fire
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
type: :development
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
name: aruba
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
type: :development
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
name: cucumber
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
type: :development
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
name: pry
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
type: :development
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
name: activesupport
|
110
|
+
description: Contract tests for rspec
|
111
|
+
email:
|
112
|
+
- gsmendoza@gmail.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- .travis.yml
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- features/readme.md
|
124
|
+
- features/step_definitions/verified_double_steps.rb
|
125
|
+
- features/support/requires.rb
|
126
|
+
- features/verified_double.feature
|
127
|
+
- lib/verified_double.rb
|
128
|
+
- lib/verified_double/get_registered_signatures.rb
|
129
|
+
- lib/verified_double/get_unverified_signatures.rb
|
130
|
+
- lib/verified_double/get_verified_signatures.rb
|
131
|
+
- lib/verified_double/method_signature.rb
|
132
|
+
- lib/verified_double/output_unverified_signatures.rb
|
133
|
+
- lib/verified_double/recording_double.rb
|
134
|
+
- lib/verified_double/report_unverified_signatures.rb
|
135
|
+
- lib/verified_double/verify_doubles_service.rb
|
136
|
+
- lib/verified_double/version.rb
|
137
|
+
- spec/spec_helper.rb
|
138
|
+
- spec/unit_helper.rb
|
139
|
+
- spec/verified_double/get_registered_signatures_spec.rb
|
140
|
+
- spec/verified_double/get_unverified_signatures_spec.rb
|
141
|
+
- spec/verified_double/get_verified_signatures_spec.rb
|
142
|
+
- spec/verified_double/method_signature_spec.rb
|
143
|
+
- spec/verified_double/output_unverified_signatures_spec.rb
|
144
|
+
- spec/verified_double/recording_double_spec.rb
|
145
|
+
- spec/verified_double/report_unverified_signatures_spec.rb
|
146
|
+
- spec/verified_double/verify_doubles_service_spec.rb
|
147
|
+
- spec/verified_double_spec.rb
|
148
|
+
- verified_double.gemspec
|
149
|
+
homepage: https://www.relishapp.com/gsmendoza/verified-double
|
150
|
+
licenses: []
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
none: false
|
157
|
+
requirements:
|
158
|
+
- - ! '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
163
|
+
requirements:
|
164
|
+
- - ! '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubyforge_project:
|
169
|
+
rubygems_version: 1.8.24
|
170
|
+
signing_key:
|
171
|
+
specification_version: 3
|
172
|
+
summary: VerifiedDouble would record any mock made in the test suite. It would then
|
173
|
+
verify if the mock is valid by checking if there is a test against it.
|
174
|
+
test_files:
|
175
|
+
- features/readme.md
|
176
|
+
- features/step_definitions/verified_double_steps.rb
|
177
|
+
- features/support/requires.rb
|
178
|
+
- features/verified_double.feature
|
179
|
+
- spec/spec_helper.rb
|
180
|
+
- spec/unit_helper.rb
|
181
|
+
- spec/verified_double/get_registered_signatures_spec.rb
|
182
|
+
- spec/verified_double/get_unverified_signatures_spec.rb
|
183
|
+
- spec/verified_double/get_verified_signatures_spec.rb
|
184
|
+
- spec/verified_double/method_signature_spec.rb
|
185
|
+
- spec/verified_double/output_unverified_signatures_spec.rb
|
186
|
+
- spec/verified_double/recording_double_spec.rb
|
187
|
+
- spec/verified_double/report_unverified_signatures_spec.rb
|
188
|
+
- spec/verified_double/verify_doubles_service_spec.rb
|
189
|
+
- spec/verified_double_spec.rb
|
190
|
+
has_rdoc:
|