verified_double 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: