handoff 0.2.0 → 1.0.0
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/LICENSE +22 -0
- data/README +1 -1
- data/examples/bad_handoffs_test.rb +24 -0
- data/{test → examples}/example_test.rb +0 -0
- data/lib/handoff.rb +2 -4
- data/lib/handoff/argument_normalizer.rb +6 -6
- data/lib/handoff/assertion.rb +15 -11
- data/lib/handoff/verifying_delegate.rb +3 -2
- data/test/handoff/argument_normalizer_test.rb +5 -7
- data/test/handoff/assertion_test.rb +49 -70
- data/test/handoff/verifying_delegate_test.rb +7 -1
- data/test/handoff_test.rb +1 -3
- data/test/test_helper_test.rb +4 -0
- metadata +7 -4
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2007 John D. Hume
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test/test_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/handoff')
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
class BadDelegator
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :a, :foo, :bar
|
8
|
+
def_delegators :b, :foo, :bar
|
9
|
+
def a; Struct.new(:foo, :bar).new; end
|
10
|
+
def b; Struct.new(:foo, :bar).new; end
|
11
|
+
end
|
12
|
+
|
13
|
+
class BadHandoffsTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_with_multiple_redefined_handoffs
|
16
|
+
bad = BadDelegator.new
|
17
|
+
assert_handoff.from(bad).to(:a).for(:foo, :bar)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_with_multiple_unimplemented_handoffs
|
21
|
+
assert_handoff.from(BadDelegator.new).to(:a).for(:baz, :bat)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
File without changes
|
data/lib/handoff.rb
CHANGED
@@ -9,11 +9,9 @@ module Handoff
|
|
9
9
|
|
10
10
|
TEARDOWN_ALIAS = :teardown_before_handoff_rewrite
|
11
11
|
|
12
|
-
# Creates an Assertion, handing a it a mock named 'handoff delegate' on which
|
13
|
-
# expectations will be set.
|
14
12
|
def assert_handoff
|
15
13
|
ensure_handoff_teardown_defined
|
16
|
-
a = Handoff::Assertion.new(self)
|
14
|
+
a = Handoff::Assertion.new(self, caller)
|
17
15
|
handoff_assertions << a
|
18
16
|
a
|
19
17
|
end
|
@@ -44,5 +42,5 @@ module Handoff
|
|
44
42
|
end
|
45
43
|
|
46
44
|
class Test::Unit::TestCase
|
47
|
-
include Handoff
|
45
|
+
include Handoff
|
48
46
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Handoff
|
2
2
|
# Handoff internal.
|
3
3
|
module ArgumentNormalizer
|
4
|
-
|
5
|
-
def to_method_map
|
6
|
-
return first if size == 1 && first.respond_to?(:each_pair)
|
7
|
-
to_self_referencing_hash
|
4
|
+
module_function
|
5
|
+
def to_method_map args
|
6
|
+
return args.first if args.size == 1 && args.first.respond_to?(:each_pair)
|
7
|
+
to_self_referencing_hash args
|
8
8
|
end
|
9
9
|
|
10
|
-
def to_self_referencing_hash
|
10
|
+
def to_self_referencing_hash args
|
11
11
|
hash = Hash.new
|
12
|
-
each {|method_symbol| hash[method_symbol] = method_symbol}
|
12
|
+
args.each {|method_symbol| hash[method_symbol] = method_symbol}
|
13
13
|
hash
|
14
14
|
end
|
15
15
|
|
data/lib/handoff/assertion.rb
CHANGED
@@ -10,13 +10,11 @@ module Handoff
|
|
10
10
|
# * +to+,
|
11
11
|
# * +for+, +for_method+ or +for_methods+, and
|
12
12
|
# * (optionally) +with+ or +with_arguments+.
|
13
|
-
class Assertion < Struct.new(:test)
|
13
|
+
class Assertion < Struct.new(:test, :backtrace)
|
14
14
|
|
15
15
|
# :stopdoc:
|
16
|
-
|
17
16
|
attr_reader :method_map
|
18
17
|
attr_reader :delegator
|
19
|
-
private :method_map, :delegator
|
20
18
|
|
21
19
|
# :startdoc:
|
22
20
|
|
@@ -48,7 +46,7 @@ module Handoff
|
|
48
46
|
# +args+:: symbols representing the delegating methods if they are not renamed, or
|
49
47
|
# a Hash mapping methods in the delegating class to methods in the delegate.
|
50
48
|
def for_methods(*args)
|
51
|
-
@method_map =
|
49
|
+
@method_map = ArgumentNormalizer.to_method_map(args)
|
52
50
|
self
|
53
51
|
end
|
54
52
|
alias for_method for_methods
|
@@ -56,6 +54,7 @@ module Handoff
|
|
56
54
|
|
57
55
|
def with_arguments *args
|
58
56
|
@args = args
|
57
|
+
self
|
59
58
|
end
|
60
59
|
alias with with_arguments
|
61
60
|
|
@@ -70,18 +69,23 @@ module Handoff
|
|
70
69
|
def conduct
|
71
70
|
validate_sufficiently_specified
|
72
71
|
method_map.each do |delegating_method, target_method|
|
73
|
-
|
72
|
+
verifying_delegate = VerifyingDelegate.new(target_method, @args||[])
|
74
73
|
accessor = @delegate_accessor
|
75
74
|
(class << @delegator; self; end).class_eval do
|
76
|
-
define_method(accessor) {
|
75
|
+
define_method(accessor) { verifying_delegate }
|
77
76
|
end
|
78
77
|
send_args = [delegating_method]
|
79
|
-
if @args
|
80
|
-
send_args << @args
|
81
|
-
send_args.flatten!
|
82
|
-
end
|
78
|
+
send_args.concat @args if @args
|
83
79
|
actual_return = @delegator.send *send_args
|
84
|
-
test.
|
80
|
+
test.instance_eval {add_assertion}
|
81
|
+
expected_return = verifying_delegate.happy_return
|
82
|
+
if expected_return != actual_return
|
83
|
+
backtrace = self.backtrace
|
84
|
+
delegate_accessor = @delegate_accessor
|
85
|
+
test.instance_eval do
|
86
|
+
add_failure "`#{delegating_method}' didn't delegate to `#{delegate_accessor}.#{target_method}'", backtrace
|
87
|
+
end
|
88
|
+
end
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
@@ -4,14 +4,15 @@ module Handoff
|
|
4
4
|
@target_method = target_method
|
5
5
|
(class << self; self; end).class_eval do
|
6
6
|
define_method target_method do |*actual_args|
|
7
|
+
raise 'called twice' if @returned
|
7
8
|
raise( ArgumentError, "expected arguments: '#{expected_args}' but got '#{actual_args}'") unless expected_args == actual_args
|
8
|
-
happy_return
|
9
|
+
@returned = true and happy_return
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
14
|
def happy_return
|
14
|
-
"return value from #{to_s}"
|
15
|
+
"handoff return value from #{to_s}"
|
15
16
|
end
|
16
17
|
|
17
18
|
def method_missing method, *args
|
@@ -3,21 +3,19 @@ require File.expand_path(File.dirname(__FILE__) + '/../../lib/handoff/argument_n
|
|
3
3
|
|
4
4
|
module Handoff
|
5
5
|
class ArgumentNormalizerTest < Test::Unit::TestCase
|
6
|
-
|
6
|
+
|
7
7
|
test "should return hash at front of one element array" do
|
8
8
|
hash = {}
|
9
|
-
assert_same hash, [hash]
|
9
|
+
assert_same hash, ArgumentNormalizer.to_method_map([hash])
|
10
10
|
end
|
11
11
|
|
12
12
|
test "should return self referencing hash for array of symbols" do
|
13
|
-
|
14
|
-
assert_equal({:foo => :foo, :bar => :bar}, args.to_method_map)
|
13
|
+
assert_equal({:foo => :foo, :bar => :bar}, ArgumentNormalizer.to_method_map([:bar, :foo]))
|
15
14
|
end
|
16
15
|
|
17
16
|
test "should return self referencing hash for one element array with symbol" do
|
18
|
-
|
19
|
-
assert_equal({:foo => :foo}, args.to_method_map)
|
17
|
+
assert_equal({:foo => :foo}, ArgumentNormalizer.to_method_map([:foo]))
|
20
18
|
end
|
21
|
-
|
19
|
+
|
22
20
|
end
|
23
21
|
end
|
@@ -9,84 +9,63 @@ module Handoff
|
|
9
9
|
|
10
10
|
test 'should construct instance to test and return self when from_any is called' do
|
11
11
|
assertion = Assertion.new(nil)
|
12
|
-
assert_same assertion, assertion.from_any(mock('class under test', :new =>
|
12
|
+
assert_same assertion, assertion.from_any(mock('class under test', :new => :created_object))
|
13
13
|
end
|
14
14
|
|
15
|
-
test 'conduct
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
assertion = Assertion.new(
|
21
|
-
|
15
|
+
test 'conduct adds failure for bad return value' do
|
16
|
+
test_case = mock
|
17
|
+
delegator = mock
|
18
|
+
verifying_delegate = mock
|
19
|
+
|
20
|
+
assertion = Assertion.new(test_case, :backtrace).from(delegator).to(:delegate).for(:method)
|
21
|
+
|
22
|
+
VerifyingDelegate.expects(:new).returns(verifying_delegate)
|
23
|
+
delegator.expects(:method).returns("something other than the verifying delegate's happy_return")
|
24
|
+
verifying_delegate.expects(:happy_return).returns(:the_expected_return_value)
|
25
|
+
test_case.expects(:add_assertion)
|
26
|
+
test_case.expects(:add_failure).with("`method' didn't delegate to `delegate.method'", :backtrace)
|
27
|
+
|
22
28
|
assertion.conduct
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# end.new
|
45
|
-
# assertion = Assertion.new(mock_delegate = mock).from(delegator).to(:delegate).for(:meth)
|
46
|
-
# assertion.with('arg1', :arg2, 3)
|
47
|
-
# assertion.conduct
|
48
|
-
# assert_true mock_delegate.expectations.first.match?(:meth, 'arg1', :arg2, 3)
|
49
|
-
# assert_false mock_delegate.expectations.first.match?(:meth)
|
50
|
-
# assert_false mock_delegate.expectations.first.match?(:meth, 'arg1')
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# {
|
54
|
-
# :with => lambda {|assertion| assertion.with},
|
55
|
-
# :with_no_arguments => lambda {|assertion| assertion.with_no_arguments}
|
56
|
-
# }.each_pair do |method, proc|
|
57
|
-
# test "should force no args when #{method} is used to specify none" do
|
58
|
-
# delegator = Class.new do
|
59
|
-
# extend Forwardable
|
60
|
-
# def_delegator :delegate, :meth
|
61
|
-
# attr_reader :delegate
|
62
|
-
# end.new
|
63
|
-
# assertion = Assertion.new(mock_delegate = mock).from(delegator).to(:delegate).for(:meth)
|
64
|
-
# proc.call(assertion)
|
65
|
-
# assertion.conduct
|
66
|
-
# assert_true mock_delegate.expectations.first.match?(:meth)
|
67
|
-
# assert_false mock_delegate.expectations.first.match?(:meth, 'arg1')
|
68
|
-
# end
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
# test 'should allow for args or no args if nothing specified' do
|
72
|
-
# delegator = Class.new do
|
73
|
-
# extend Forwardable
|
74
|
-
# def_delegator :delegate, :meth
|
75
|
-
# attr_reader :delegate
|
76
|
-
# end.new
|
77
|
-
# assertion = Assertion.new(mock_delegate = mock).from(delegator).to(:delegate).for(:meth)
|
78
|
-
# assertion.conduct
|
79
|
-
# assert_true mock_delegate.expectations.first.match?(:meth)
|
80
|
-
# assert_true mock_delegate.expectations.first.match?(:meth, 'arg1')
|
81
|
-
# end
|
31
|
+
test 'for each method, conduct attaches verifying delegate to delegator and invokes method' do
|
32
|
+
test_case = mock
|
33
|
+
delegator = mock
|
34
|
+
verifying_delegate1 = mock
|
35
|
+
verifying_delegate2 = mock
|
36
|
+
method_map = mock
|
37
|
+
|
38
|
+
assertion = Assertion.new(test_case).from(delegator).to(:delegate).for(:method1 => :target_method1, :method2 => :target_method2).with('the args')
|
39
|
+
VerifyingDelegate.expects(:new).with(:target_method1, ['the args']).returns(verifying_delegate1)
|
40
|
+
delegator.expects(:method1).with('the args').returns(:return_value1)
|
41
|
+
verifying_delegate1.expects(:happy_return).returns(:return_value1)
|
42
|
+
test_case.expects(:add_assertion)
|
43
|
+
VerifyingDelegate.expects(:new).with(:target_method2, ['the args']).returns(verifying_delegate2)
|
44
|
+
delegator.expects(:method2).with('the args').returns(:return_value2)
|
45
|
+
verifying_delegate2.expects(:happy_return).returns(:return_value2)
|
46
|
+
test_case.expects(:add_assertion)
|
47
|
+
|
48
|
+
assertion.conduct
|
49
|
+
end
|
82
50
|
|
83
|
-
test '
|
84
|
-
|
85
|
-
assert_raises(UsageError) { assertion.conduct }
|
51
|
+
test 'converts method list or hash into method map with ArgumentNormalizer' do
|
52
|
+
ArgumentNormalizer.expects(:to_method_map).with([:args]).returns(:the_method_map)
|
86
53
|
|
87
|
-
assertion = Assertion.new(mock).
|
54
|
+
assertion = Assertion.new(mock).for_methods(:args)
|
55
|
+
assert_equal :the_method_map, assertion.method_map
|
56
|
+
end
|
57
|
+
|
58
|
+
test 'validates presence of delegator' do
|
59
|
+
assertion = Assertion.new(mock).to(:asdf).for_method(:meth)
|
88
60
|
assert_raises(UsageError) { assertion.conduct }
|
89
|
-
|
61
|
+
end
|
62
|
+
|
63
|
+
test 'validates presence of delegate accessor' do
|
64
|
+
assertion = Assertion.new(mock).from("whatever").for_method(:meth)
|
65
|
+
assert_raises(UsageError) { assertion.conduct }
|
66
|
+
end
|
67
|
+
|
68
|
+
test 'validates presence of delegating methods' do
|
90
69
|
assertion = Assertion.new(mock).from("whatever").to(:asdf)
|
91
70
|
assert_raises(UsageError) { assertion.conduct }
|
92
71
|
end
|
@@ -5,7 +5,7 @@ module Handoff
|
|
5
5
|
class VerifyingDelegateTest < Test::Unit::TestCase
|
6
6
|
test "happy_return value" do
|
7
7
|
d = VerifyingDelegate.new(:foo, [])
|
8
|
-
assert_equal "return value from #{d.to_s}", d.happy_return
|
8
|
+
assert_equal "handoff return value from #{d.to_s}", d.happy_return
|
9
9
|
end
|
10
10
|
|
11
11
|
test 'responds to target method with happy_return value' do
|
@@ -23,6 +23,12 @@ module Handoff
|
|
23
23
|
assert_raises(ArgumentError) { d.foo }
|
24
24
|
end
|
25
25
|
|
26
|
+
test 'raises if target invoked twice' do
|
27
|
+
d = VerifyingDelegate.new(:foo, [])
|
28
|
+
d.foo
|
29
|
+
assert_raises(RuntimeError) { d.foo }
|
30
|
+
end
|
31
|
+
|
26
32
|
test 'raises NoMethodError with helpful message if wrong method is invoked' do
|
27
33
|
d = VerifyingDelegate.new(:foo, [])
|
28
34
|
begin
|
data/test/handoff_test.rb
CHANGED
@@ -4,13 +4,11 @@ require 'mocha'
|
|
4
4
|
require File.expand_path(File.dirname(__FILE__) + '/../lib/handoff')
|
5
5
|
|
6
6
|
class HandoffTest < Test::Unit::TestCase
|
7
|
-
test '
|
7
|
+
test 'conducts each assertion in conduct_and_clear_handoffs' do
|
8
8
|
handoff_assertions << assertion1 = mock(:conduct => nil)
|
9
9
|
handoff_assertions << assertion2 = mock(:conduct => nil)
|
10
10
|
conduct_and_clear_handoffs
|
11
11
|
assert_true handoff_assertions.empty?
|
12
|
-
assertion1.verify
|
13
|
-
assertion2.verify
|
14
12
|
end
|
15
13
|
|
16
14
|
def blank_test_case
|
data/test/test_helper_test.rb
CHANGED
metadata
CHANGED
@@ -3,9 +3,9 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: handoff
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
8
|
-
summary: Handoff is a fluent interface for making
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-10-26 00:00:00 -04:00
|
8
|
+
summary: Handoff is a fluent interface for making Test::Unit assertions about delegation.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email: ""
|
@@ -35,9 +35,11 @@ files:
|
|
35
35
|
- lib/handoff/assertion.rb
|
36
36
|
- lib/handoff/usage_error.rb
|
37
37
|
- lib/handoff/verifying_delegate.rb
|
38
|
+
- examples/bad_handoffs_test.rb
|
39
|
+
- examples/example_test.rb
|
38
40
|
- README
|
41
|
+
- LICENSE
|
39
42
|
test_files:
|
40
|
-
- test/example_test.rb
|
41
43
|
- test/handoff_test.rb
|
42
44
|
- test/test_helper_test.rb
|
43
45
|
- test/handoff/argument_normalizer_test.rb
|
@@ -47,6 +49,7 @@ rdoc_options: []
|
|
47
49
|
|
48
50
|
extra_rdoc_files:
|
49
51
|
- README
|
52
|
+
- LICENSE
|
50
53
|
executables: []
|
51
54
|
|
52
55
|
extensions: []
|