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.
Files changed (33) hide show
  1. data/.gitignore +21 -0
  2. data/.travis.yml +6 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +65 -0
  6. data/Rakefile +1 -0
  7. data/features/readme.md +65 -0
  8. data/features/step_definitions/verified_double_steps.rb +37 -0
  9. data/features/support/requires.rb +1 -0
  10. data/features/verified_double.feature +152 -0
  11. data/lib/verified_double/get_registered_signatures.rb +11 -0
  12. data/lib/verified_double/get_unverified_signatures.rb +11 -0
  13. data/lib/verified_double/get_verified_signatures.rb +16 -0
  14. data/lib/verified_double/method_signature.rb +16 -0
  15. data/lib/verified_double/output_unverified_signatures.rb +18 -0
  16. data/lib/verified_double/recording_double.rb +58 -0
  17. data/lib/verified_double/report_unverified_signatures.rb +16 -0
  18. data/lib/verified_double/verify_doubles_service.rb +15 -0
  19. data/lib/verified_double/version.rb +3 -0
  20. data/lib/verified_double.rb +28 -0
  21. data/spec/spec_helper.rb +24 -0
  22. data/spec/unit_helper.rb +7 -0
  23. data/spec/verified_double/get_registered_signatures_spec.rb +42 -0
  24. data/spec/verified_double/get_unverified_signatures_spec.rb +28 -0
  25. data/spec/verified_double/get_verified_signatures_spec.rb +33 -0
  26. data/spec/verified_double/method_signature_spec.rb +50 -0
  27. data/spec/verified_double/output_unverified_signatures_spec.rb +38 -0
  28. data/spec/verified_double/recording_double_spec.rb +133 -0
  29. data/spec/verified_double/report_unverified_signatures_spec.rb +57 -0
  30. data/spec/verified_double/verify_doubles_service_spec.rb +24 -0
  31. data/spec/verified_double_spec.rb +52 -0
  32. data/verified_double.gemspec +28 -0
  33. 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
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ script:
5
+ - bundle exec rspec
6
+ - bundle exec cucumber
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in verified_double.gemspec
4
+ gemspec
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"
@@ -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 GetRegisteredSignatures
3
+ def initialize(double_registry)
4
+ @double_registry = double_registry
5
+ end
6
+
7
+ def execute
8
+ @double_registry.map(&:method_signatures).flatten.map(&:to_s).uniq
9
+ end
10
+ end
11
+ end
@@ -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,3 @@
1
+ module VerifiedDouble
2
+ VERSION = "0.0.1"
3
+ 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
+
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'active_support/core_ext/string'
2
+ require 'pry'
3
+ require 'rspec/fire'
4
+
5
+ RSpec.configure do |config|
6
+ config.include(RSpec::Fire)
7
+ end
@@ -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: