verified_double 0.0.1 → 0.0.2
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/.travis.yml +1 -1
- data/CHANGELOG.markdown +12 -0
- data/features/CHANGELOG.markdown +12 -0
- data/features/customizing_arguments_and_return_values.feature +105 -0
- data/lib/verified_double.rb +3 -0
- data/lib/verified_double/boolean.rb +4 -0
- data/lib/verified_double/get_registered_signatures.rb +1 -1
- data/lib/verified_double/get_unverified_signatures.rb +3 -1
- data/lib/verified_double/get_verified_signatures.rb +1 -0
- data/lib/verified_double/method_signature.rb +45 -6
- data/lib/verified_double/method_signature_value.rb +29 -0
- data/lib/verified_double/output_unverified_signatures.rb +1 -1
- data/lib/verified_double/parse_method_signature.rb +49 -0
- data/lib/verified_double/recording_double.rb +8 -4
- data/lib/verified_double/version.rb +1 -1
- data/spec/unit_helper.rb +8 -0
- data/spec/verified_double/get_registered_signatures_spec.rb +4 -4
- data/spec/verified_double/get_unverified_signatures_spec.rb +28 -4
- data/spec/verified_double/get_verified_signatures_spec.rb +32 -2
- data/spec/verified_double/method_signature_spec.rb +119 -16
- data/spec/verified_double/method_signature_value_spec.rb +82 -0
- data/spec/verified_double/output_unverified_signatures_spec.rb +23 -3
- data/spec/verified_double/parse_method_signature_spec.rb +95 -0
- data/spec/verified_double/recording_double_spec.rb +7 -3
- data/verified_double.gemspec +1 -1
- metadata +18 -6
data/.travis.yml
CHANGED
data/CHANGELOG.markdown
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
0.0.2 - 2013-06-22
|
2
|
+
------------------
|
3
|
+
|
4
|
+
* Passes #1: Customizing arguments and return values.
|
5
|
+
* Set rspec-fire to 1.1 for the meantime.
|
6
|
+
|
7
|
+
0.0.1 - 2013-06-02
|
8
|
+
------------------
|
9
|
+
|
10
|
+
* Initial release. Passes "I want to be informed if the mocks I use are verified by contract tests" feature.
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
0.0.2 - 2013-06-22
|
2
|
+
------------------
|
3
|
+
|
4
|
+
* Passes #1: Customizing arguments and return values.
|
5
|
+
* Set rspec-fire to 1.1 for the meantime.
|
6
|
+
|
7
|
+
0.0.1 - 2013-06-02
|
8
|
+
------------------
|
9
|
+
|
10
|
+
* Initial release. Passes "I want to be informed if the mocks I use are verified by contract tests" feature.
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
Feature: Customizing arguments and return values
|
2
|
+
As a developer
|
3
|
+
I want the ability to make contract arguments and return values more or less specific
|
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
|
+
end
|
13
|
+
|
14
|
+
class Collaborator
|
15
|
+
def some_method(input)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
"""
|
19
|
+
|
20
|
+
And the test suite has an after(:suite) callback asking VerifiedDouble to report unverified doubles:
|
21
|
+
"""
|
22
|
+
require 'verified_double'
|
23
|
+
require 'main'
|
24
|
+
|
25
|
+
RSpec.configure do |config|
|
26
|
+
config.after :suite do
|
27
|
+
VerifiedDouble::ReportUnverifiedSignatures.new(VerifiedDouble.registry, self).execute
|
28
|
+
end
|
29
|
+
end
|
30
|
+
"""
|
31
|
+
|
32
|
+
And a test that uses VerifiedDouble to mock an object:
|
33
|
+
"""
|
34
|
+
require 'spec_helper'
|
35
|
+
describe ObjectUnderTest do
|
36
|
+
let(:input) { :input }
|
37
|
+
let(:output) { :output }
|
38
|
+
let(:instance_double) { VerifiedDouble.of_instance('Collaborator') }
|
39
|
+
|
40
|
+
it "tests something" do
|
41
|
+
instance_double.should_receive(:some_method).with(input).and_return(output)
|
42
|
+
ObjectUnderTest.new.do_something(instance_double, input)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
"""
|
46
|
+
|
47
|
+
Scenario: More general argument
|
48
|
+
Given the test suite has a contract test for the mock:
|
49
|
+
"""
|
50
|
+
require 'spec_helper'
|
51
|
+
|
52
|
+
describe 'Collaborator' do
|
53
|
+
it "tests something", verifies_contract: 'Collaborator#some_method(Object)=>Symbol' do
|
54
|
+
# do nothing
|
55
|
+
end
|
56
|
+
end
|
57
|
+
"""
|
58
|
+
|
59
|
+
When I run the test suite
|
60
|
+
Then I should not see any output saying the mock is unverified
|
61
|
+
|
62
|
+
Scenario: More specific argument
|
63
|
+
Given the test suite has a contract test for the mock:
|
64
|
+
"""
|
65
|
+
require 'spec_helper'
|
66
|
+
|
67
|
+
describe 'Collaborator' do
|
68
|
+
it "tests something", verifies_contract: 'Collaborator#some_method(:input)=>Symbol' do
|
69
|
+
# do nothing
|
70
|
+
end
|
71
|
+
end
|
72
|
+
"""
|
73
|
+
|
74
|
+
When I run the test suite
|
75
|
+
Then I should not see any output saying the mock is unverified
|
76
|
+
|
77
|
+
Scenario: More general return value
|
78
|
+
Given the test suite has a contract test for the mock:
|
79
|
+
"""
|
80
|
+
require 'spec_helper'
|
81
|
+
|
82
|
+
describe 'Collaborator' do
|
83
|
+
it "tests something", verifies_contract: 'Collaborator#some_method(Symbol)=>Object' do
|
84
|
+
# do nothing
|
85
|
+
end
|
86
|
+
end
|
87
|
+
"""
|
88
|
+
|
89
|
+
When I run the test suite
|
90
|
+
Then I should not see any output saying the mock is unverified
|
91
|
+
|
92
|
+
Scenario: More specific return value
|
93
|
+
Given the test suite has a contract test for the mock:
|
94
|
+
"""
|
95
|
+
require 'spec_helper'
|
96
|
+
|
97
|
+
describe 'Collaborator' do
|
98
|
+
it "tests something", verifies_contract: 'Collaborator#some_method(Symbol)=>:output' do
|
99
|
+
# do nothing
|
100
|
+
end
|
101
|
+
end
|
102
|
+
"""
|
103
|
+
|
104
|
+
When I run the test suite
|
105
|
+
Then I should not see any output saying the mock is unverified
|
data/lib/verified_double.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'rspec/fire'
|
2
2
|
|
3
|
+
require 'verified_double/boolean'
|
3
4
|
require 'verified_double/get_registered_signatures'
|
4
5
|
require 'verified_double/get_unverified_signatures'
|
5
6
|
require 'verified_double/get_verified_signatures'
|
6
7
|
require 'verified_double/method_signature'
|
8
|
+
require 'verified_double/method_signature_value'
|
7
9
|
require 'verified_double/output_unverified_signatures'
|
10
|
+
require 'verified_double/parse_method_signature'
|
8
11
|
require 'verified_double/recording_double'
|
9
12
|
require 'verified_double/report_unverified_signatures'
|
10
13
|
|
@@ -5,7 +5,9 @@ module VerifiedDouble
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def execute
|
8
|
-
@get_registered_signatures.execute
|
8
|
+
@get_registered_signatures.execute.select{|registered_signature|
|
9
|
+
@get_verified_signatures.execute.all?{|verified_signature|
|
10
|
+
! registered_signature.accepts?(verified_signature) } }
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
@@ -1,16 +1,55 @@
|
|
1
1
|
module VerifiedDouble
|
2
2
|
class MethodSignature
|
3
|
-
attr_accessor :args, :method, :
|
3
|
+
attr_accessor :args, :class_name, :method, :method_operator, :return_values
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
|
5
|
+
def initialize(attributes = {})
|
6
|
+
attributes.each do |name, value|
|
7
|
+
self.send "#{name}=", value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def accepts?(other)
|
12
|
+
self.class_name == other.class_name &&
|
13
|
+
self.method_operator == other.method_operator &&
|
14
|
+
self.method == other.method &&
|
15
|
+
self.args.size == other.args.size &&
|
16
|
+
(0 ... args.size).all?{|i| self.args[i].accepts?(other.args[i]) } &&
|
17
|
+
self.return_values.size == other.return_values.size &&
|
18
|
+
(0 ... return_values.size).all?{|i| self.return_values[i].accepts?(other.return_values[i]) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def args
|
22
|
+
@args ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
def eql?(other)
|
26
|
+
to_s.eql?(other.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def hash
|
30
|
+
to_s.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def recommended_verified_signature
|
34
|
+
self.clone.tap do |result|
|
35
|
+
result.args = result.args.map{|arg| arg.recommended_value }
|
36
|
+
result.return_values = result.return_values.map{|return_value| return_value.recommended_value }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def return_values
|
41
|
+
@return_values ||= []
|
7
42
|
end
|
8
43
|
|
9
44
|
def to_s
|
45
|
+
args_string = args.map(&:value).map{|v| v || 'nil'}.join(', ')
|
46
|
+
return_values_string = return_values.map(&:value).map{|v| v || 'nil'}.join(', ')
|
47
|
+
return_values_string = nil if return_values_string.empty?
|
48
|
+
|
10
49
|
result = [
|
11
|
-
"#{
|
12
|
-
|
13
|
-
result.compact.join("=>")
|
50
|
+
"#{class_name}#{method_operator}#{method}(#{args_string})",
|
51
|
+
return_values_string]
|
52
|
+
result.flatten.compact.join("=>")
|
14
53
|
end
|
15
54
|
end
|
16
55
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class MethodSignatureValue
|
3
|
+
attr_reader :value
|
4
|
+
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def accepts?(other)
|
10
|
+
if self.value.is_a?(Class) || ! other.value.is_a?(Class)
|
11
|
+
self.value == other.value
|
12
|
+
else
|
13
|
+
self.modified_class.ancestors.include?(other.value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def modified_class
|
18
|
+
if value == true or value == false
|
19
|
+
VerifiedDouble::Boolean
|
20
|
+
else
|
21
|
+
value.class
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def recommended_value
|
26
|
+
self.class.new(self.modified_class)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -6,7 +6,7 @@ module VerifiedDouble
|
|
6
6
|
|
7
7
|
def execute
|
8
8
|
if unverified_signatures.any?
|
9
|
-
output = ["The following mocks are not verified:" ] + unverified_signatures
|
9
|
+
output = ["The following mocks are not verified:" ] + unverified_signatures.map(&:recommended_verified_signature)
|
10
10
|
puts output.join("\n")
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module VerifiedDouble
|
2
|
+
class ParseMethodSignature
|
3
|
+
attr_reader :string
|
4
|
+
|
5
|
+
def initialize(string)
|
6
|
+
@string = string
|
7
|
+
end
|
8
|
+
|
9
|
+
def args
|
10
|
+
results = string.scan(/\((.*)\)/)[0]
|
11
|
+
if results
|
12
|
+
results[0].split(',').map{|arg| MethodSignatureValue.new(eval(arg)) }
|
13
|
+
else
|
14
|
+
[]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def class_name
|
19
|
+
string.scan(/(.*)[\.\#]/)[0][0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
MethodSignature.new(
|
24
|
+
class_name: class_name,
|
25
|
+
method_operator: method_operator,
|
26
|
+
method: method,
|
27
|
+
args: args,
|
28
|
+
return_values: return_values)
|
29
|
+
end
|
30
|
+
|
31
|
+
def method
|
32
|
+
string.scan(/[\.\#](.*?)(=>|\(|$)/)[0][0]
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_operator
|
36
|
+
string.scan(/[\.\#]/)[0][0]
|
37
|
+
end
|
38
|
+
|
39
|
+
def return_values
|
40
|
+
results = string.scan(/=>(.*)/)[0]
|
41
|
+
if results
|
42
|
+
results[0].split(',').map{|return_value|
|
43
|
+
MethodSignatureValue.new(eval(return_value)) }
|
44
|
+
else
|
45
|
+
[]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -8,7 +8,7 @@ module VerifiedDouble
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def and_return(return_value)
|
11
|
-
self.method_signatures.last.
|
11
|
+
self.method_signatures.last.return_values = [MethodSignatureValue.new(return_value)]
|
12
12
|
@double_call.and_return(return_value)
|
13
13
|
self
|
14
14
|
end
|
@@ -38,8 +38,11 @@ module VerifiedDouble
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def should_receive(method)
|
41
|
-
method_signature = MethodSignature.new(
|
42
|
-
|
41
|
+
method_signature = MethodSignature.new(
|
42
|
+
class_name: class_name,
|
43
|
+
method_operator: method_operator,
|
44
|
+
method: method.to_s)
|
45
|
+
|
43
46
|
self.method_signatures << method_signature
|
44
47
|
@double_call = super(method)
|
45
48
|
self
|
@@ -50,7 +53,8 @@ module VerifiedDouble
|
|
50
53
|
end
|
51
54
|
|
52
55
|
def with(*args)
|
53
|
-
self.method_signatures.last.args =
|
56
|
+
self.method_signatures.last.args =
|
57
|
+
args.map{|arg| MethodSignatureValue.new(arg) }
|
54
58
|
@double_call.with(*args)
|
55
59
|
self
|
56
60
|
end
|
data/spec/unit_helper.rb
CHANGED
@@ -2,6 +2,14 @@ require 'active_support/core_ext/string'
|
|
2
2
|
require 'pry'
|
3
3
|
require 'rspec/fire'
|
4
4
|
|
5
|
+
require 'verified_double/boolean'
|
6
|
+
|
7
|
+
# Requiring because these are Value objects.
|
8
|
+
# As value objects, we treat them as primitives.
|
9
|
+
# Hence, there should be no need to mock or stub them.
|
10
|
+
require "verified_double/method_signature"
|
11
|
+
require "verified_double/method_signature_value"
|
12
|
+
|
5
13
|
RSpec.configure do |config|
|
6
14
|
config.include(RSpec::Fire)
|
7
15
|
end
|
@@ -3,10 +3,10 @@ require 'verified_double/get_registered_signatures'
|
|
3
3
|
|
4
4
|
describe VerifiedDouble::GetRegisteredSignatures do
|
5
5
|
let(:method_signature_1) {
|
6
|
-
|
6
|
+
VerifiedDouble::MethodSignature.new(class_name: 'Object', method_operator: '#', method: 'to_s') }
|
7
7
|
|
8
8
|
let(:method_signature_2) {
|
9
|
-
|
9
|
+
VerifiedDouble::MethodSignature.new(class_name: 'Object', method_operator: '#', method: 'inspect') }
|
10
10
|
|
11
11
|
let(:recording_double_1) {
|
12
12
|
fire_double('VerifiedDouble::RecordingDouble',
|
@@ -23,7 +23,7 @@ describe VerifiedDouble::GetRegisteredSignatures do
|
|
23
23
|
let(:double_registry){ [recording_double_1, recording_double_2] }
|
24
24
|
|
25
25
|
it "maps and flattens the method signatures of the recording doubles" do
|
26
|
-
expect(subject.execute).to eq([
|
26
|
+
expect(subject.execute).to eq([method_signature_1, method_signature_2])
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -35,7 +35,7 @@ describe VerifiedDouble::GetRegisteredSignatures do
|
|
35
35
|
let(:double_registry){ [recording_double_1, recording_double_2] }
|
36
36
|
|
37
37
|
it "returns distinct method signatures" do
|
38
|
-
expect(subject.execute).to eq([
|
38
|
+
expect(subject.execute).to eq([method_signature_1])
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -11,16 +11,40 @@ describe VerifiedDouble::GetUnverifiedSignatures do
|
|
11
11
|
subject { described_class.new(get_registered_signatures_service, get_verified_signatures_service) }
|
12
12
|
|
13
13
|
describe "#execute" do
|
14
|
-
|
14
|
+
let(:registered_signature) {
|
15
|
+
VerifiedDouble::MethodSignature.new(
|
16
|
+
class_name: 'Person',
|
17
|
+
method: 'find',
|
18
|
+
method_operator: '.',
|
19
|
+
args: [VerifiedDouble::MethodSignatureValue.new(1)]) }
|
20
|
+
|
21
|
+
let(:registered_signature_without_match) {
|
22
|
+
VerifiedDouble::MethodSignature.new(
|
23
|
+
class_name: 'Person',
|
24
|
+
method: 'save!',
|
25
|
+
method_operator: '#') }
|
26
|
+
|
27
|
+
let(:verified_signature) {
|
28
|
+
VerifiedDouble::MethodSignature.new(
|
29
|
+
class_name: 'Person',
|
30
|
+
method: 'find',
|
31
|
+
method_operator: '.',
|
32
|
+
args: [VerifiedDouble::MethodSignatureValue.new(Object)]) }
|
33
|
+
|
34
|
+
it "retains registered signatures that cannot accept any of the verified_signatures" do
|
35
|
+
expect(registered_signature.accepts?(verified_signature)).to be_true
|
36
|
+
expect(registered_signature_without_match.accepts?(verified_signature)).to be_false
|
37
|
+
|
15
38
|
get_registered_signatures_service
|
16
39
|
.should_receive(:execute)
|
17
|
-
.and_return([
|
40
|
+
.and_return([registered_signature, registered_signature_without_match])
|
18
41
|
|
19
42
|
get_verified_signatures_service
|
20
43
|
.should_receive(:execute)
|
21
|
-
.
|
44
|
+
.at_least(:once)
|
45
|
+
.and_return([verified_signature])
|
22
46
|
|
23
|
-
expect(subject.execute).to eq([
|
47
|
+
expect(subject.execute).to eq([registered_signature_without_match])
|
24
48
|
end
|
25
49
|
end
|
26
50
|
end
|
@@ -2,7 +2,16 @@ require 'unit_helper'
|
|
2
2
|
require 'verified_double/get_verified_signatures'
|
3
3
|
|
4
4
|
describe VerifiedDouble::GetVerifiedSignatures do
|
5
|
+
let(:method_signature) { VerifiedDouble::MethodSignature.new }
|
6
|
+
|
5
7
|
let(:nested_example_group){ double(:nested_example_group) }
|
8
|
+
|
9
|
+
let(:parse_method_signature_service) {
|
10
|
+
fire_double('VerifiedDouble::ParseMethodSignature') }
|
11
|
+
|
12
|
+
let(:parse_method_signature_service_class) {
|
13
|
+
fire_class_double('VerifiedDouble::ParseMethodSignature').as_replaced_constant }
|
14
|
+
|
6
15
|
subject { described_class.new(nested_example_group) }
|
7
16
|
|
8
17
|
describe "#execute" do
|
@@ -18,14 +27,35 @@ describe VerifiedDouble::GetVerifiedSignatures do
|
|
18
27
|
nested_example_group
|
19
28
|
.stub_chain(:class, :descendant_filtered_examples)
|
20
29
|
.and_return([example_with_verified_contract_tag, example_without_verified_contract_tag])
|
21
|
-
|
30
|
+
|
31
|
+
parse_method_signature_service_class
|
32
|
+
.should_receive(:new)
|
33
|
+
.with(example_with_verified_contract_tag.metadata[:verifies_contract])
|
34
|
+
.and_return(parse_method_signature_service)
|
35
|
+
|
36
|
+
parse_method_signature_service
|
37
|
+
.should_receive(:execute)
|
38
|
+
.and_return(method_signature)
|
39
|
+
|
40
|
+
expect(subject.execute).to eq([method_signature])
|
22
41
|
end
|
23
42
|
|
24
43
|
it "returns unique signatures" do
|
25
44
|
nested_example_group
|
26
45
|
.stub_chain(:class, :descendant_filtered_examples)
|
27
46
|
.and_return([example_with_verified_contract_tag, example_with_verified_contract_tag])
|
28
|
-
|
47
|
+
|
48
|
+
parse_method_signature_service_class
|
49
|
+
.should_receive(:new)
|
50
|
+
.with(example_with_verified_contract_tag.metadata[:verifies_contract])
|
51
|
+
.at_least(:once)
|
52
|
+
.and_return(parse_method_signature_service)
|
53
|
+
|
54
|
+
parse_method_signature_service
|
55
|
+
.should_receive(:execute)
|
56
|
+
.and_return(method_signature)
|
57
|
+
|
58
|
+
expect(subject.execute).to eq([method_signature])
|
29
59
|
end
|
30
60
|
end
|
31
61
|
end
|
@@ -2,49 +2,152 @@ require 'unit_helper'
|
|
2
2
|
require 'verified_double/method_signature'
|
3
3
|
|
4
4
|
describe VerifiedDouble::MethodSignature do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class Dummy
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:attributes){
|
9
|
+
{ class_name: 'Dummy',
|
10
|
+
method_operator: '#' } }
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
it { expect(subject.return_values).to be_empty }
|
14
|
+
it { expect(subject.args).to be_empty }
|
15
|
+
end
|
10
16
|
|
17
|
+
describe "#to_s" do
|
11
18
|
subject {
|
12
|
-
described_class.new(
|
19
|
+
described_class.new(attributes).tap {|method_signature|
|
13
20
|
method_signature.method = 'do_something' } }
|
14
21
|
|
15
22
|
context "when there are args" do
|
16
|
-
it "includes the
|
17
|
-
subject.args = [1, {}]
|
18
|
-
expect(subject.to_s).to eq("Dummy#do_something(
|
23
|
+
it "includes the arg values in the result" do
|
24
|
+
subject.args = [VerifiedDouble::MethodSignatureValue.new(1), VerifiedDouble::MethodSignatureValue.new({})]
|
25
|
+
expect(subject.to_s).to eq("Dummy#do_something(1, {})")
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
29
|
context "when there are no args" do
|
23
30
|
it "displays an empty parenthesis for the args of the result" do
|
24
|
-
expect(subject.
|
31
|
+
expect(subject.args).to be_empty
|
25
32
|
expect(subject.to_s).to eq("Dummy#do_something()")
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
29
36
|
context "when there is a nil arg" do
|
30
|
-
it "displays
|
31
|
-
subject.args = [nil]
|
32
|
-
expect(subject.to_s).to eq("Dummy#do_something(
|
37
|
+
it "displays nil for the arg of the result" do
|
38
|
+
subject.args = [VerifiedDouble::MethodSignatureValue.new(nil)]
|
39
|
+
expect(subject.to_s).to eq("Dummy#do_something(nil)")
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
43
|
context "where there is a return value" do
|
37
44
|
it "displays the return value" do
|
38
|
-
subject.
|
39
|
-
expect(subject.to_s).to eq("Dummy#do_something()=>
|
45
|
+
subject.return_values = [VerifiedDouble::MethodSignatureValue.new(true)]
|
46
|
+
expect(subject.to_s).to eq("Dummy#do_something()=>true")
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
43
50
|
context "where there is no return value" do
|
44
51
|
it "does not include the hash rocket in the result" do
|
45
|
-
expect(subject.
|
52
|
+
expect(subject.return_values).to be_empty
|
46
53
|
expect(subject.to_s).to eq("Dummy#do_something()")
|
47
54
|
end
|
48
55
|
end
|
49
56
|
end
|
57
|
+
|
58
|
+
context "multiple method signatures with the same #to_s" do
|
59
|
+
let(:method_signature){
|
60
|
+
described_class.new(attributes).tap {|method_signature|
|
61
|
+
method_signature.method = 'do_something' } }
|
62
|
+
|
63
|
+
let(:method_signature_with_same_to_s){
|
64
|
+
described_class.new(attributes).tap {|method_signature|
|
65
|
+
method_signature.method = 'do_something' } }
|
66
|
+
|
67
|
+
it { expect(method_signature.to_s).to eq(method_signature_with_same_to_s.to_s) }
|
68
|
+
it { expect(method_signature.hash).to eq(method_signature_with_same_to_s.hash) }
|
69
|
+
it { expect(method_signature.eql?(method_signature_with_same_to_s)).to be_true }
|
70
|
+
it { expect([method_signature, method_signature_with_same_to_s].uniq == [method_signature]).to be_true }
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#accepts?(other)" do
|
74
|
+
let(:method_signature){
|
75
|
+
described_class.new(
|
76
|
+
class_name: 'Dummy',
|
77
|
+
method_operator: '.',
|
78
|
+
method: 'find',
|
79
|
+
args: [VerifiedDouble::MethodSignatureValue.new(1)],
|
80
|
+
return_values: [VerifiedDouble::MethodSignatureValue.new(Dummy.new)]) }
|
81
|
+
|
82
|
+
subject { method_signature.accepts?(other) }
|
83
|
+
|
84
|
+
context "where self has same attributes as other" do
|
85
|
+
let(:other){ method_signature.clone }
|
86
|
+
it { expect(subject).to be_true }
|
87
|
+
end
|
88
|
+
|
89
|
+
context "where self and other have different class names" do
|
90
|
+
let(:other){ method_signature.clone.tap{|ms| ms.class_name = 'Object' } }
|
91
|
+
it { expect(subject).to be_false }
|
92
|
+
end
|
93
|
+
|
94
|
+
context "where self and other have different method operators" do
|
95
|
+
let(:other){ method_signature.clone.tap{|ms| ms.method_operator = '#' } }
|
96
|
+
it { expect(subject).to be_false }
|
97
|
+
end
|
98
|
+
|
99
|
+
context "where self and other have different methods" do
|
100
|
+
let(:other){ method_signature.clone.tap{|ms| ms.method = 'destroy' } }
|
101
|
+
it { expect(subject).to be_false }
|
102
|
+
end
|
103
|
+
|
104
|
+
context "where self and other have different number of args" do
|
105
|
+
let(:other){
|
106
|
+
method_signature.clone.tap{|ms|
|
107
|
+
ms.args = [VerifiedDouble::MethodSignatureValue.new(1), VerifiedDouble::MethodSignatureValue.new(2)] } }
|
108
|
+
|
109
|
+
it { expect(subject).to be_false }
|
110
|
+
end
|
111
|
+
|
112
|
+
context "where not all of self's args accept the args of other" do
|
113
|
+
let(:other){
|
114
|
+
method_signature.clone.tap{|ms|
|
115
|
+
ms.args = [VerifiedDouble::MethodSignatureValue.new(2)] } }
|
116
|
+
|
117
|
+
it { expect(subject).to be_false }
|
118
|
+
end
|
119
|
+
|
120
|
+
context "where self and other have different number of return values" do
|
121
|
+
let(:other){
|
122
|
+
method_signature.clone.tap{|ms|
|
123
|
+
ms.return_values = [VerifiedDouble::MethodSignatureValue.new(1), VerifiedDouble::MethodSignatureValue.new(2)] } }
|
124
|
+
|
125
|
+
it { expect(subject).to be_false }
|
126
|
+
end
|
127
|
+
|
128
|
+
context "where not all of self's return values accept the return values of other" do
|
129
|
+
let(:other){
|
130
|
+
method_signature.clone.tap{|ms|
|
131
|
+
ms.return_values = [VerifiedDouble::MethodSignatureValue.new(Symbol)] } }
|
132
|
+
|
133
|
+
it { expect(subject).to be_false }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#recommended_verified_signature" do
|
138
|
+
let(:method_signature){
|
139
|
+
described_class.new(
|
140
|
+
class_name: 'Dummy',
|
141
|
+
method_operator: '.',
|
142
|
+
method: 'find',
|
143
|
+
args: [VerifiedDouble::MethodSignatureValue.new(1)],
|
144
|
+
return_values: [VerifiedDouble::MethodSignatureValue.new(Dummy.new)]) }
|
145
|
+
|
146
|
+
subject { method_signature.recommended_verified_signature }
|
147
|
+
|
148
|
+
it "is a method signature that is recommended for the user to verify" do
|
149
|
+
expect(subject.args[0].value).to eq(method_signature.args[0].recommended_value.value)
|
150
|
+
expect(subject.return_values[0].value).to eq(method_signature.return_values[0].recommended_value.value)
|
151
|
+
end
|
152
|
+
end
|
50
153
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/method_signature_value'
|
3
|
+
|
4
|
+
describe VerifiedDouble::MethodSignatureValue do
|
5
|
+
let(:value){ :some_value }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
it "requires a value from a method signature" do
|
9
|
+
described_class.new(value)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#accepts?(other)" do
|
14
|
+
subject { this.accepts?(other) }
|
15
|
+
|
16
|
+
context "where self's value is an actual class and other's value matches it" do
|
17
|
+
let(:this){ described_class.new(Fixnum) }
|
18
|
+
let(:other){ described_class.new(Fixnum) }
|
19
|
+
it { expect(subject).to be_true }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "where self's value is an actual class and other's value does not match it" do
|
23
|
+
let(:this){ described_class.new(Fixnum) }
|
24
|
+
let(:other){ described_class.new(Object) }
|
25
|
+
it { expect(subject).to be_false }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "where the other value is an instance and self's value matches it" do
|
29
|
+
let(:this){ described_class.new(1) }
|
30
|
+
let(:other){ described_class.new(1) }
|
31
|
+
it { expect(subject).to be_true }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "where the other value is an instance and self's value does not it" do
|
35
|
+
let(:this){ described_class.new(2) }
|
36
|
+
let(:other){ described_class.new(1) }
|
37
|
+
it { expect(subject).to be_false }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "where self is an instance and the other's class is an ancestor of self's modified class" do
|
41
|
+
let(:this){ described_class.new(1) }
|
42
|
+
let(:other){ described_class.new(Object) }
|
43
|
+
it { expect(subject).to be_true }
|
44
|
+
end
|
45
|
+
|
46
|
+
context "where self is an instance and the other's class is not an ancestor of self's modified class" do
|
47
|
+
let(:this){ described_class.new(1) }
|
48
|
+
let(:other){ described_class.new(Float) }
|
49
|
+
it { expect(subject).to be_false }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#modified_class" do
|
54
|
+
subject { method_signature_value.modified_class }
|
55
|
+
|
56
|
+
context "where the value is true" do
|
57
|
+
let(:method_signature_value) { described_class.new(true) }
|
58
|
+
it { expect(subject).to eq(VerifiedDouble::Boolean) }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "where the value is false" do
|
62
|
+
let(:method_signature_value) { described_class.new(false) }
|
63
|
+
it { expect(subject).to eq(VerifiedDouble::Boolean) }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "where the value is not true or false" do
|
67
|
+
let(:method_signature_value) { described_class.new(1) }
|
68
|
+
it "is the class of the value" do
|
69
|
+
expect(subject).to eq(Fixnum)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#recommended_value" do
|
75
|
+
subject { described_class.new(value) }
|
76
|
+
|
77
|
+
it "is a version of self that will be recommended to users to verify" do
|
78
|
+
expect(subject.recommended_value.value).to eq(subject.modified_class)
|
79
|
+
expect(subject.recommended_value.value).to_not eq(subject)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -2,10 +2,25 @@ require 'unit_helper'
|
|
2
2
|
require 'verified_double/output_unverified_signatures'
|
3
3
|
|
4
4
|
describe VerifiedDouble::OutputUnverifiedSignatures do
|
5
|
+
class Dummy
|
6
|
+
end
|
7
|
+
|
5
8
|
let(:get_unverified_signatures_service){
|
6
9
|
fire_double('VerifiedDouble::GetUnverifiedSignatures') }
|
7
10
|
|
8
|
-
let(:unverified_signatures){
|
11
|
+
let(:unverified_signatures){ [
|
12
|
+
VerifiedDouble::MethodSignature.new(
|
13
|
+
class_name: 'Dummy',
|
14
|
+
method_operator: '.',
|
15
|
+
method: 'find',
|
16
|
+
args: [VerifiedDouble::MethodSignatureValue.new(1)],
|
17
|
+
return_values: [VerifiedDouble::MethodSignatureValue.new(Dummy.new)]),
|
18
|
+
VerifiedDouble::MethodSignature.new(
|
19
|
+
class_name: 'Dummy',
|
20
|
+
method_operator: '.',
|
21
|
+
method: 'where',
|
22
|
+
args: [VerifiedDouble::MethodSignatureValue.new(id: 1)],
|
23
|
+
return_values: [VerifiedDouble::MethodSignatureValue.new(Dummy.new)]) ] }
|
9
24
|
|
10
25
|
subject { described_class.new(get_unverified_signatures_service) }
|
11
26
|
|
@@ -20,10 +35,15 @@ describe VerifiedDouble::OutputUnverifiedSignatures do
|
|
20
35
|
end
|
21
36
|
|
22
37
|
context "where there are unverified_signatures" do
|
23
|
-
it "should output the unverified_signatures" do
|
38
|
+
it "should output the recommended versions of the unverified_signatures" do
|
24
39
|
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
40
|
|
41
|
+
lines = [
|
42
|
+
"The following mocks are not verified:",
|
43
|
+
unverified_signatures[0].recommended_verified_signature,
|
44
|
+
unverified_signatures[1].recommended_verified_signature ]
|
45
|
+
|
46
|
+
subject.should_receive(:puts).with(lines.join("\n"))
|
27
47
|
subject.execute
|
28
48
|
end
|
29
49
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'unit_helper'
|
2
|
+
require 'verified_double/parse_method_signature'
|
3
|
+
|
4
|
+
describe VerifiedDouble::ParseMethodSignature do
|
5
|
+
subject { described_class.new(string) }
|
6
|
+
|
7
|
+
describe "#execute" do
|
8
|
+
let(:string){ "Class#method(:arg_1, :arg_2)=>:return_value" }
|
9
|
+
|
10
|
+
subject { described_class.new(string).execute }
|
11
|
+
|
12
|
+
it "returns a method signature from the signature string" do
|
13
|
+
expect(subject).to be_a(VerifiedDouble::MethodSignature)
|
14
|
+
expect(subject.class_name).to eq(subject.class_name)
|
15
|
+
expect(subject.method_operator).to eq(subject.method_operator)
|
16
|
+
expect(subject.method).to eq(subject.method)
|
17
|
+
expect(subject.args).to eq(subject.args)
|
18
|
+
expect(subject.return_values).to eq(subject.return_values)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#method_operator" do
|
23
|
+
context "for Class.method" do
|
24
|
+
let(:string){ "Class.method" }
|
25
|
+
it { expect(subject.method_operator).to eq('.') }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "for Class#method" do
|
29
|
+
let(:string){ "Class#method" }
|
30
|
+
it { expect(subject.method_operator).to eq('#') }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#class_name" do
|
35
|
+
context "for Class.method" do
|
36
|
+
let(:string){ "Class.method" }
|
37
|
+
it { expect(subject.class_name).to eq('Class') }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#method" do
|
42
|
+
context "for Class.method" do
|
43
|
+
let(:string){ "Class.method_1!?" }
|
44
|
+
it { expect(subject.method).to eq('method_1!?') }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "for Class.method(:arg_1, :arg_2)" do
|
48
|
+
let(:string){ "Class.method_1!?(:arg_1, :arg_2)" }
|
49
|
+
it { expect(subject.method).to eq('method_1!?') }
|
50
|
+
end
|
51
|
+
|
52
|
+
context "for Class.method=>return_value" do
|
53
|
+
let(:string){ "Class.method_1!?=>return_value" }
|
54
|
+
it { expect(subject.method).to eq('method_1!?') }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
describe "#args" do
|
60
|
+
context "for Class.method(:arg_1, :arg_2)" do
|
61
|
+
let(:string){ "Class.method(:arg_1, :arg_2)" }
|
62
|
+
|
63
|
+
it "builds method signature values from the evals of the args" do
|
64
|
+
expect(subject.args.map(&:value)).to eq([:arg_1, :arg_2])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "for Class.method" do
|
69
|
+
let(:string){ "Class.method" }
|
70
|
+
it { expect(subject.args).to eq([]) }
|
71
|
+
end
|
72
|
+
|
73
|
+
context "for Class.method=>:return_value" do
|
74
|
+
let(:string){ "Class.method=>:return_value" }
|
75
|
+
it { expect(subject.args).to eq([]) }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#return_values" do
|
80
|
+
context "for Class.method=>:return_value" do
|
81
|
+
let(:string){ "Class.method=>:return_value" }
|
82
|
+
it { expect(subject.return_values.map(&:value)).to eq([:return_value]) }
|
83
|
+
end
|
84
|
+
|
85
|
+
context "for Class.method" do
|
86
|
+
let(:string){ "Class.method" }
|
87
|
+
it { expect(subject.return_values).to be_empty }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "for Class.method(:arg_1, :arg_2)" do
|
91
|
+
let(:string){ "Class.method(:arg_1, :arg_2)" }
|
92
|
+
it { expect(subject.return_values).to be_empty }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -104,7 +104,7 @@ describe VerifiedDouble::RecordingDouble do
|
|
104
104
|
subject.should_receive(:to_s)
|
105
105
|
subject.should_receive(:inspect)
|
106
106
|
|
107
|
-
expect(subject.method_signatures.map(&:method)).to eq([
|
107
|
+
expect(subject.method_signatures.map(&:method)).to eq(['to_s', 'inspect'])
|
108
108
|
|
109
109
|
subject.to_s
|
110
110
|
subject.inspect
|
@@ -115,7 +115,8 @@ describe VerifiedDouble::RecordingDouble do
|
|
115
115
|
it "sets the args of the last method signature" do
|
116
116
|
subject.should_receive(:to_s).with(:arg_1, :arg_2)
|
117
117
|
|
118
|
-
expect(subject.method_signatures[0].args).to
|
118
|
+
expect(subject.method_signatures[0].args).to be_all{|arg| arg.is_a?(VerifiedDouble::MethodSignatureValue) }
|
119
|
+
expect(subject.method_signatures[0].args.map(&:value)).to eq([:arg_1, :arg_2])
|
119
120
|
|
120
121
|
subject.to_s(:arg_1, :arg_2)
|
121
122
|
end
|
@@ -125,7 +126,10 @@ describe VerifiedDouble::RecordingDouble do
|
|
125
126
|
it "sets the return value of the last method signature" do
|
126
127
|
subject.should_receive(:to_s).with(:arg_1, :arg_2).and_return(:return_value)
|
127
128
|
|
128
|
-
|
129
|
+
return_values = subject.method_signatures[0].return_values
|
130
|
+
expect(return_values).to have(1).return_value
|
131
|
+
expect(return_values.first).to be_a(VerifiedDouble::MethodSignatureValue)
|
132
|
+
expect(return_values.first.value).to eq(:return_value)
|
129
133
|
|
130
134
|
subject.to_s(:arg_1, :arg_2)
|
131
135
|
end
|
data/verified_double.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_runtime_dependency "rspec"
|
21
|
-
gem.add_runtime_dependency "rspec-fire"
|
21
|
+
gem.add_runtime_dependency "rspec-fire", '~> 1.1.3'
|
22
22
|
|
23
23
|
gem.add_development_dependency "aruba"
|
24
24
|
gem.add_development_dependency "cucumber"
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: verified_double
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- George Mendoza
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
type: :runtime
|
@@ -32,16 +32,16 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 1.1.3
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
|
-
- -
|
42
|
+
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
44
|
+
version: 1.1.3
|
45
45
|
name: rspec-fire
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
type: :development
|
@@ -116,20 +116,26 @@ extra_rdoc_files: []
|
|
116
116
|
files:
|
117
117
|
- .gitignore
|
118
118
|
- .travis.yml
|
119
|
+
- CHANGELOG.markdown
|
119
120
|
- Gemfile
|
120
121
|
- LICENSE.txt
|
121
122
|
- README.md
|
122
123
|
- Rakefile
|
124
|
+
- features/CHANGELOG.markdown
|
125
|
+
- features/customizing_arguments_and_return_values.feature
|
123
126
|
- features/readme.md
|
124
127
|
- features/step_definitions/verified_double_steps.rb
|
125
128
|
- features/support/requires.rb
|
126
129
|
- features/verified_double.feature
|
127
130
|
- lib/verified_double.rb
|
131
|
+
- lib/verified_double/boolean.rb
|
128
132
|
- lib/verified_double/get_registered_signatures.rb
|
129
133
|
- lib/verified_double/get_unverified_signatures.rb
|
130
134
|
- lib/verified_double/get_verified_signatures.rb
|
131
135
|
- lib/verified_double/method_signature.rb
|
136
|
+
- lib/verified_double/method_signature_value.rb
|
132
137
|
- lib/verified_double/output_unverified_signatures.rb
|
138
|
+
- lib/verified_double/parse_method_signature.rb
|
133
139
|
- lib/verified_double/recording_double.rb
|
134
140
|
- lib/verified_double/report_unverified_signatures.rb
|
135
141
|
- lib/verified_double/verify_doubles_service.rb
|
@@ -140,7 +146,9 @@ files:
|
|
140
146
|
- spec/verified_double/get_unverified_signatures_spec.rb
|
141
147
|
- spec/verified_double/get_verified_signatures_spec.rb
|
142
148
|
- spec/verified_double/method_signature_spec.rb
|
149
|
+
- spec/verified_double/method_signature_value_spec.rb
|
143
150
|
- spec/verified_double/output_unverified_signatures_spec.rb
|
151
|
+
- spec/verified_double/parse_method_signature_spec.rb
|
144
152
|
- spec/verified_double/recording_double_spec.rb
|
145
153
|
- spec/verified_double/report_unverified_signatures_spec.rb
|
146
154
|
- spec/verified_double/verify_doubles_service_spec.rb
|
@@ -172,6 +180,8 @@ specification_version: 3
|
|
172
180
|
summary: VerifiedDouble would record any mock made in the test suite. It would then
|
173
181
|
verify if the mock is valid by checking if there is a test against it.
|
174
182
|
test_files:
|
183
|
+
- features/CHANGELOG.markdown
|
184
|
+
- features/customizing_arguments_and_return_values.feature
|
175
185
|
- features/readme.md
|
176
186
|
- features/step_definitions/verified_double_steps.rb
|
177
187
|
- features/support/requires.rb
|
@@ -182,7 +192,9 @@ test_files:
|
|
182
192
|
- spec/verified_double/get_unverified_signatures_spec.rb
|
183
193
|
- spec/verified_double/get_verified_signatures_spec.rb
|
184
194
|
- spec/verified_double/method_signature_spec.rb
|
195
|
+
- spec/verified_double/method_signature_value_spec.rb
|
185
196
|
- spec/verified_double/output_unverified_signatures_spec.rb
|
197
|
+
- spec/verified_double/parse_method_signature_spec.rb
|
186
198
|
- spec/verified_double/recording_double_spec.rb
|
187
199
|
- spec/verified_double/report_unverified_signatures_spec.rb
|
188
200
|
- spec/verified_double/verify_doubles_service_spec.rb
|