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.
@@ -2,5 +2,5 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  script:
5
- - bundle exec rspec
5
+ - bundle exec rspec -r ./spec/spec_helper.rb
6
6
  - bundle exec cucumber
@@ -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
@@ -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
 
@@ -0,0 +1,4 @@
1
+ module VerifiedDouble
2
+ module Boolean
3
+ end
4
+ end
@@ -5,7 +5,7 @@ module VerifiedDouble
5
5
  end
6
6
 
7
7
  def execute
8
- @double_registry.map(&:method_signatures).flatten.map(&:to_s).uniq
8
+ @double_registry.map(&:method_signatures).flatten.uniq
9
9
  end
10
10
  end
11
11
  end
@@ -5,7 +5,9 @@ module VerifiedDouble
5
5
  end
6
6
 
7
7
  def execute
8
- @get_registered_signatures.execute - @get_verified_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
@@ -11,6 +11,7 @@ module VerifiedDouble
11
11
  .map{|example| example.metadata[:verifies_contract] }
12
12
  .compact
13
13
  .uniq
14
+ .map{|method_signature_string| ParseMethodSignature.new(method_signature_string).execute }
14
15
  end
15
16
  end
16
17
  end
@@ -1,16 +1,55 @@
1
1
  module VerifiedDouble
2
2
  class MethodSignature
3
- attr_accessor :args, :method, :recording_double, :return_value
3
+ attr_accessor :args, :class_name, :method, :method_operator, :return_values
4
4
 
5
- def initialize(recording_double)
6
- @recording_double = recording_double
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
- "#{recording_double.class_name}#{recording_double.method_operator}#{method}(#{args && args.map(&:class).join(', ')})",
12
- return_value && return_value.class]
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.return_value = return_value
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(self)
42
- method_signature.method = method
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 = 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
@@ -1,3 +1,3 @@
1
1
  module VerifiedDouble
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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
- fire_double('VerifiedDouble::MethodSignature', to_s: 'method_signature_1') }
6
+ VerifiedDouble::MethodSignature.new(class_name: 'Object', method_operator: '#', method: 'to_s') }
7
7
 
8
8
  let(:method_signature_2) {
9
- fire_double('VerifiedDouble::MethodSignature', to_s: 'method_signature_2') }
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(['method_signature_1', 'method_signature_2'])
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(['method_signature_1'])
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
- it "subtracts verified_signatures from registered_signatures" do
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([:verified_signature, :unverified_signature])
40
+ .and_return([registered_signature, registered_signature_without_match])
18
41
 
19
42
  get_verified_signatures_service
20
43
  .should_receive(:execute)
21
- .and_return([:verified_signature])
44
+ .at_least(:once)
45
+ .and_return([verified_signature])
22
46
 
23
- expect(subject.execute).to eq([:unverified_signature])
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
- expect(subject.execute).to eq([example_with_verified_contract_tag.metadata[:verifies_contract]])
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
- expect(subject.execute).to eq([example_with_verified_contract_tag.metadata[:verifies_contract]])
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
- describe "#to_s" do
6
- let(:recording_double) {
7
- fire_double('VerifiedDouble::RecordingDouble',
8
- class_name: 'Dummy',
9
- method_operator: '#') }
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(recording_double).tap {|method_signature|
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 args in the result" do
17
- subject.args = [1, {}]
18
- expect(subject.to_s).to eq("Dummy#do_something(Fixnum, Hash)")
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.return_value).to be_nil
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 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)")
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.return_value = true
39
- expect(subject.to_s).to eq("Dummy#do_something()=>TrueClass")
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.return_value).to be_nil
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){ %w(UNVERIFIED_SIGNATURES_1 UNVERIFIED_SIGNATURES_2) }
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([:to_s, :inspect])
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 eq([:arg_1, :arg_2])
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
- expect(subject.method_signatures[0].return_value).to eq(:return_value)
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
@@ -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.1
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-02 00:00:00.000000000 Z
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: '0'
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: '0'
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