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 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
@@ -9,5 +9,5 @@ As of 0.2.0, Handoff no longer depends on Mocha and Stubba.
9
9
 
10
10
  Here's example_test.rb to give you an idea of what you can do:
11
11
 
12
- :include: test/example_test.rb
12
+ :include: examples/example_test.rb
13
13
 
@@ -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
@@ -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 unless ancestors.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
 
@@ -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 = args.extend(ArgumentNormalizer).to_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
- mock_delegate = VerifyingDelegate.new(target_method, @args||[])
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) { mock_delegate }
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.assert_equal mock_delegate.happy_return, actual_return
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].extend(ArgumentNormalizer).to_method_map
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
- args = [:bar, :foo].extend(ArgumentNormalizer)
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
- args = [:foo].extend(ArgumentNormalizer)
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 => nil))
12
+ assert_same assertion, assertion.from_any(mock('class under test', :new => :created_object))
13
13
  end
14
14
 
15
- test 'conduct should pass with one Test::Unit assertion if delegator does its job' do
16
- delegator = Class.new do
17
- def foo; delegate.foo; end
18
- def delegate; nil; end
19
- end.new
20
- assertion = Assertion.new(mock(:assert_equal => nil))
21
- assertion.from(delegator).to(:delegate).for(:foo)
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
- # test 'should create expectations on mock_delegate and object under test upon conduct' do
26
- # cut = Class.new do
27
- # extend Forwardable
28
- # def_delegator :asdf, :meth
29
- # attr_reader :asdf
30
- # end
31
- # mock_delegate = mock
32
- # object_under_test = cut.new
33
- # assertion = Assertion.new(mock_delegate).from(object_under_test).to(:asdf).for_method(:meth)
34
- # assertion.conduct
35
- # assert_equal :asdf, object_under_test.mocha.expectations.first.method_name
36
- # assert_equal :meth, mock_delegate.expectations.last.method_name
37
- # end
38
- #
39
- # test 'should create mock_delegate expectation with arguments when supplied' do
40
- # delegator = Class.new do
41
- # extend Forwardable
42
- # def_delegator :delegate, :meth
43
- # attr_reader :delegate
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 'validates presence of delegator, delegate accessor, and delegating methods' do
84
- assertion = Assertion.new(mock).from(nil).to(:asdf).for_method(:meth)
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).from("whatever").to(nil).for_method(:meth)
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
@@ -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 'should conduct each assertion in conduct_and_clear_handoffs' do
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
@@ -7,4 +7,8 @@ class TestHelperTest < Test::Unit::TestCase
7
7
  assert_raises(Test::Unit::AssertionFailedError) { assert_true 'foo' }
8
8
  end
9
9
 
10
+ test "assert_false fails on nil" do
11
+ assert_raises(Test::Unit::AssertionFailedError) { assert_false nil }
12
+ end
13
+
10
14
  end
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.2.0
7
- date: 2007-05-18 00:00:00 -07:00
8
- summary: Handoff is a fluent interface for making test assertions about delegation.
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: []