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.
Files changed (133) hide show
  1. data/CHANGES +221 -0
  2. data/README.rdoc +343 -0
  3. data/Rakefile +88 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/rr.rb +88 -0
  6. data/lib/rr/adapters/rr_methods.rb +122 -0
  7. data/lib/rr/adapters/rspec.rb +59 -0
  8. data/lib/rr/adapters/test_unit.rb +29 -0
  9. data/lib/rr/double.rb +152 -0
  10. data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
  11. data/lib/rr/double_definitions/double_definition.rb +348 -0
  12. data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
  13. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
  14. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
  15. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
  16. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  17. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
  18. data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
  19. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +50 -0
  20. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
  21. data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
  22. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
  23. data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
  24. data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
  25. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
  26. data/lib/rr/double_injection.rb +180 -0
  27. data/lib/rr/double_matches.rb +51 -0
  28. data/lib/rr/errors/argument_equality_error.rb +6 -0
  29. data/lib/rr/errors/double_definition_error.rb +6 -0
  30. data/lib/rr/errors/double_not_found_error.rb +6 -0
  31. data/lib/rr/errors/double_order_error.rb +6 -0
  32. data/lib/rr/errors/rr_error.rb +20 -0
  33. data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
  34. data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
  35. data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
  36. data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
  37. data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
  38. data/lib/rr/errors/times_called_error.rb +6 -0
  39. data/lib/rr/expectations/any_argument_expectation.rb +21 -0
  40. data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
  41. data/lib/rr/expectations/times_called_expectation.rb +57 -0
  42. data/lib/rr/hash_with_object_id_key.rb +44 -0
  43. data/lib/rr/method_dispatches/base_method_dispatch.rb +108 -0
  44. data/lib/rr/method_dispatches/method_dispatch.rb +61 -0
  45. data/lib/rr/method_dispatches/method_missing_dispatch.rb +49 -0
  46. data/lib/rr/proc_from_block.rb +7 -0
  47. data/lib/rr/recorded_calls.rb +103 -0
  48. data/lib/rr/space.rb +123 -0
  49. data/lib/rr/spy_verification.rb +48 -0
  50. data/lib/rr/spy_verification_proxy.rb +18 -0
  51. data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
  52. data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
  53. data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
  54. data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
  55. data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
  56. data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
  57. data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
  58. data/lib/rr/times_called_matchers/terminal.rb +20 -0
  59. data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
  60. data/lib/rr/wildcard_matchers.rb +158 -0
  61. data/lib/rr/wildcard_matchers/anything.rb +18 -0
  62. data/lib/rr/wildcard_matchers/boolean.rb +23 -0
  63. data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
  64. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  65. data/lib/rr/wildcard_matchers/is_a.rb +25 -0
  66. data/lib/rr/wildcard_matchers/numeric.rb +13 -0
  67. data/lib/rr/wildcard_matchers/range.rb +7 -0
  68. data/lib/rr/wildcard_matchers/regexp.rb +7 -0
  69. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  70. data/spec/core_spec_suite.rb +19 -0
  71. data/spec/environment_fixture_setup.rb +7 -0
  72. data/spec/high_level_spec.rb +398 -0
  73. data/spec/proc_from_block_spec.rb +14 -0
  74. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  75. data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
  76. data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
  77. data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
  78. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
  79. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
  80. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
  81. data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
  82. data/spec/rr/double_definitions/double_definition_spec.rb +1165 -0
  83. data/spec/rr/double_injection/double_injection_spec.rb +339 -0
  84. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  85. data/spec/rr/double_spec.rb +352 -0
  86. data/spec/rr/errors/rr_error_spec.rb +67 -0
  87. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  88. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  89. data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
  90. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
  91. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  92. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  93. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  94. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  95. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
  96. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
  97. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
  98. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
  99. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
  100. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
  101. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
  102. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
  103. data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
  104. data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
  105. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
  106. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
  107. data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
  108. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  109. data/spec/rr/space/space_spec.rb +550 -0
  110. data/spec/rr/test_unit/test_helper.rb +7 -0
  111. data/spec/rr/test_unit/test_unit_backtrace_test.rb +36 -0
  112. data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
  113. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  114. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  115. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  116. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  117. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  118. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  119. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  120. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  121. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  122. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  123. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  124. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  125. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  126. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  127. data/spec/rr_spec.rb +28 -0
  128. data/spec/rspec_spec_suite.rb +17 -0
  129. data/spec/spec_helper.rb +109 -0
  130. data/spec/spec_suite.rb +31 -0
  131. data/spec/spy_verification_spec.rb +129 -0
  132. data/spec/test_unit_spec_suite.rb +21 -0
  133. metadata +193 -0
@@ -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
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 10
3
+ :patch: 3
4
+ :major: 0
@@ -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
@@ -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