redinger-rr 0.10.3
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 +221 -0
- data/README.rdoc +343 -0
- data/Rakefile +88 -0
- data/VERSION.yml +4 -0
- data/lib/rr.rb +88 -0
- data/lib/rr/adapters/rr_methods.rb +122 -0
- data/lib/rr/adapters/rspec.rb +59 -0
- data/lib/rr/adapters/test_unit.rb +29 -0
- data/lib/rr/double.rb +152 -0
- data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
- data/lib/rr/double_definitions/double_definition.rb +348 -0
- data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
- data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
- data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
- data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
- data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
- data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
- data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +50 -0
- data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
- data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
- data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
- data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
- data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
- data/lib/rr/double_injection.rb +180 -0
- data/lib/rr/double_matches.rb +51 -0
- data/lib/rr/errors/argument_equality_error.rb +6 -0
- data/lib/rr/errors/double_definition_error.rb +6 -0
- data/lib/rr/errors/double_not_found_error.rb +6 -0
- data/lib/rr/errors/double_order_error.rb +6 -0
- data/lib/rr/errors/rr_error.rb +20 -0
- data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
- data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
- data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
- data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
- data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
- data/lib/rr/errors/times_called_error.rb +6 -0
- data/lib/rr/expectations/any_argument_expectation.rb +21 -0
- data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
- data/lib/rr/expectations/times_called_expectation.rb +57 -0
- data/lib/rr/hash_with_object_id_key.rb +44 -0
- data/lib/rr/method_dispatches/base_method_dispatch.rb +108 -0
- data/lib/rr/method_dispatches/method_dispatch.rb +61 -0
- data/lib/rr/method_dispatches/method_missing_dispatch.rb +49 -0
- data/lib/rr/proc_from_block.rb +7 -0
- data/lib/rr/recorded_calls.rb +103 -0
- data/lib/rr/space.rb +123 -0
- data/lib/rr/spy_verification.rb +48 -0
- data/lib/rr/spy_verification_proxy.rb +18 -0
- data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
- data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
- data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
- data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
- data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
- data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
- data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
- data/lib/rr/times_called_matchers/terminal.rb +20 -0
- data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
- data/lib/rr/wildcard_matchers.rb +158 -0
- data/lib/rr/wildcard_matchers/anything.rb +18 -0
- data/lib/rr/wildcard_matchers/boolean.rb +23 -0
- data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
- data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
- data/lib/rr/wildcard_matchers/is_a.rb +25 -0
- data/lib/rr/wildcard_matchers/numeric.rb +13 -0
- data/lib/rr/wildcard_matchers/range.rb +7 -0
- data/lib/rr/wildcard_matchers/regexp.rb +7 -0
- data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
- data/spec/core_spec_suite.rb +19 -0
- data/spec/environment_fixture_setup.rb +7 -0
- data/spec/high_level_spec.rb +398 -0
- data/spec/proc_from_block_spec.rb +14 -0
- data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
- data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
- data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
- data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
- data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
- data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
- data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
- data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
- data/spec/rr/double_definitions/double_definition_spec.rb +1165 -0
- data/spec/rr/double_injection/double_injection_spec.rb +339 -0
- data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
- data/spec/rr/double_spec.rb +352 -0
- data/spec/rr/errors/rr_error_spec.rb +67 -0
- data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
- data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
- data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
- data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
- data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
- data/spec/rr/expectations/hash_including_spec.rb +17 -0
- data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
- data/spec/rr/expectations/satisfy_spec.rb +14 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
- data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
- data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
- data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
- data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
- data/spec/rr/space/space_spec.rb +550 -0
- data/spec/rr/test_unit/test_helper.rb +7 -0
- data/spec/rr/test_unit/test_unit_backtrace_test.rb +36 -0
- data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
- data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
- data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
- data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
- data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
- data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
- data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
- data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
- data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
- data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
- data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
- data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
- data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
- data/spec/rr_spec.rb +28 -0
- data/spec/rspec_spec_suite.rb +17 -0
- data/spec/spec_helper.rb +109 -0
- data/spec/spec_suite.rb +31 -0
- data/spec/spy_verification_spec.rb +129 -0
- data/spec/test_unit_spec_suite.rb +21 -0
- metadata +193 -0
data/Rakefile
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require "rake"
|
2
|
+
require 'rake/contrib/rubyforgepublisher'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
|
7
|
+
desc "Runs the Rspec suite"
|
8
|
+
task(:default) do
|
9
|
+
run_suite
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Runs the Rspec suite"
|
13
|
+
task(:spec) do
|
14
|
+
run_suite
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_suite
|
18
|
+
dir = File.dirname(__FILE__)
|
19
|
+
system("ruby #{dir}/spec/spec_suite.rb") || raise("Spec Suite failed")
|
20
|
+
end
|
21
|
+
|
22
|
+
begin
|
23
|
+
require 'jeweler'
|
24
|
+
Jeweler::Tasks.new do |s|
|
25
|
+
s.name = "rr"
|
26
|
+
s.summary = "RR (Double Ruby) is a double framework that features a rich " <<
|
27
|
+
"selection of double techniques and a terse syntax. " <<
|
28
|
+
"http://xunitpatterns.com/Test%20Double.html"
|
29
|
+
s.email = "brian@pivotallabs.com"
|
30
|
+
s.homepage = "http://pivotallabs.com"
|
31
|
+
s.description = "RR (Double Ruby) is a double framework that features a rich " <<
|
32
|
+
"selection of double techniques and a terse syntax. " <<
|
33
|
+
"http://xunitpatterns.com/Test%20Double.html"
|
34
|
+
s.authors = ["Brian Takita"]
|
35
|
+
s.files = FileList[
|
36
|
+
'[A-Z]*',
|
37
|
+
'*.rb',
|
38
|
+
'lib/**/*.rb',
|
39
|
+
'spec/**/*.rb'
|
40
|
+
].to_a
|
41
|
+
s.test_files = Dir.glob('spec/*_spec.rb')
|
42
|
+
s.has_rdoc = true
|
43
|
+
s.extra_rdoc_files = [ "README.rdoc", "CHANGES" ]
|
44
|
+
s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
|
45
|
+
s.rubyforge_project = "pivotalrb"
|
46
|
+
end
|
47
|
+
rescue LoadError
|
48
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
49
|
+
end
|
50
|
+
RUBYFORGE_PACKAGE_NAME = "rr (Double Ruby)"
|
51
|
+
# The package was renamed from "rr (Double R)" to "rr (Double Ruby)".
|
52
|
+
# When this was last run, the script did not work for the new name but it did work for the old name.
|
53
|
+
# Perhaps more time was needed for the name change to propagate?
|
54
|
+
#RUBYFORGE_PACKAGE_NAME = "rr (Double R)"
|
55
|
+
|
56
|
+
# This is hacked to get around the 3 character limitation for package names on Rubyforge.
|
57
|
+
# http://rubyforge.org/tracker/index.php?func=detail&aid=27026&group_id=5&atid=102
|
58
|
+
class Jeweler
|
59
|
+
module Commands
|
60
|
+
class ReleaseToRubyforge
|
61
|
+
def run
|
62
|
+
raise NoRubyForgeProjectInGemspecError unless @gemspec.rubyforge_project
|
63
|
+
|
64
|
+
@rubyforge.configure rescue nil
|
65
|
+
|
66
|
+
output.puts 'Logging in rubyforge'
|
67
|
+
@rubyforge.login
|
68
|
+
|
69
|
+
@rubyforge.userconfig['release_notes'] = @gemspec.description if @gemspec.description
|
70
|
+
@rubyforge.userconfig['preformatted'] = true
|
71
|
+
|
72
|
+
output.puts "Releasing #{@gemspec.name}-#{@version} to #{@gemspec.rubyforge_project}"
|
73
|
+
begin
|
74
|
+
@rubyforge.add_release(@gemspec.rubyforge_project, RUBYFORGE_PACKAGE_NAME, @version.to_s, @gemspec_helper.gem_path)
|
75
|
+
rescue StandardError => e
|
76
|
+
case e.message
|
77
|
+
when /no <group_id> configured for <#{Regexp.escape @gemspec.rubyforge_project}>/
|
78
|
+
raise RubyForgeProjectNotConfiguredError, @gemspec.rubyforge_project
|
79
|
+
when /no <package_id> configured for <#{Regexp.escape @gemspec.name}>/i
|
80
|
+
raise MissingRubyForgePackageError, @gemspec.name
|
81
|
+
else
|
82
|
+
raise
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/VERSION.yml
ADDED
data/lib/rr.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require "#{dir}/rr/errors/rr_error"
|
5
|
+
require "#{dir}/rr/errors/subject_does_not_implement_method_error"
|
6
|
+
require "#{dir}/rr/errors/subject_has_different_arity_error"
|
7
|
+
require "#{dir}/rr/errors/double_definition_error"
|
8
|
+
require "#{dir}/rr/errors/double_not_found_error"
|
9
|
+
require "#{dir}/rr/errors/double_order_error"
|
10
|
+
require "#{dir}/rr/errors/argument_equality_error"
|
11
|
+
require "#{dir}/rr/errors/times_called_error"
|
12
|
+
require "#{dir}/rr/errors/spy_verification_errors/spy_verification_error"
|
13
|
+
require "#{dir}/rr/errors/spy_verification_errors/double_injection_not_found_error"
|
14
|
+
require "#{dir}/rr/errors/spy_verification_errors/invocation_count_error"
|
15
|
+
|
16
|
+
require "#{dir}/rr/space"
|
17
|
+
require "#{dir}/rr/double_injection"
|
18
|
+
require "#{dir}/rr/method_dispatches/base_method_dispatch"
|
19
|
+
require "#{dir}/rr/method_dispatches/method_dispatch"
|
20
|
+
require "#{dir}/rr/method_dispatches/method_missing_dispatch"
|
21
|
+
require "#{dir}/rr/hash_with_object_id_key"
|
22
|
+
require "#{dir}/rr/recorded_calls"
|
23
|
+
require "#{dir}/rr/proc_from_block"
|
24
|
+
|
25
|
+
require "#{dir}/rr/double_definitions/double_definition_creator_proxy"
|
26
|
+
require "#{dir}/rr/double_definitions/double_definition_creator"
|
27
|
+
require "#{dir}/rr/double_definitions/child_double_definition_creator"
|
28
|
+
require "#{dir}/rr/adapters/rr_methods"
|
29
|
+
|
30
|
+
require "#{dir}/rr/double"
|
31
|
+
require "#{dir}/rr/double_definitions/double_definition"
|
32
|
+
require "#{dir}/rr/double_definitions/strategies/strategy"
|
33
|
+
require "#{dir}/rr/double_definitions/strategies/verification/verification_strategy"
|
34
|
+
require "#{dir}/rr/double_definitions/strategies/verification/mock"
|
35
|
+
require "#{dir}/rr/double_definitions/strategies/verification/stub"
|
36
|
+
require "#{dir}/rr/double_definitions/strategies/verification/dont_allow"
|
37
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/implementation_strategy"
|
38
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/reimplementation"
|
39
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation"
|
40
|
+
require "#{dir}/rr/double_definitions/strategies/implementation/proxy"
|
41
|
+
require "#{dir}/rr/double_definitions/strategies/scope/scope_strategy"
|
42
|
+
require "#{dir}/rr/double_definitions/strategies/scope/instance"
|
43
|
+
require "#{dir}/rr/double_definitions/strategies/scope/instance_of_class"
|
44
|
+
require "#{dir}/rr/double_matches"
|
45
|
+
|
46
|
+
require "#{dir}/rr/expectations/argument_equality_expectation"
|
47
|
+
require "#{dir}/rr/expectations/any_argument_expectation"
|
48
|
+
require "#{dir}/rr/expectations/times_called_expectation"
|
49
|
+
|
50
|
+
require "#{dir}/rr/wildcard_matchers/anything"
|
51
|
+
require "#{dir}/rr/wildcard_matchers/is_a"
|
52
|
+
require "#{dir}/rr/wildcard_matchers/numeric"
|
53
|
+
require "#{dir}/rr/wildcard_matchers/boolean"
|
54
|
+
require "#{dir}/rr/wildcard_matchers/duck_type"
|
55
|
+
require "#{dir}/rr/wildcard_matchers/regexp"
|
56
|
+
require "#{dir}/rr/wildcard_matchers/range"
|
57
|
+
require "#{dir}/rr/wildcard_matchers/satisfy"
|
58
|
+
require "#{dir}/rr/wildcard_matchers/hash_including"
|
59
|
+
|
60
|
+
require "#{dir}/rr/times_called_matchers/terminal"
|
61
|
+
require "#{dir}/rr/times_called_matchers/non_terminal"
|
62
|
+
require "#{dir}/rr/times_called_matchers/times_called_matcher"
|
63
|
+
require "#{dir}/rr/times_called_matchers/any_times_matcher"
|
64
|
+
require "#{dir}/rr/times_called_matchers/integer_matcher"
|
65
|
+
require "#{dir}/rr/times_called_matchers/range_matcher"
|
66
|
+
require "#{dir}/rr/times_called_matchers/proc_matcher"
|
67
|
+
require "#{dir}/rr/times_called_matchers/at_least_matcher"
|
68
|
+
require "#{dir}/rr/times_called_matchers/at_most_matcher"
|
69
|
+
|
70
|
+
require "#{dir}/rr/spy_verification_proxy"
|
71
|
+
require "#{dir}/rr/spy_verification"
|
72
|
+
|
73
|
+
require "#{dir}/rr/adapters/rspec"
|
74
|
+
require "#{dir}/rr/adapters/test_unit"
|
75
|
+
|
76
|
+
module RR
|
77
|
+
class << self
|
78
|
+
include Adapters::RRMethods
|
79
|
+
(RR::Space.instance_methods - Object.instance_methods).each do |method_name|
|
80
|
+
returns_method = <<-METHOD
|
81
|
+
def #{method_name}(*args, &block)
|
82
|
+
RR::Space.instance.__send__(:#{method_name}, *args, &block)
|
83
|
+
end
|
84
|
+
METHOD
|
85
|
+
class_eval(returns_method, __FILE__, __LINE__ - 4)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module RR
|
2
|
+
module Adapters
|
3
|
+
module RRMethods
|
4
|
+
class << self
|
5
|
+
def register_strategy_class(strategy_class, method_name)
|
6
|
+
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
7
|
+
def #{method_name}(subject=DoubleDefinitions::DoubleDefinitionCreator::NO_SUBJECT, method_name=nil, &definition_eval_block)
|
8
|
+
creator = DoubleDefinitions::DoubleDefinitionCreator.new
|
9
|
+
creator.#{method_name}(subject, method_name, &definition_eval_block)
|
10
|
+
end
|
11
|
+
CLASS
|
12
|
+
|
13
|
+
class_eval((<<-CLASS), __FILE__, __LINE__ + 1)
|
14
|
+
def #{method_name}!(method_name=nil, &definition_eval_block)
|
15
|
+
creator = DoubleDefinitions::DoubleDefinitionCreator.new
|
16
|
+
creator.#{method_name}!(method_name, &definition_eval_block)
|
17
|
+
end
|
18
|
+
CLASS
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Verifies all the DoubleInjection objects have met their
|
23
|
+
# TimesCalledExpectations.
|
24
|
+
def verify
|
25
|
+
RR::Space.instance.verify_doubles
|
26
|
+
end
|
27
|
+
|
28
|
+
# Resets the registered Doubles and ordered Doubles
|
29
|
+
def reset
|
30
|
+
RR::Space.instance.reset
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a AnyTimesMatcher. This is meant to be passed in as an argument
|
34
|
+
# to Double#times.
|
35
|
+
#
|
36
|
+
# mock(object).method_name(anything).times(any_times) {return_value}
|
37
|
+
def any_times
|
38
|
+
TimesCalledMatchers::AnyTimesMatcher.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets up an Anything wildcard ArgumentEqualityExpectation
|
42
|
+
# that succeeds when passed any argument.
|
43
|
+
# mock(object).method_name(anything) {return_value}
|
44
|
+
# object.method_name("an arbitrary value") # passes
|
45
|
+
def anything
|
46
|
+
RR::WildcardMatchers::Anything.new
|
47
|
+
end
|
48
|
+
|
49
|
+
# Sets up an IsA wildcard ArgumentEqualityExpectation
|
50
|
+
# that succeeds when passed an argument of a certain type.
|
51
|
+
# mock(object).method_name(is_a(String)) {return_value}
|
52
|
+
# object.method_name("A String") # passes
|
53
|
+
def is_a(klass)
|
54
|
+
RR::WildcardMatchers::IsA.new(klass)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Sets up an Numeric wildcard ArgumentEqualityExpectation
|
58
|
+
# that succeeds when passed an argument that is ::Numeric.
|
59
|
+
# mock(object).method_name(numeric) {return_value}
|
60
|
+
# object.method_name(99) # passes
|
61
|
+
def numeric
|
62
|
+
RR::WildcardMatchers::Numeric.new
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets up an Boolean wildcard ArgumentEqualityExpectation
|
66
|
+
# that succeeds when passed an argument that is a ::Boolean.
|
67
|
+
# mock(object).method_name(boolean) {return_value}
|
68
|
+
# object.method_name(false) # passes
|
69
|
+
def boolean
|
70
|
+
RR::WildcardMatchers::Boolean.new
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sets up a DuckType wildcard ArgumentEqualityExpectation
|
74
|
+
# that succeeds when the passed argument implements the methods.
|
75
|
+
# arg = Object.new
|
76
|
+
# def arg.foo; end
|
77
|
+
# def arg.bar; end
|
78
|
+
# mock(object).method_name(duck_type(:foo, :bar)) {return_value}
|
79
|
+
# object.method_name(arg) # passes
|
80
|
+
def duck_type(*args)
|
81
|
+
RR::WildcardMatchers::DuckType.new(*args)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Sets up a HashIncluding wildcard ArgumentEqualityExpectation
|
85
|
+
# that succeeds when the passed argument contains at least those keys
|
86
|
+
# and values of the expectation.
|
87
|
+
# mock(object).method_name(hash_including(:foo => 1)) {return_value}
|
88
|
+
# object.method_name({:foo => 1, :bar => 2) # passes
|
89
|
+
def hash_including(expected_hash)
|
90
|
+
RR::WildcardMatchers::HashIncluding.new(expected_hash)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sets up a Satisfy wildcard ArgumentEqualityExpectation
|
94
|
+
# that succeeds when the passed argument causes the expectation's
|
95
|
+
# proc to return true.
|
96
|
+
# mock(object).method_name(satisfy {|arg| arg == :foo}) {return_value}
|
97
|
+
# object.method_name(:foo) # passes
|
98
|
+
def satisfy(expectation_proc=nil, &block)
|
99
|
+
expectation_proc ||= block
|
100
|
+
RR::WildcardMatchers::Satisfy.new(expectation_proc)
|
101
|
+
end
|
102
|
+
|
103
|
+
def spy(subject)
|
104
|
+
methods_to_stub = subject.public_methods - ["methods", "==", "__send__", "__id__"]
|
105
|
+
methods_to_stub.each do |method|
|
106
|
+
stub.proxy(subject, method)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def received(subject)
|
111
|
+
RR::SpyVerificationProxy.new(subject)
|
112
|
+
end
|
113
|
+
|
114
|
+
instance_methods.each do |name|
|
115
|
+
alias_method "rr_#{name}", name
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
module Extensions
|
120
|
+
InstanceMethods = Adapters::RRMethods
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module RR
|
2
|
+
module Adapters
|
3
|
+
module Rspec
|
4
|
+
def self.included(mod)
|
5
|
+
patterns = ::Spec::Runner::QuietBacktraceTweaker::IGNORE_PATTERNS
|
6
|
+
unless patterns.include?(RR::Errors::BACKTRACE_IDENTIFIER)
|
7
|
+
patterns.push(RR::Errors::BACKTRACE_IDENTIFIER)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
include RRMethods
|
12
|
+
def setup_mocks_for_rspec
|
13
|
+
RR.reset
|
14
|
+
end
|
15
|
+
def verify_mocks_for_rspec
|
16
|
+
RR.verify
|
17
|
+
end
|
18
|
+
def teardown_mocks_for_rspec
|
19
|
+
RR.reset
|
20
|
+
end
|
21
|
+
|
22
|
+
def have_received(method = nil)
|
23
|
+
InvocationMatcher.new(method)
|
24
|
+
end
|
25
|
+
|
26
|
+
class InvocationMatcher < SpyVerificationProxy
|
27
|
+
attr_reader :failure_message
|
28
|
+
|
29
|
+
def initialize(method = nil)
|
30
|
+
method_missing(method) if method
|
31
|
+
end
|
32
|
+
|
33
|
+
def matches?(subject)
|
34
|
+
@verification.subject = subject
|
35
|
+
calls = RR::Space.instance.recorded_calls
|
36
|
+
if error = calls.match_error(@verification)
|
37
|
+
@failure_message = error.message
|
38
|
+
false
|
39
|
+
else
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def nil?
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
48
|
+
def method_missing(method_name, *args, &block)
|
49
|
+
if @verification
|
50
|
+
@verification.send(method_name, *args)
|
51
|
+
else
|
52
|
+
@verification = super
|
53
|
+
end
|
54
|
+
self
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RR
|
2
|
+
module Adapters
|
3
|
+
module TestUnit
|
4
|
+
include RRMethods
|
5
|
+
def self.included(mod)
|
6
|
+
RR.trim_backtrace = true
|
7
|
+
mod.class_eval do
|
8
|
+
alias_method :setup_without_rr, :setup
|
9
|
+
def setup_with_rr
|
10
|
+
setup_without_rr
|
11
|
+
RR.reset
|
12
|
+
end
|
13
|
+
alias_method :setup, :setup_with_rr
|
14
|
+
|
15
|
+
alias_method :teardown_without_rr, :teardown
|
16
|
+
def teardown_with_rr
|
17
|
+
RR.verify
|
18
|
+
teardown_without_rr
|
19
|
+
end
|
20
|
+
alias_method :teardown, :teardown_with_rr
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def assert_received(subject, &block)
|
25
|
+
block.call(received(subject)).call
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rr/double.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
module RR
|
2
|
+
# RR::Double is the use case for a method call.
|
3
|
+
# It has the ArgumentEqualityExpectation, TimesCalledExpectation,
|
4
|
+
# and the implementation.
|
5
|
+
class Double
|
6
|
+
class << self
|
7
|
+
def formatted_name(method_name, args)
|
8
|
+
formatted_errors = args.collect {|arg| arg.inspect}.join(', ')
|
9
|
+
"#{method_name}(#{formatted_errors})"
|
10
|
+
end
|
11
|
+
|
12
|
+
def list_message_part(doubles)
|
13
|
+
doubles.collect do |double|
|
14
|
+
"- #{formatted_name(double.method_name, double.expected_arguments)}"
|
15
|
+
end.join("\n")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :times_called, :double_injection, :definition, :times_called_expectation
|
20
|
+
include Space::Reader
|
21
|
+
|
22
|
+
def initialize(double_injection, definition)
|
23
|
+
@double_injection = double_injection
|
24
|
+
@definition = definition
|
25
|
+
@times_called = 0
|
26
|
+
@times_called_expectation = Expectations::TimesCalledExpectation.new(self)
|
27
|
+
definition.double = self
|
28
|
+
verify_method_signature if definition.verify_method_signature?
|
29
|
+
double_injection.register_double self
|
30
|
+
end
|
31
|
+
|
32
|
+
# Double#exact_match? returns true when the passed in arguments
|
33
|
+
# exactly match the ArgumentEqualityExpectation arguments.
|
34
|
+
def exact_match?(*arguments)
|
35
|
+
definition.exact_match?(*arguments)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Double#wildcard_match? returns true when the passed in arguments
|
39
|
+
# wildcard match the ArgumentEqualityExpectation arguments.
|
40
|
+
def wildcard_match?(*arguments)
|
41
|
+
definition.wildcard_match?(*arguments)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Double#attempt? returns true when the
|
45
|
+
# TimesCalledExpectation is satisfied.
|
46
|
+
def attempt?
|
47
|
+
verify_times_matcher_is_set
|
48
|
+
times_called_expectation.attempt?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Double#verify verifies the the TimesCalledExpectation
|
52
|
+
# is satisfied for this double. A TimesCalledError
|
53
|
+
# is raised if the TimesCalledExpectation is not met.
|
54
|
+
def verify
|
55
|
+
verify_times_matcher_is_set
|
56
|
+
times_called_expectation.verify!
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def terminal?
|
61
|
+
verify_times_matcher_is_set
|
62
|
+
times_called_expectation.terminal?
|
63
|
+
end
|
64
|
+
|
65
|
+
# The method name that this Double is attatched to
|
66
|
+
def method_name
|
67
|
+
double_injection.method_name
|
68
|
+
end
|
69
|
+
|
70
|
+
# The Arguments that this Double expects
|
71
|
+
def expected_arguments
|
72
|
+
verify_argument_expectation_is_set
|
73
|
+
argument_expectation.expected_arguments
|
74
|
+
end
|
75
|
+
|
76
|
+
# The TimesCalledMatcher for the TimesCalledExpectation
|
77
|
+
def times_matcher
|
78
|
+
definition.times_matcher
|
79
|
+
end
|
80
|
+
|
81
|
+
def formatted_name
|
82
|
+
self.class.formatted_name(method_name, expected_arguments)
|
83
|
+
end
|
84
|
+
|
85
|
+
def method_call(args)
|
86
|
+
if verbose?
|
87
|
+
puts Double.formatted_name(method_name, args)
|
88
|
+
end
|
89
|
+
times_called_expectation.attempt if definition.times_matcher
|
90
|
+
space.verify_ordered_double(self) if ordered?
|
91
|
+
end
|
92
|
+
|
93
|
+
def implementation_is_original_method?
|
94
|
+
definition.implementation_is_original_method?
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
def ordered?
|
99
|
+
definition.ordered?
|
100
|
+
end
|
101
|
+
|
102
|
+
def verbose?
|
103
|
+
definition.verbose?
|
104
|
+
end
|
105
|
+
|
106
|
+
def verify_times_matcher_is_set
|
107
|
+
unless definition.times_matcher
|
108
|
+
raise RR::Errors::DoubleDefinitionError, "#definition.times_matcher is not set"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def verify_argument_expectation_is_set
|
113
|
+
unless definition.argument_expectation
|
114
|
+
raise RR::Errors::DoubleDefinitionError, "#definition.argument_expectation is not set"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def verify_method_signature
|
119
|
+
raise RR::Errors::SubjectDoesNotImplementMethodError unless definition.subject.respond_to?(double_injection.send(:original_method_alias_name))
|
120
|
+
raise RR::Errors::SubjectHasDifferentArityError unless arity_matches?
|
121
|
+
end
|
122
|
+
|
123
|
+
def subject_arity
|
124
|
+
definition.subject.method(double_injection.send(:original_method_alias_name)).arity
|
125
|
+
end
|
126
|
+
|
127
|
+
def subject_accepts_only_varargs?
|
128
|
+
subject_arity == -1
|
129
|
+
end
|
130
|
+
|
131
|
+
def subject_accepts_varargs?
|
132
|
+
subject_arity < 0
|
133
|
+
end
|
134
|
+
|
135
|
+
def arity_matches?
|
136
|
+
return true if subject_accepts_only_varargs?
|
137
|
+
if subject_accepts_varargs?
|
138
|
+
return ((subject_arity * -1) - 1) <= args.size
|
139
|
+
else
|
140
|
+
return subject_arity == args.size
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def args
|
145
|
+
definition.argument_expectation.expected_arguments
|
146
|
+
end
|
147
|
+
|
148
|
+
def argument_expectation
|
149
|
+
definition.argument_expectation
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|