rr 0.1.6 → 0.1.7
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 +7 -0
- data/Rakefile +1 -1
- data/examples/environment_fixture_setup.rb +1 -1
- data/examples/example_helper.rb +1 -0
- data/examples/high_level_example.rb +1 -2
- data/examples/rr/do_not_allow_creator_example.rb +1 -2
- data/examples/rr/double_bind_example.rb +1 -2
- data/examples/rr/double_dispatching_example.rb +2 -3
- data/examples/rr/double_example.rb +1 -2
- data/examples/rr/double_register_scenario_example.rb +1 -2
- data/examples/rr/double_reset_example.rb +1 -2
- data/examples/rr/double_verify_example.rb +1 -2
- data/examples/rr/errors/rr_error_example.rb +1 -2
- data/examples/rr/expectations/any_argument_expectation_example.rb +1 -2
- data/examples/rr/expectations/anything_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/boolean_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/duck_type_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/is_a_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/numeric_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/range_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/regexp_argument_equality_expectation_example.rb +1 -2
- data/examples/rr/expectations/times_called_expectation/times_called_expectation_at_least_example.rb +74 -0
- data/examples/rr/expectations/times_called_expectation/times_called_expectation_at_most_example.rb +69 -0
- data/examples/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +18 -0
- data/examples/rr/expectations/times_called_expectation/times_called_expectation_integer_example.rb +102 -0
- data/examples/rr/expectations/times_called_expectation/times_called_expectation_proc_example.rb +80 -0
- data/examples/rr/expectations/times_called_expectation/times_called_expectation_range_example.rb +81 -0
- data/examples/rr/expectations/times_called_expectation_example.rb +1 -185
- data/examples/rr/extensions/double_methods_example.rb +3 -4
- data/examples/rr/mock_creator_example.rb +1 -2
- data/examples/rr/probe_creator_example.rb +1 -2
- data/examples/rr/rspec/rspec_adapter_example.rb +1 -2
- data/examples/rr/rspec/rspec_backtrace_tweaking_example.rb +1 -2
- data/examples/rr/rspec/rspec_usage_example.rb +1 -2
- data/examples/rr/scenario_example.rb +60 -15
- data/examples/rr/space_create_example.rb +1 -2
- data/examples/rr/space_example.rb +1 -2
- data/examples/rr/space_register_example.rb +1 -2
- data/examples/rr/space_reset_example.rb +51 -4
- data/examples/rr/space_verify_example.rb +4 -5
- data/examples/rr/stub_creator_example.rb +1 -2
- data/examples/rr/test_unit/test_helper.rb +1 -1
- data/examples/rr/times_called_matchers/at_least_matcher_example.rb +74 -0
- data/examples/rr/times_called_matchers/at_most_matcher_example.rb +82 -0
- data/examples/rr/times_called_matchers/integer_matcher_example.rb +88 -0
- data/examples/rr/times_called_matchers/proc_matcher_example.rb +74 -0
- data/examples/rr/times_called_matchers/range_matcher_example.rb +94 -0
- data/examples/rr/times_called_matchers/times_called_matcher_example.rb +53 -0
- data/lib/rr.rb +15 -7
- data/lib/rr/adapters/rspec.rb +2 -2
- data/lib/rr/adapters/test_unit.rb +1 -1
- data/lib/rr/double.rb +2 -2
- data/lib/rr/expectations/times_called_expectation.rb +14 -13
- data/lib/rr/extensions/double_methods.rb +5 -5
- data/lib/rr/scenario.rb +35 -7
- data/lib/rr/space.rb +20 -8
- data/lib/rr/times_called_matchers/at_least_matcher.rb +22 -0
- data/lib/rr/times_called_matchers/at_most_matcher.rb +22 -0
- data/lib/rr/times_called_matchers/integer_matcher.rb +17 -0
- data/lib/rr/times_called_matchers/proc_matcher.rb +17 -0
- data/lib/rr/times_called_matchers/range_matcher.rb +19 -0
- data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
- data/lib/rr/wildcard_matchers/anything.rb +13 -0
- data/lib/rr/wildcard_matchers/boolean.rb +18 -0
- data/lib/rr/wildcard_matchers/duck_type.rb +24 -0
- data/lib/rr/wildcard_matchers/is_a.rb +20 -0
- data/lib/rr/wildcard_matchers/numeric.rb +9 -0
- data/lib/rr/{expectations/wildcard_matchers → wildcard_matchers}/range.rb +0 -0
- data/lib/rr/{expectations/wildcard_matchers → wildcard_matchers}/regexp.rb +0 -0
- metadata +27 -9
- data/lib/rr/expectations/wildcard_matchers/anything.rb +0 -15
- data/lib/rr/expectations/wildcard_matchers/boolean.rb +0 -20
- data/lib/rr/expectations/wildcard_matchers/duck_type.rb +0 -26
- data/lib/rr/expectations/wildcard_matchers/is_a.rb +0 -22
- data/lib/rr/expectations/wildcard_matchers/numeric.rb +0 -11
@@ -0,0 +1,94 @@
|
|
1
|
+
require "examples/example_helper"
|
2
|
+
|
3
|
+
module RR
|
4
|
+
module TimesCalledMatchers
|
5
|
+
describe TimesCalledMatcher, ".create when passed a IntegerMatcher" do
|
6
|
+
it "returns the passed in argument" do
|
7
|
+
matcher = RangeMatcher.new(2..4)
|
8
|
+
TimesCalledMatcher.create(matcher).should === matcher
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe TimesCalledMatcher, ".create when passed a Integer" do
|
13
|
+
it "returns RangeMatcher" do
|
14
|
+
TimesCalledMatcher.create(2..4).should == RangeMatcher.new(2..4)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe RangeMatcher, "#possible_match?" do
|
19
|
+
before do
|
20
|
+
@times = 2..4
|
21
|
+
@matcher = RangeMatcher.new(@times)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns true when times called < start of range" do
|
25
|
+
@matcher.should be_possible_match(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns true when times called in range" do
|
29
|
+
@matcher.should be_possible_match(2)
|
30
|
+
@matcher.should be_possible_match(3)
|
31
|
+
@matcher.should be_possible_match(4)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns false when times called > end of range" do
|
35
|
+
@matcher.should_not be_possible_match(5)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe RangeMatcher, "#matches?" do
|
40
|
+
before do
|
41
|
+
@times = 2..4
|
42
|
+
@matcher = RangeMatcher.new(@times)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns false when times_called less than start of range" do
|
46
|
+
@matcher.should_not be_matches(1)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns true when times_called in range" do
|
50
|
+
@matcher.should be_matches(2)
|
51
|
+
@matcher.should be_matches(3)
|
52
|
+
@matcher.should be_matches(4)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns false when times_called > end of range" do
|
56
|
+
@matcher.should_not be_matches(5)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe RangeMatcher, "#attempt?" do
|
61
|
+
before do
|
62
|
+
@times = 2..4
|
63
|
+
@matcher = RangeMatcher.new(@times)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns true when less than start of range" do
|
67
|
+
@matcher.should be_attempt(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns true when in range" do
|
71
|
+
@matcher.should be_attempt(2)
|
72
|
+
@matcher.should be_attempt(3)
|
73
|
+
@matcher.should be_attempt(4)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns false when > end of range" do
|
77
|
+
@matcher.should_not be_attempt(5)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe RangeMatcher, "#error_message" do
|
82
|
+
before do
|
83
|
+
@times = 2..4
|
84
|
+
@matcher = RangeMatcher.new(@times)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "has an error message" do
|
88
|
+
@matcher.error_message(1).should == (
|
89
|
+
"Called 1 time. Expected 2..4 times."
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "examples/example_helper"
|
2
|
+
|
3
|
+
module RR
|
4
|
+
module TimesCalledMatchers
|
5
|
+
describe TimesCalledMatcher, ".create when passed a TimesCalledMatcher" do
|
6
|
+
it "returns the passed in argument" do
|
7
|
+
matcher = TimesCalledMatcher.new(5)
|
8
|
+
TimesCalledMatcher.create(matcher).should === matcher
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe TimesCalledMatcher, ".create when passed an unsupported type" do
|
13
|
+
it "raises an ArgumentError" do
|
14
|
+
matcher = Object.new
|
15
|
+
proc do
|
16
|
+
TimesCalledMatcher.create(matcher)
|
17
|
+
end.should raise_error(ArgumentError, "There is no TimesCalledMatcher for #{matcher.inspect}.")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe TimesCalledMatcher, "#error_message" do
|
22
|
+
before do
|
23
|
+
@times = 3
|
24
|
+
@matcher = TimesCalledMatcher.new(@times)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has an error message" do
|
28
|
+
@matcher.error_message(5).should == (
|
29
|
+
"Called 5 times. Expected 3 times."
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe TimesCalledMatcher, "#==" do
|
35
|
+
before do
|
36
|
+
@times = 3
|
37
|
+
@matcher = TimesCalledMatcher.new(@times)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns true when other is the same class and times are ==" do
|
41
|
+
@matcher.should == TimesCalledMatcher.new(@times)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns false when other is a different class and times are ==" do
|
45
|
+
@matcher.should_not == IntegerMatcher.new(@times)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns false when is the same class and times are not ==" do
|
49
|
+
@matcher.should_not == TimesCalledMatcher.new(1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/rr.rb
CHANGED
@@ -19,12 +19,20 @@ require "rr/errors/times_called_error"
|
|
19
19
|
require "rr/expectations/argument_equality_expectation"
|
20
20
|
require "rr/expectations/any_argument_expectation"
|
21
21
|
require "rr/expectations/times_called_expectation"
|
22
|
-
|
23
|
-
require "rr/
|
24
|
-
require "rr/
|
25
|
-
require "rr/
|
26
|
-
require "rr/
|
27
|
-
require "rr/
|
28
|
-
require "rr/
|
22
|
+
|
23
|
+
require "rr/wildcard_matchers/anything"
|
24
|
+
require "rr/wildcard_matchers/is_a"
|
25
|
+
require "rr/wildcard_matchers/numeric"
|
26
|
+
require "rr/wildcard_matchers/boolean"
|
27
|
+
require "rr/wildcard_matchers/duck_type"
|
28
|
+
require "rr/wildcard_matchers/regexp"
|
29
|
+
require "rr/wildcard_matchers/range"
|
30
|
+
|
31
|
+
require "rr/times_called_matchers/times_called_matcher"
|
32
|
+
require "rr/times_called_matchers/integer_matcher"
|
33
|
+
require "rr/times_called_matchers/range_matcher"
|
34
|
+
require "rr/times_called_matchers/proc_matcher"
|
35
|
+
require "rr/times_called_matchers/at_least_matcher"
|
36
|
+
require "rr/times_called_matchers/at_most_matcher"
|
29
37
|
|
30
38
|
require "rr/extensions/double_methods"
|
data/lib/rr/adapters/rspec.rb
CHANGED
@@ -6,13 +6,13 @@ module RR
|
|
6
6
|
module Rspec
|
7
7
|
include RR::Extensions::DoubleMethods
|
8
8
|
def setup_mocks_for_rspec
|
9
|
-
RR::Space.instance.
|
9
|
+
RR::Space.instance.reset
|
10
10
|
end
|
11
11
|
def verify_mocks_for_rspec
|
12
12
|
RR::Space.instance.verify_doubles
|
13
13
|
end
|
14
14
|
def teardown_mocks_for_rspec
|
15
|
-
RR::Space.instance.
|
15
|
+
RR::Space.instance.reset
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/rr/double.rb
CHANGED
@@ -67,13 +67,13 @@ module RR
|
|
67
67
|
@scenarios.each do |scenario|
|
68
68
|
if scenario.exact_match?(*args)
|
69
69
|
matching_scenarios << scenario
|
70
|
-
return scenario.call(*args, &block)
|
70
|
+
return scenario.call(*args, &block) if scenario.attempt?
|
71
71
|
end
|
72
72
|
end
|
73
73
|
@scenarios.each do |scenario|
|
74
74
|
if scenario.wildcard_match?(*args)
|
75
75
|
matching_scenarios << scenario
|
76
|
-
return scenario.call(*args, &block)
|
76
|
+
return scenario.call(*args, &block) if scenario.attempt?
|
77
77
|
end
|
78
78
|
end
|
79
79
|
matching_scenarios.first.call(*args) unless matching_scenarios.empty?
|
@@ -1,27 +1,29 @@
|
|
1
1
|
module RR
|
2
2
|
module Expectations
|
3
3
|
class TimesCalledExpectation
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :matcher, :times_called
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
raise ArgumentError, "Cannot pass in both an argument and a block" if
|
8
|
-
|
6
|
+
def initialize(matcher=nil, &time_condition_block)
|
7
|
+
raise ArgumentError, "Cannot pass in both an argument and a block" if matcher && time_condition_block
|
8
|
+
matcher_value = matcher || time_condition_block
|
9
|
+
@matcher = TimesCalledMatchers::TimesCalledMatcher.create(matcher_value)
|
9
10
|
@times_called = 0
|
10
11
|
@verify_backtrace = caller[1..-1]
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
+
def attempt?
|
15
|
+
@matcher.attempt?(@times_called)
|
16
|
+
end
|
17
|
+
|
18
|
+
def attempt!
|
14
19
|
@times_called += 1
|
15
|
-
verify_input_error
|
16
|
-
verify_input_error if @times.is_a?(Range) && @times_called > @times.end
|
20
|
+
verify_input_error unless @matcher.possible_match?(@times_called)
|
17
21
|
return
|
18
22
|
end
|
19
23
|
|
20
24
|
def verify
|
21
|
-
return
|
22
|
-
return
|
23
|
-
return true if @times.is_a?(Range) && @times.include?(@times_called)
|
24
|
-
return false
|
25
|
+
return false unless @matcher.is_a?(TimesCalledMatchers::TimesCalledMatcher)
|
26
|
+
return @matcher.matches?(@times_called)
|
25
27
|
end
|
26
28
|
|
27
29
|
def verify!
|
@@ -42,8 +44,7 @@ module RR
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def error_message
|
45
|
-
|
46
|
-
"Called #{@times_called.inspect} #{time_casing}. Expected #{@times.inspect}."
|
47
|
+
@matcher.error_message(@times_called)
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
@@ -35,7 +35,7 @@ module Extensions
|
|
35
35
|
# mock(object).method_name(anything) {return_value}
|
36
36
|
# object.method_name("an arbitrary value") # passes
|
37
37
|
def anything
|
38
|
-
RR::
|
38
|
+
RR::WildcardMatchers::Anything.new
|
39
39
|
end
|
40
40
|
|
41
41
|
# Sets up an IsA wildcard ArgumentEqualityError
|
@@ -43,7 +43,7 @@ module Extensions
|
|
43
43
|
# mock(object).method_name(is_a(String)) {return_value}
|
44
44
|
# object.method_name("A String") # passes
|
45
45
|
def is_a(klass)
|
46
|
-
RR::
|
46
|
+
RR::WildcardMatchers::IsA.new(klass)
|
47
47
|
end
|
48
48
|
|
49
49
|
# Sets up an Numeric wildcard ArgumentEqualityError
|
@@ -51,7 +51,7 @@ module Extensions
|
|
51
51
|
# mock(object).method_name(numeric) {return_value}
|
52
52
|
# object.method_name(99) # passes
|
53
53
|
def numeric
|
54
|
-
RR::
|
54
|
+
RR::WildcardMatchers::Numeric.new
|
55
55
|
end
|
56
56
|
|
57
57
|
# Sets up an Boolean wildcard ArgumentEqualityError
|
@@ -59,7 +59,7 @@ module Extensions
|
|
59
59
|
# mock(object).method_name(boolean) {return_value}
|
60
60
|
# object.method_name(false) # passes
|
61
61
|
def boolean
|
62
|
-
RR::
|
62
|
+
RR::WildcardMatchers::Boolean.new
|
63
63
|
end
|
64
64
|
|
65
65
|
# Sets up a DuckType wildcard ArgumentEqualityError
|
@@ -70,7 +70,7 @@ module Extensions
|
|
70
70
|
# mock(object).method_name(duck_type(:foo, :bar)) {return_value}
|
71
71
|
# object.method_name(arg) # passes
|
72
72
|
def duck_type(*args)
|
73
|
-
RR::
|
73
|
+
RR::WildcardMatchers::DuckType.new(*args)
|
74
74
|
end
|
75
75
|
|
76
76
|
instance_methods.each do |name|
|
data/lib/rr/scenario.rb
CHANGED
@@ -83,7 +83,35 @@ module RR
|
|
83
83
|
self
|
84
84
|
end
|
85
85
|
|
86
|
-
# Scenario#
|
86
|
+
# Scenario#at_least allows you to set an expectation that the Scenario
|
87
|
+
# will be called at least n times.
|
88
|
+
# It works by creating a TimesCalledExpectation.
|
89
|
+
#
|
90
|
+
# Passing in a block sets the return value.
|
91
|
+
#
|
92
|
+
# mock(subject).method_name.at_least(4) {:return_value}
|
93
|
+
def at_least(number, &returns)
|
94
|
+
matcher = RR::TimesCalledMatchers::AtLeastMatcher.new(number)
|
95
|
+
@times_called_expectation = Expectations::TimesCalledExpectation.new(matcher)
|
96
|
+
returns(&returns) if returns
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
# Scenario#at_most allows you to set an expectation that the Scenario
|
101
|
+
# will be called at most n times.
|
102
|
+
# It works by creating a TimesCalledExpectation.
|
103
|
+
#
|
104
|
+
# Passing in a block sets the return value.
|
105
|
+
#
|
106
|
+
# mock(subject).method_name.at_most(4) {:return_value}
|
107
|
+
def at_most(number, &returns)
|
108
|
+
matcher = RR::TimesCalledMatchers::AtMostMatcher.new(number)
|
109
|
+
@times_called_expectation = Expectations::TimesCalledExpectation.new(matcher)
|
110
|
+
returns(&returns) if returns
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
# Scenario#times creates an TimesCalledExpectation of the passed
|
87
115
|
# in number.
|
88
116
|
#
|
89
117
|
# Passing in a block sets the return value.
|
@@ -188,7 +216,7 @@ module RR
|
|
188
216
|
end
|
189
217
|
|
190
218
|
def call_implementation(*args, &block)
|
191
|
-
@times_called_expectation.
|
219
|
+
@times_called_expectation.attempt! if @times_called_expectation
|
192
220
|
@space.verify_ordered_scenario(self) if ordered?
|
193
221
|
if @yields
|
194
222
|
unless block
|
@@ -221,11 +249,11 @@ module RR
|
|
221
249
|
@argument_expectation.wildcard_match?(*arguments)
|
222
250
|
end
|
223
251
|
|
224
|
-
# Scenario#
|
252
|
+
# Scenario#attempt? returns true when the
|
225
253
|
# TimesCalledExpectation is satisfied.
|
226
|
-
def
|
227
|
-
return
|
228
|
-
@times_called_expectation.
|
254
|
+
def attempt?
|
255
|
+
return true unless @times_called_expectation
|
256
|
+
@times_called_expectation.attempt?
|
229
257
|
end
|
230
258
|
|
231
259
|
# Scenario#verify verifies the the TimesCalledExpectation
|
@@ -237,4 +265,4 @@ module RR
|
|
237
265
|
true
|
238
266
|
end
|
239
267
|
end
|
240
|
-
end
|
268
|
+
end
|
data/lib/rr/space.rb
CHANGED
@@ -73,7 +73,7 @@ module RR
|
|
73
73
|
# in the correct position.
|
74
74
|
def verify_ordered_scenario(scenario)
|
75
75
|
raise Errors::ScenarioOrderError unless @ordered_scenarios.first == scenario
|
76
|
-
@ordered_scenarios.shift
|
76
|
+
@ordered_scenarios.shift unless scenario.attempt?
|
77
77
|
scenario
|
78
78
|
end
|
79
79
|
|
@@ -87,13 +87,10 @@ module RR
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
# Resets the registered Doubles
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
reset_double(object, method_name)
|
95
|
-
end
|
96
|
-
end
|
90
|
+
# Resets the registered Doubles and ordered Scenarios
|
91
|
+
def reset
|
92
|
+
reset_ordered_scenarios
|
93
|
+
reset_doubles
|
97
94
|
end
|
98
95
|
|
99
96
|
# Verifies the Double for the passed in object and method_name.
|
@@ -109,5 +106,20 @@ module RR
|
|
109
106
|
@doubles.delete(object) if @doubles[object].empty?
|
110
107
|
double.reset
|
111
108
|
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
# Removes the ordered Scenarios from the list
|
112
|
+
def reset_ordered_scenarios
|
113
|
+
@ordered_scenarios.clear
|
114
|
+
end
|
115
|
+
|
116
|
+
# Resets the registered Doubles for the next test run.
|
117
|
+
def reset_doubles
|
118
|
+
@doubles.each do |object, method_double_map|
|
119
|
+
method_double_map.keys.each do |method_name|
|
120
|
+
reset_double(object, method_name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
112
124
|
end
|
113
125
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RR
|
2
|
+
module TimesCalledMatchers
|
3
|
+
class AtLeastMatcher < TimesCalledMatcher
|
4
|
+
def possible_match?(times_called)
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(times_called)
|
9
|
+
times_called >= @times
|
10
|
+
end
|
11
|
+
|
12
|
+
def attempt?(times_called)
|
13
|
+
times_called < @times
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def expected_message_part
|
18
|
+
"Expected at least #{@times.inspect} times."
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|