handoff 0.0.1

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/README ADDED
@@ -0,0 +1,10 @@
1
+ Handoff provides a fluent interface for testing simple delegation. The Ruby
2
+ stdlib module +Forwardable+ makes implementing delegation simple and readable.
3
+ Handoff is intended to make the code to test it just as simple and
4
+ readable.
5
+
6
+ Handoff depends on Mocha and Stubba (http://mocha.rubyforge.org/).
7
+
8
+ Here's example_test.rb to give you an idea of what your tests will look like:
9
+
10
+ :include: test/example_test.rb
@@ -0,0 +1,20 @@
1
+ module Handoff
2
+ =begin rdoc
3
+ Module mixed into a *args array to munge it into a hash keying delegating
4
+ method names to target method names.
5
+ =end
6
+ module ArgumentNormalizer
7
+
8
+ def to_method_map
9
+ return self.first if self.size == 1 && self.first.is_a?(Hash)
10
+ to_self_referencing_hash
11
+ end
12
+
13
+ def to_self_referencing_hash
14
+ hash = Hash.new
15
+ self.each {|sym| hash[sym]=sym}
16
+ hash
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,70 @@
1
+ require 'handoff/argument_normalizer'
2
+
3
+ module Handoff
4
+ # This is where the fluent stuff is.
5
+ # Get an assertion by calling Handoff#assert_handoff. Specify the delegating
6
+ # behavior with from or from_any, to, and for_method or for_methods.
7
+ class Assertion
8
+
9
+ attr_reader :method_map
10
+ attr_reader :object_under_test
11
+ private :method_map, :object_under_test
12
+
13
+ # Creates an expectation on the mock delegate that it will be touched later
14
+ # to give a failure if the user forgets to specify everything required.
15
+ def initialize mock_delegate
16
+ @mock_delegate = mock_delegate
17
+ @mock_delegate.expects(:called!)
18
+ end
19
+
20
+ # Creates an instance of +class_under_test+ with no arguments and uses it
21
+ # as the object under test.
22
+ def from_any class_under_test
23
+ from(class_under_test.new)
24
+ end
25
+
26
+ # Specifies the object being tested, returning self.
27
+ def from object_under_test
28
+ @object_under_test = object_under_test
29
+ self
30
+ end
31
+
32
+ # Specifies the accessor the object under test will use to acquire its delegate,
33
+ # returning self.
34
+ def to(delegate_accessor)
35
+ @object_under_test.expects(delegate_accessor).at_least_once.returns(@mock_delegate)
36
+ self
37
+ end
38
+
39
+ # Tells the assertion what delegating methods to test and what methods in the delegate
40
+ # they should delegate to. Then actually does the testing.
41
+ #
42
+ # :call-seq: for_methods(:delegating_method1, :delegating_method2, ...)
43
+ # for_methods({:delegating_method1 => :target_method1, :delegating_method2 => :target_method2})
44
+ #
45
+ # +args+:: symbols representing the delegating methods if they are not renamed, or
46
+ # a Hash mapping methods in the delegating class to methods in the delegate.
47
+ def for_methods(*args)
48
+ @method_map = args.extend(ArgumentNormalizer).to_method_map
49
+ conduct
50
+ end
51
+ alias for_method for_methods
52
+
53
+ private
54
+ def conduct
55
+ @mock_delegate.called!
56
+ expected_returns = {}
57
+ method_map.each_pair do |delegating_method, target|
58
+ expected_returns[delegating_method] = "#{delegating_method.to_s}_return"
59
+ @mock_delegate.expects(target).returns(expected_returns[delegating_method])
60
+ end
61
+ method_map.each_pair do |delegating_method, target|
62
+ actual = object_under_test.send(delegating_method)
63
+ unless actual.equal? expected_returns[delegating_method]
64
+ raise "expected #{delegating_method.to_s} to return #{expected_returns[method]}, but was #{actual}"
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+ end
data/lib/handoff.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'handoff/assertion'
2
+ require 'test/unit'
3
+
4
+ # +require+ (or +require_gem+) 'handoff' and #assert_handoff can
5
+ # be called from any +Test::Unit::TestCase+ test method to create
6
+ # a new Handoff::Assertion.
7
+ #
8
+ # After defining Handoff, This file includes it in Test::Unit::TestCase.
9
+ module Handoff
10
+
11
+ # Creates an Assertion, handing a it a mock named 'handoff delegate' on which
12
+ # expectations will be set.
13
+ def assert_handoff
14
+ Handoff::Assertion.new(self.mock('handoff delegate'))
15
+ end
16
+ end
17
+
18
+ Test::Unit::TestCase.send :include, Handoff
@@ -0,0 +1,41 @@
1
+ # This example is only helpful if you're familiar with Forwardable from the
2
+ # stdlib, which you should be if you're coding delegating behavior in Ruby.
3
+ # Here comes an example of something you might have in your code base, but
4
+ # haven't managed to test readably. You might have some code like this that's
5
+ # tested in very long methods which either repeat but varying set-ups
6
+ # Foo is a simple delegating class, which normally wouldn't live in
7
+ # your test.
8
+ class Foo
9
+ require 'forwardable'
10
+ extend Forwardable
11
+ def_delegators :bar, :baz, :bat
12
+ def_delegator :bar, :baq, :bar_baq
13
+ def_delegator :bar, :ban, :bar_ban
14
+ def bar
15
+ @bar ||= BarFactory.create_for(Foo) # gets the delegate ... this is not what we're testing
16
+ end
17
+ end
18
+
19
+ require 'test/unit'
20
+ require 'rubygems'
21
+
22
+ require File.dirname(__FILE__) + '/../lib/handoff' # I require it this way because I don't want the installed gem.
23
+ # require 'handoff' # this is how you'd require handoff (or do require_gem w/ a version).
24
+
25
+ require 'mocha' # you need to require mocha and stubba in your test
26
+ require 'stubba' # ditto
27
+
28
+ class ExampleTest < Test::Unit::TestCase
29
+
30
+ def test_using_from_and_single_method
31
+ assert_handoff.from(Foo.new).to(:bar).for_method(:baz)
32
+ end
33
+
34
+ def test_using_from_any_and_multiple_methods
35
+ assert_handoff.from_any(Foo).to(:bar).for_methods(:baz, :bat)
36
+ end
37
+
38
+ def test_showing_delegating_methods_with_names_different_than_their_delegate_methods
39
+ assert_handoff.from(Foo.new).to(:bar).for_methods(:bar_baq => :baq, :bar_ban => :ban)
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/handoff/argument_normalizer'
3
+
4
+ module Handoff
5
+ class ArgumentNormalizerTest < Test::Unit::TestCase
6
+
7
+ def test_should_return_hash_at_front_of_one_element_array
8
+ hash = {}
9
+ assert_same hash, [hash].extend(ArgumentNormalizer).to_method_map
10
+ end
11
+
12
+ def test_should_return_self_referencing_hash_for_array_of_symbols
13
+ args = [:bar, :foo].extend(ArgumentNormalizer)
14
+ assert_equal({:foo => :foo, :bar => :bar}, args.to_method_map)
15
+ end
16
+
17
+ def test_should_return_self_referencing_hash_for_one_element_array_with_symbol
18
+ args = [:foo].extend(ArgumentNormalizer)
19
+ assert_equal({:foo => :foo}, args.to_method_map)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+ require File.dirname(__FILE__) + '/../../lib/handoff/assertion'
4
+ require 'rubygems'
5
+ require 'mocha'
6
+ require 'stubba'
7
+
8
+ module Handoff
9
+ class AssertionTest < Test::Unit::TestCase
10
+
11
+ test 'should construct instance to test and return self when from_any is called' do
12
+ mock_class = mock(:new => nil)
13
+ mock_delegate = mock
14
+ assertion = Assertion.new(mock_delegate)
15
+ mock_delegate.expectations.clear
16
+ assert_same assertion, assertion.from_any(mock_class)
17
+ end
18
+
19
+ test 'should create expectation on creation to guard against incomplete usage' do
20
+ mock_delegate = mock
21
+ Assertion.new(mock_delegate)
22
+ assert_equal :called!, mock_delegate.expectations.first.method_name
23
+ mock_delegate.expectations.clear
24
+ end
25
+
26
+ test 'should create expectations on mock_delegate and object under test once fully specified' do
27
+ cut = define_class(Object, <<-EOS)
28
+ extend Forwardable
29
+ def_delegator :asdf, :meth
30
+ attr_reader :asdf
31
+ EOS
32
+ mock_delegate = mock
33
+ object_under_test = cut.new
34
+ Assertion.new(mock_delegate).from(object_under_test).to(:asdf).for_method(:meth)
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
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'rubygems'
3
+ require 'mocha'
4
+ require 'stubba'
5
+ require File.dirname(__FILE__) + '/../lib/handoff'
6
+
7
+ class HandoffTest < Test::Unit::TestCase
8
+ test 'should create a mock named "handoff delegate" and hand it to a new Assertion' do
9
+ given_name = nil
10
+ def self.mock name
11
+ assert_equal 'handoff delegate', name
12
+ :mock_return
13
+ end
14
+ Assertion.expects(:new).with(:mock_return).returns(:new_assertion)
15
+ assert_equal :new_assertion, assert_handoff
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: handoff
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-01-17 00:00:00 -05:00
8
+ summary: Handoff is a fluent interface for making test assertions about simple delegation.
9
+ require_paths:
10
+ - lib
11
+ email: ""
12
+ homepage: http://handoff.rubyforge.org/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: hand_off
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - John Hume
31
+ files:
32
+ - lib/handoff
33
+ - lib/handoff.rb
34
+ - lib/handoff/argument_normalizer.rb
35
+ - lib/handoff/assertion.rb
36
+ - README
37
+ test_files:
38
+ - test/example_test.rb
39
+ - test/handoff_test.rb
40
+ - test/handoff/argument_normalizer_test.rb
41
+ - test/handoff/assertion_test.rb
42
+ rdoc_options: []
43
+
44
+ extra_rdoc_files:
45
+ - README
46
+ executables: []
47
+
48
+ extensions: []
49
+
50
+ requirements: []
51
+
52
+ dependencies:
53
+ - !ruby/object:Gem::Dependency
54
+ name: mocha
55
+ version_requirement:
56
+ version_requirements: !ruby/object:Gem::Version::Requirement
57
+ requirements:
58
+ - - ">"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.0.0
61
+ version: