rspec 0.5.3 → 0.5.4
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/CHANGES +57 -32
- data/EXAMPLES.rd +0 -0
- data/Rakefile +22 -21
- data/bin/spec +9 -11
- data/doc/README +1 -3
- data/doc/plugin/syntax.rb +27 -5
- data/doc/src/core_team.page +22 -0
- data/doc/src/default.css +11 -11
- data/doc/src/default.template +0 -1
- data/doc/src/documentation/index.page +183 -8
- data/doc/src/documentation/meta.info +7 -7
- data/doc/src/documentation/mocks.page +168 -109
- data/doc/src/documentation/underscores.page +20 -0
- data/doc/src/examples.page +2 -1
- data/doc/src/images/David_and_Aslak.jpg +0 -0
- data/doc/src/images/Whats_That_Dude.jpg +0 -0
- data/doc/src/index.page +70 -3
- data/doc/src/meta.info +18 -11
- data/doc/src/tools/index.page +40 -134
- data/doc/src/tools/meta.info +9 -3
- data/doc/src/tools/rails.page +3 -1
- data/doc/src/tools/rake.page +20 -3
- data/doc/src/tools/rcov.page +19 -0
- data/doc/src/tools/spec.page +99 -0
- data/doc/src/tools/test2rspec.page +2 -4
- data/doc/src/tutorials/index.page +52 -0
- data/doc/src/tutorials/meta.info +31 -0
- data/doc/src/tutorials/notes.txt +252 -0
- data/doc/src/tutorials/stack.rb +11 -0
- data/doc/src/tutorials/stack_01.page +224 -0
- data/doc/src/tutorials/stack_02.page +180 -0
- data/doc/src/tutorials/stack_03.page +291 -0
- data/doc/src/tutorials/stack_04.page +203 -0
- data/doc/src/tutorials/stack_04.page.orig +123 -0
- data/doc/src/tutorials/stack_05.page +90 -0
- data/doc/src/tutorials/stack_05.page.orig +124 -0
- data/doc/src/tutorials/stack_06.page +359 -0
- data/doc/src/tutorials/stack_06.page.orig +359 -0
- data/doc/src/tutorials/stack_spec.rb +41 -0
- data/examples/airport_spec.rb +4 -4
- data/examples/{spec_framework_spec.rb → bdd_framework_spec.rb} +6 -7
- data/examples/mocking_spec.rb +0 -5
- data/examples/stack_spec.rb +6 -7
- data/examples/sugar_spec.rb +14 -0
- data/lib/spec/api.rb +5 -2
- data/lib/spec/api/helper/should_base.rb +17 -22
- data/lib/spec/api/helper/should_helper.rb +4 -3
- data/lib/spec/api/helper/should_negator.rb +3 -2
- data/lib/spec/api/mocks/argument_expectation.rb +104 -0
- data/lib/spec/api/{mock.rb → mocks/message_expectation.rb} +47 -96
- data/lib/spec/api/mocks/mock.rb +63 -0
- data/lib/spec/api/mocks/order_group.rb +21 -0
- data/lib/spec/api/sugar.rb +47 -0
- data/lib/spec/rake/rcov_verify.rb +45 -0
- data/lib/spec/rake/spectask.rb +41 -56
- data/lib/spec/runner.rb +4 -1
- data/lib/spec/runner/backtrace_tweaker.rb +24 -3
- data/lib/spec/runner/base_text_formatter.rb +28 -0
- data/lib/spec/runner/context.rb +21 -18
- data/lib/spec/runner/context_runner.rb +20 -31
- data/lib/spec/runner/execution_context.rb +3 -3
- data/lib/spec/runner/kernel_ext.rb +10 -1
- data/lib/spec/runner/option_parser.rb +32 -14
- data/lib/spec/runner/progress_bar_formatter.rb +21 -0
- data/lib/spec/runner/rdoc_formatter.rb +15 -5
- data/lib/spec/runner/reporter.rb +100 -0
- data/lib/spec/runner/specdoc_formatter.rb +20 -0
- data/lib/spec/runner/specification.rb +42 -22
- data/lib/spec/version.rb +1 -1
- data/test/rcov/rcov_testtask.rb +1 -0
- data/test/spec/api/duck_type_test.rb +4 -4
- data/test/spec/api/helper/raising_test.rb +37 -17
- data/test/spec/api/{mock_arg_constraints_test.rb → mocks/mock_arg_constraints_test.rb} +10 -4
- data/test/spec/api/mocks/mock_ordering_test.rb +62 -0
- data/test/spec/api/{mock_test.rb → mocks/mock_test.rb} +30 -7
- data/test/spec/api/mocks/null_object_test.rb +31 -0
- data/test/spec/api/sugar_test.rb +71 -0
- data/test/spec/runner/backtrace_tweaker_test.rb +52 -4
- data/test/spec/runner/context_runner_test.rb +41 -21
- data/test/spec/runner/context_test.rb +60 -32
- data/test/spec/runner/execution_context_test.rb +4 -3
- data/test/spec/runner/failure_dump_test.rb +92 -0
- data/test/spec/runner/kernel_ext_test.rb +1 -2
- data/test/spec/runner/option_parser_test.rb +48 -28
- data/test/spec/runner/progress_bar_formatter_test.rb +48 -0
- data/test/spec/runner/rdoc_formatter_test.rb +31 -4
- data/test/spec/runner/reporter_test.rb +103 -0
- data/test/spec/runner/specdoc_formatter_test.rb +50 -0
- data/test/spec/runner/specification_test.rb +49 -11
- data/test/test_helper.rb +1 -4
- metadata +46 -15
- data/doc/src/community.page +0 -7
- data/doc/src/documentation/api.page +0 -185
- data/doc/src/why_rspec.page +0 -7
- data/examples/empty_stack_spec.rb +0 -22
- data/examples/team_spec.rb +0 -30
- data/lib/spec/api/duck_type.rb +0 -16
- data/lib/spec/runner/simple_text_reporter.rb +0 -88
- data/test/rcov/rcov_verify.rb +0 -28
- data/test/spec/runner/simple_text_reporter_test.rb +0 -123
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'stack'
|
2
|
+
|
3
|
+
context "A new stack" do
|
4
|
+
setup do
|
5
|
+
@stack = Stack.new
|
6
|
+
end
|
7
|
+
|
8
|
+
specify "should be empty" do
|
9
|
+
@stack.should_be_empty
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "An empty stack" do
|
14
|
+
setup do
|
15
|
+
@stack = Stack.new
|
16
|
+
end
|
17
|
+
|
18
|
+
specify "should keep its mouth shut when you send it 'push'" do
|
19
|
+
lambda { @stack.push Object.new }.should.not.raise
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "A stack with one item" do
|
24
|
+
setup do
|
25
|
+
@stack = Stack.new
|
26
|
+
@stack.push "one item"
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "should not be empty" do
|
30
|
+
@stack.should_not_be_empty
|
31
|
+
end
|
32
|
+
|
33
|
+
specify "should return top when you send it 'top'" do
|
34
|
+
@stack.top.should_equal "one item"
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should not be empty after 'top'" do
|
38
|
+
@stack.top
|
39
|
+
@stack.should_not_be_empty
|
40
|
+
end
|
41
|
+
end
|
data/examples/airport_spec.rb
CHANGED
@@ -6,7 +6,7 @@ class Airport
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def need?(thing)
|
9
|
-
|
9
|
+
false unless [:cables, :electricity].include? thing
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -25,16 +25,16 @@ topic "Airport at home" do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
fact "should always work" do
|
28
|
-
@airport.
|
28
|
+
@airport.should_be_working
|
29
29
|
end
|
30
30
|
|
31
31
|
must "not need cables" do
|
32
|
-
@airport.
|
32
|
+
@airport.should_not_need :cables
|
33
33
|
end
|
34
34
|
|
35
35
|
must "not need electricity" do
|
36
36
|
# This will fail...
|
37
|
-
@airport.
|
37
|
+
@airport.should_not_need :electricity
|
38
38
|
end
|
39
39
|
|
40
40
|
teardown do
|
@@ -1,28 +1,27 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../lib/spec'
|
2
2
|
|
3
|
-
class
|
3
|
+
class BddFramework
|
4
4
|
def intuitive?
|
5
5
|
true
|
6
6
|
end
|
7
7
|
|
8
8
|
def adopted_quickly?
|
9
|
-
|
9
|
+
true
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
context "
|
13
|
+
context "BDD framework" do
|
14
14
|
|
15
15
|
setup do
|
16
|
-
@
|
16
|
+
@bdd_framework = BddFramework.new
|
17
17
|
end
|
18
18
|
|
19
19
|
specify "should be adopted quickly" do
|
20
|
-
|
21
|
-
@spec_framework.should.be.adopted_quickly
|
20
|
+
@bdd_framework.should_be_adopted_quickly
|
22
21
|
end
|
23
22
|
|
24
23
|
specify "should be intuitive" do
|
25
|
-
@
|
24
|
+
@bdd_framework.should_be_intuitive
|
26
25
|
end
|
27
26
|
|
28
27
|
end
|
data/examples/mocking_spec.rb
CHANGED
data/examples/stack_spec.rb
CHANGED
@@ -8,11 +8,11 @@ context "An empty stack" do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
specify "should accept an item when sent push" do
|
11
|
-
lambda { @stack.push Object.new }.
|
11
|
+
lambda { @stack.push Object.new }.should_not_raise
|
12
12
|
end
|
13
13
|
|
14
14
|
specify "should complain when sent top" do
|
15
|
-
lambda { @stack.top }.
|
15
|
+
lambda { @stack.top }.should_raise StackUnderflowError
|
16
16
|
end
|
17
17
|
|
18
18
|
specify "should complain when sent pop" do
|
@@ -21,7 +21,8 @@ context "An empty stack" do
|
|
21
21
|
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
context "A stack with one item" do
|
25
|
+
|
25
26
|
setup do
|
26
27
|
@stack = Stack.new
|
27
28
|
@stack.push 3
|
@@ -52,6 +53,7 @@ end
|
|
52
53
|
end
|
53
54
|
|
54
55
|
context "An almost full stack (with one item less than capacity)" do
|
56
|
+
|
55
57
|
setup do
|
56
58
|
@stack = Stack.new
|
57
59
|
(1..9).each { |i| @stack.push i }
|
@@ -110,7 +112,4 @@ context "A full stack" do
|
|
110
112
|
@stack.pop.should.be 9
|
111
113
|
end
|
112
114
|
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/spec'
|
2
|
+
|
3
|
+
context "Underscore sugar" do
|
4
|
+
specify "should be available for regular objects" do
|
5
|
+
1.should_equal 1
|
6
|
+
lambda { 1.should_not_equal 1 }.should_raise
|
7
|
+
end
|
8
|
+
|
9
|
+
specify "should be available for mocks" do
|
10
|
+
sweetened = mock "sweetened"
|
11
|
+
sweetened.should_receive :salt
|
12
|
+
sweetened.salt
|
13
|
+
end
|
14
|
+
end
|
data/lib/spec/api.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'spec/api/exceptions'
|
2
|
-
require 'spec/api/
|
3
|
-
require 'spec/api/
|
2
|
+
require 'spec/api/mocks/argument_expectation'
|
3
|
+
require 'spec/api/mocks/order_group'
|
4
|
+
require 'spec/api/mocks/message_expectation'
|
5
|
+
require 'spec/api/mocks/mock'
|
4
6
|
require 'spec/api/expectations'
|
5
7
|
require 'spec/api/helper'
|
8
|
+
require 'spec/api/sugar'
|
@@ -1,38 +1,33 @@
|
|
1
|
+
class TrueClass; def inspect_for_expectation_not_met_error; "<true>" end end
|
2
|
+
class FalseClass; def inspect_for_expectation_not_met_error; "<false>" end end
|
3
|
+
class NilClass; def inspect_for_expectation_not_met_error; "nil" end end
|
4
|
+
class Class; def inspect_for_expectation_not_met_error; "<#{name}>" end end
|
5
|
+
class Proc; def inspect_for_expectation_not_met_error; "<Proc>" end end
|
6
|
+
class Array; def inspect_for_expectation_not_met_error; "#{inspect}" end end
|
7
|
+
class String; def inspect_for_expectation_not_met_error; "#{inspect}" end end
|
8
|
+
class Object
|
9
|
+
def inspect_for_expectation_not_met_error
|
10
|
+
return "#{self.class} #{inspect}" if inspect.include? "<"
|
11
|
+
return "#{self.class} <#{inspect}>" unless inspect.include? "<"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
1
15
|
module Spec
|
2
16
|
|
3
17
|
class ShouldBase
|
4
18
|
|
5
19
|
def default_message(expectation, expected=:no_expectation_specified)
|
6
|
-
message =
|
7
|
-
message += " #{expectation}"
|
20
|
+
message = "#{@target.inspect_for_expectation_not_met_error} #{expectation}"
|
8
21
|
if (expected != :no_expectation_specified)
|
9
|
-
message
|
22
|
+
message << " " << expected.inspect_for_expectation_not_met_error
|
10
23
|
end
|
11
24
|
message
|
12
25
|
end
|
13
|
-
|
14
|
-
def wrap(obj)
|
15
|
-
if obj == true
|
16
|
-
"<true>"
|
17
|
-
elsif obj == false
|
18
|
-
"<false>"
|
19
|
-
elsif obj.nil?
|
20
|
-
"nil"
|
21
|
-
elsif obj.kind_of? Proc
|
22
|
-
"<Proc>"
|
23
|
-
elsif (obj.kind_of? Array) || (obj.kind_of? String)
|
24
|
-
"#{obj.inspect}"
|
25
|
-
elsif obj.inspect.include? "<"
|
26
|
-
"#{obj.class} #{obj.inspect}"
|
27
|
-
else
|
28
|
-
"#{obj.class} <#{obj.inspect}>"
|
29
|
-
end
|
30
|
-
end
|
31
26
|
|
32
27
|
def fail_with_message(message)
|
33
28
|
Kernel::raise(Spec::Api::ExpectationNotMetError.new(message))
|
34
29
|
end
|
35
|
-
|
30
|
+
|
36
31
|
end
|
37
32
|
|
38
33
|
end
|
@@ -64,11 +64,12 @@ module Spec
|
|
64
64
|
def raise(exception=Exception)
|
65
65
|
begin
|
66
66
|
@target.call
|
67
|
-
fail_with_message(default_message("should raise", exception.inspect))
|
68
67
|
rescue exception
|
69
|
-
|
70
|
-
|
68
|
+
return
|
69
|
+
rescue => e
|
70
|
+
fail_with_message("#{default_message("should raise", exception)} but raised #{e.inspect}")
|
71
71
|
end
|
72
|
+
fail_with_message("#{default_message("should raise", exception)} but raised nothing")
|
72
73
|
end
|
73
74
|
|
74
75
|
def throw(symbol)
|
@@ -48,8 +48,9 @@ module Spec
|
|
48
48
|
def raise(exception=Exception)
|
49
49
|
begin
|
50
50
|
@target.call
|
51
|
-
rescue exception
|
52
|
-
fail_with_message(default_message("should not raise", exception
|
51
|
+
rescue exception => e
|
52
|
+
fail_with_message("#{default_message("should not raise", exception)}") if e.instance_of? exception
|
53
|
+
fail_with_message("#{default_message("should not raise", exception)} but raised #{e.inspect}") unless e.instance_of? exception
|
53
54
|
rescue
|
54
55
|
true
|
55
56
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Spec
|
2
|
+
module Api
|
3
|
+
|
4
|
+
class LiteralArgConstraint
|
5
|
+
def initialize(literal)
|
6
|
+
@literal_value = literal
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(value)
|
10
|
+
@literal_value == value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class AnyArgConstraint
|
15
|
+
def initialize(ignore)
|
16
|
+
end
|
17
|
+
|
18
|
+
def matches?(value)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NumericArgConstraint
|
24
|
+
def initialize(ignore)
|
25
|
+
end
|
26
|
+
|
27
|
+
def matches?(value)
|
28
|
+
value.is_a?(Numeric)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class BooleanArgConstraint
|
33
|
+
def initialize(ignore)
|
34
|
+
end
|
35
|
+
|
36
|
+
def matches?(value)
|
37
|
+
return true if value.is_a?(TrueClass)
|
38
|
+
return true if value.is_a?(FalseClass)
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class StringArgConstraint
|
44
|
+
def initialize(ignore)
|
45
|
+
end
|
46
|
+
|
47
|
+
def matches?(value)
|
48
|
+
value.is_a?(String)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class DuckTypeArgConstraint
|
53
|
+
def initialize(*methods_to_respond_do)
|
54
|
+
@methods_to_respond_do = methods_to_respond_do
|
55
|
+
end
|
56
|
+
|
57
|
+
def matches?(value)
|
58
|
+
@methods_to_respond_do.all? { |sym| value.respond_to?(sym) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class ArgumentExpectation
|
63
|
+
|
64
|
+
@@constraint_classes = Hash.new { |hash, key| LiteralArgConstraint}
|
65
|
+
@@constraint_classes[:anything] = AnyArgConstraint
|
66
|
+
@@constraint_classes[:numeric] = NumericArgConstraint
|
67
|
+
@@constraint_classes[:boolean] = BooleanArgConstraint
|
68
|
+
@@constraint_classes[:string] = StringArgConstraint
|
69
|
+
|
70
|
+
def initialize(args)
|
71
|
+
if args == [:any_args] then @expected_params = nil
|
72
|
+
elsif args == [:no_args] then @expected_params = []
|
73
|
+
else @expected_params = process_arg_constraints(args)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def process_arg_constraints(constraints)
|
78
|
+
constraints.collect do |constraint|
|
79
|
+
convert_constraint(constraint)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def convert_constraint(constraint)
|
84
|
+
return @@constraint_classes[constraint].new(constraint) if constraint.is_a?(Symbol)
|
85
|
+
return constraint if constraint.is_a?(DuckTypeArgConstraint)
|
86
|
+
return LiteralArgConstraint.new(constraint)
|
87
|
+
end
|
88
|
+
|
89
|
+
def check_args(args)
|
90
|
+
return true if @expected_params.nil?
|
91
|
+
return true if @expected_params == args
|
92
|
+
return constraints_match?(args)
|
93
|
+
end
|
94
|
+
|
95
|
+
def constraints_match?(args)
|
96
|
+
return false if args.length != @expected_params.length
|
97
|
+
@expected_params.each_index { |i| return false unless @expected_params[i].matches?(args[i]) }
|
98
|
+
return true
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -1,65 +1,10 @@
|
|
1
1
|
module Spec
|
2
2
|
module Api
|
3
|
-
class Mock
|
4
|
-
|
5
|
-
DEFAULT_OPTIONS = {
|
6
|
-
:null_object => false
|
7
|
-
}
|
8
|
-
# Creates a new mock with a +name+ (that will be used in error messages only)
|
9
|
-
# Options:
|
10
|
-
# * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it.
|
11
|
-
def initialize(name, options={})
|
12
|
-
@name = name
|
13
|
-
@options = DEFAULT_OPTIONS.dup.merge(options)
|
14
|
-
@expectations = []
|
15
|
-
end
|
16
|
-
|
17
|
-
def should
|
18
|
-
self
|
19
|
-
end
|
20
|
-
|
21
|
-
def receive(sym, &block)
|
22
|
-
expected_from = caller(1)[0]
|
23
|
-
expectation = MessageExpectation.new(@name, expected_from, sym, block_given? ? block : nil)
|
24
|
-
@expectations << expectation
|
25
|
-
expectation
|
26
|
-
end
|
27
|
-
|
28
|
-
def __verify
|
29
|
-
@expectations.each do |expectation|
|
30
|
-
expectation.verify_messages_received
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def method_missing(sym, *args, &block)
|
35
|
-
# TODO: use find_expectation(sym, args) which will lookup based on sym, args and strict mode.
|
36
|
-
if expectation = find_matching_expectation(sym, *args)
|
37
|
-
expectation.verify_message(args, block)
|
38
|
-
else
|
39
|
-
begin
|
40
|
-
# act as null object if method is missing and we ignore them. return value too!
|
41
|
-
@options[:null_object] ? self : super(sym, *args, &block)
|
42
|
-
rescue NoMethodError
|
43
|
-
|
44
|
-
arg_message = args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", ")
|
45
|
-
|
46
|
-
Kernel::raise Spec::Api::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with [#{arg_message}]"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def find_matching_expectation(sym, *args)
|
54
|
-
expectation = @expectations.find {|expectation| expectation.matches(sym, args)}
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
3
|
|
59
4
|
# Represents the expection of the reception of a message
|
60
5
|
class MessageExpectation
|
61
|
-
|
62
|
-
def initialize(mock_name, expected_from, sym, block)
|
6
|
+
|
7
|
+
def initialize(mock_name, expectation_ordering, expected_from, sym, block)
|
63
8
|
@mock_name = mock_name
|
64
9
|
@expected_from = expected_from
|
65
10
|
@sym = sym
|
@@ -67,33 +12,21 @@ module Spec
|
|
67
12
|
@block = proc {}
|
68
13
|
@received_count = 0
|
69
14
|
@expected_received_count = 1
|
70
|
-
@
|
15
|
+
@args_expectation = ArgumentExpectation.new([:any_args])
|
71
16
|
@consecutive = false
|
72
17
|
@exception_to_raise = nil
|
73
18
|
@symbol_to_throw = nil
|
74
19
|
@any_seen = false
|
75
20
|
@at_seen = false
|
76
21
|
@and_seen = false
|
22
|
+
@ordering = expectation_ordering
|
23
|
+
@ordered = false
|
77
24
|
end
|
78
25
|
|
79
26
|
def matches(sym, args)
|
80
|
-
@sym == sym and
|
81
|
-
end
|
82
|
-
|
83
|
-
def constraints_match?(args)
|
84
|
-
return true if @expected_params.length == 1 and @expected_params[0] == :any_args
|
85
|
-
return false if args.length != @expected_params.length
|
86
|
-
@expected_params.each_index do |i|
|
87
|
-
next if @expected_params[i] == :anything
|
88
|
-
next if @expected_params[i] == :numeric and args[i].is_a?Numeric
|
89
|
-
next if @expected_params[i] == :boolean and args[i].is_a?TrueClass or args[i].is_a?FalseClass
|
90
|
-
next if @expected_params[i] == :string and args[i].is_a?String
|
91
|
-
next if @expected_params[i].is_a? DuckType and @expected_params[i].walks_like? args[i]
|
92
|
-
return false unless args[i] == @expected_params[i]
|
93
|
-
end
|
94
|
-
return true
|
27
|
+
@sym == sym and @args_expectation.check_args(args)
|
95
28
|
end
|
96
|
-
|
29
|
+
|
97
30
|
def make_count_message(count)
|
98
31
|
return "at least #{pretty_print(count.abs)}" if count < 0
|
99
32
|
return pretty_print(count) if count > 0
|
@@ -105,53 +38,63 @@ module Spec
|
|
105
38
|
return "twice" if count == 2
|
106
39
|
return "#{count} times"
|
107
40
|
end
|
108
|
-
|
41
|
+
|
109
42
|
# This method is called at the end of a spec, after teardown.
|
110
43
|
def verify_messages_received
|
111
44
|
# TODO: this doesn't provide good enough error messages to fix the error.
|
112
45
|
# Error msg should tell exactly what went wrong. (AH).
|
113
|
-
|
46
|
+
|
114
47
|
return if @expected_received_count == :any
|
115
48
|
return if (@expected_received_count < 0) && (@received_count >= @expected_received_count.abs)
|
116
49
|
return if @expected_received_count == @received_count
|
117
50
|
|
118
|
-
expected_signature = nil
|
119
|
-
if @expected_params.nil?
|
120
|
-
expected_signature = @sym
|
121
|
-
else
|
122
|
-
params = @expected_params.collect{|param| "<#{param}:#{param.class.name}>"}.join(", ")
|
123
|
-
expected_signature = "#{@sym}(#{params})"
|
124
|
-
end
|
125
|
-
|
126
51
|
count_message = make_count_message(@expected_received_count)
|
127
52
|
|
128
|
-
message = "Mock '#{@mock_name}' expected #{
|
53
|
+
message = "Mock '#{@mock_name}' expected '#{@sym}' #{count_message}, but received it #{@received_count} times"
|
129
54
|
begin
|
130
|
-
Kernel::raise
|
55
|
+
Kernel::raise(Spec::Api::MockExpectationError, message)
|
131
56
|
rescue => error
|
132
57
|
error.backtrace.insert(0, @expected_from)
|
133
58
|
Kernel::raise error
|
134
59
|
end
|
135
60
|
end
|
136
61
|
|
62
|
+
def handle_order_constraint
|
63
|
+
return unless @ordered
|
64
|
+
return @ordering.consume(@self) if @ordering.ready_for?(self)
|
65
|
+
message = "Mock '#{@mock_name}' received '#{@sym}' out of order"
|
66
|
+
Kernel::raise(Spec::Api::MockExpectationError, message)
|
67
|
+
end
|
68
|
+
|
137
69
|
# This method is called when a method is invoked on a mock
|
138
70
|
def verify_message(args, block)
|
71
|
+
|
72
|
+
handle_order_constraint
|
73
|
+
|
139
74
|
unless @method_block.nil?
|
140
75
|
begin
|
141
76
|
result = @method_block.call(*args)
|
142
77
|
rescue Spec::Api::ExpectationNotMetError => detail
|
143
|
-
Kernel::raise Spec::Api::MockExpectationError, "Call expectation violated with: " +
|
78
|
+
Kernel::raise Spec::Api::MockExpectationError, "Call expectation violated with: " + detail
|
144
79
|
end
|
145
80
|
@received_count += 1
|
146
81
|
return result
|
147
82
|
end
|
148
83
|
|
149
|
-
args << block unless block.nil?
|
150
|
-
@received_count += 1
|
151
|
-
|
152
84
|
Kernel::raise @exception_to_raise.new unless @exception_to_raise.nil?
|
153
85
|
Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil?
|
154
|
-
|
86
|
+
unless @args_to_yield.nil?
|
87
|
+
if block.nil?
|
88
|
+
Kernel::raise Spec::Api::MockExpectationError, "Expected block to be passed"
|
89
|
+
end
|
90
|
+
if @args_to_yield.length != block.arity
|
91
|
+
Kernel::raise Spec::Api::MockExpectationError, "Wrong arity of passed block. Expected #{@args_to_yield.size}"
|
92
|
+
end
|
93
|
+
block.call @args_to_yield
|
94
|
+
end
|
95
|
+
|
96
|
+
args << block unless block.nil?
|
97
|
+
@received_count += 1
|
155
98
|
value = @block.call(*args)
|
156
99
|
|
157
100
|
return value unless @consecutive
|
@@ -160,11 +103,7 @@ module Spec
|
|
160
103
|
end
|
161
104
|
|
162
105
|
def with(*args)
|
163
|
-
|
164
|
-
elsif args == [:no_args] then @expected_params = []
|
165
|
-
else @expected_params = args
|
166
|
-
end
|
167
|
-
|
106
|
+
@args_expectation = ArgumentExpectation.new(args)
|
168
107
|
self
|
169
108
|
end
|
170
109
|
|
@@ -249,6 +188,18 @@ module Spec
|
|
249
188
|
@and_seen = false
|
250
189
|
@symbol_to_throw = symbol
|
251
190
|
end
|
191
|
+
|
192
|
+
def ordered
|
193
|
+
@ordering.register(self)
|
194
|
+
@ordered = true
|
195
|
+
self
|
196
|
+
end
|
197
|
+
|
198
|
+
def yield(*args)
|
199
|
+
return self unless @and_seen
|
200
|
+
@and_seen = false
|
201
|
+
@args_to_yield = args
|
202
|
+
end
|
252
203
|
|
253
204
|
end
|
254
205
|
end
|