hardmock 1.3.5 → 1.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +5 -0
- data/Rakefile +1 -1
- data/lib/extend_test_unit.rb +14 -0
- data/lib/hardmock.rb +1 -91
- data/lib/test_unit_before_after.rb +170 -0
- data/test/functional/auto_verify_test.rb +16 -30
- data/test/test_helper.rb +0 -3
- data/test/unit/test_unit_before_after_test.rb +452 -0
- metadata +56 -45
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
Hardmock 1.3.6
|
2
|
+
|
3
|
+
* BUG FIX: In Rails apps (and others) Hardmock and Fixtures battled viciously over "setup" and "teardown" and "method_added" (and any other clever test enhancement tool, namely Mocha) causing unpredictable results, notably failure to auto-verify mocks after teardown (leading to false positive tests).
|
4
|
+
** The newly-added TestUnitBeforeAfter provides TestCase.before_setup and TestCase.after_teardown -- formal test wrapping hooks -- lets Hardmock provide its preparation and auto-verify behavior without contending for setup/teardown supremacy.
|
5
|
+
|
1
6
|
Hardmock 1.3.5
|
2
7
|
|
3
8
|
* Aliased should_receive => expects and and_return => returns for easier transition from rspec mock and flexmock users.
|
data/Rakefile
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
require 'test/unit/testcase'
|
3
|
+
class Test::Unit::TestCase
|
4
|
+
include Hardmock
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'test_unit_before_after'
|
8
|
+
Test::Unit::TestCase.before_setup do |test|
|
9
|
+
test.prepare_hardmock_control
|
10
|
+
end
|
11
|
+
|
12
|
+
Test::Unit::TestCase.after_teardown do |test|
|
13
|
+
test.verify_mocks
|
14
|
+
end
|
data/lib/hardmock.rb
CHANGED
@@ -9,92 +9,8 @@ require 'hardmock/expectation'
|
|
9
9
|
require 'hardmock/expectation_builder'
|
10
10
|
require 'hardmock/stubbing'
|
11
11
|
|
12
|
-
|
13
12
|
module Hardmock
|
14
13
|
|
15
|
-
# Setup auto mock verification on teardown, being careful not to interfere
|
16
|
-
# with inherited, pre-mixed or post-added user teardowns.
|
17
|
-
def self.included(base) #:nodoc:#
|
18
|
-
base.class_eval do
|
19
|
-
# Core of our actual setup behavior
|
20
|
-
def hardmock_setup
|
21
|
-
prepare_hardmock_control
|
22
|
-
end
|
23
|
-
|
24
|
-
# Core of our actual teardown behavior
|
25
|
-
def hardmock_teardown
|
26
|
-
verify_mocks
|
27
|
-
end
|
28
|
-
|
29
|
-
# disable until later:
|
30
|
-
def self.method_added(symbol) #:nodoc:
|
31
|
-
end
|
32
|
-
|
33
|
-
if method_defined?(:setup) then
|
34
|
-
# Wrap existing setup
|
35
|
-
alias_method :old_setup, :setup
|
36
|
-
define_method(:new_setup) do
|
37
|
-
begin
|
38
|
-
hardmock_setup
|
39
|
-
ensure
|
40
|
-
old_setup
|
41
|
-
end
|
42
|
-
end
|
43
|
-
else
|
44
|
-
# We don't need to account for previous setup
|
45
|
-
define_method(:new_setup) do
|
46
|
-
hardmock_setup
|
47
|
-
end
|
48
|
-
end
|
49
|
-
alias_method :setup, :new_setup
|
50
|
-
|
51
|
-
if method_defined?(:teardown) then
|
52
|
-
# Wrap existing teardown
|
53
|
-
alias_method :old_teardown, :teardown
|
54
|
-
define_method(:new_teardown) do
|
55
|
-
begin
|
56
|
-
hardmock_teardown
|
57
|
-
ensure
|
58
|
-
old_teardown
|
59
|
-
end
|
60
|
-
end
|
61
|
-
else
|
62
|
-
# We don't need to account for previous teardown
|
63
|
-
define_method(:new_teardown) do
|
64
|
-
hardmock_teardown
|
65
|
-
end
|
66
|
-
end
|
67
|
-
alias_method :teardown, :new_teardown
|
68
|
-
|
69
|
-
def self.method_added(method) #:nodoc:
|
70
|
-
case method
|
71
|
-
when :teardown
|
72
|
-
unless method_defined?(:user_teardown)
|
73
|
-
alias_method :user_teardown, :teardown
|
74
|
-
define_method(:teardown) do
|
75
|
-
begin
|
76
|
-
new_teardown
|
77
|
-
ensure
|
78
|
-
user_teardown
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
when :setup
|
83
|
-
unless method_defined?(:user_setup)
|
84
|
-
alias_method :user_setup, :setup
|
85
|
-
define_method(:setup) do
|
86
|
-
begin
|
87
|
-
new_setup
|
88
|
-
ensure
|
89
|
-
user_setup
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
14
|
# Create one or more new Mock instances in your test suite.
|
99
15
|
# Once created, the Mocks are accessible as instance variables in your test.
|
100
16
|
# Newly built Mocks are added to the full set of Mocks for this test, which will
|
@@ -167,10 +83,4 @@ module Hardmock
|
|
167
83
|
|
168
84
|
end
|
169
85
|
|
170
|
-
|
171
|
-
require 'test/unit/testcase'
|
172
|
-
unless Test::Unit::TestCase.instance_methods.include?('hardmock_teardown')
|
173
|
-
class Test::Unit::TestCase #:nodoc:#
|
174
|
-
include Hardmock
|
175
|
-
end
|
176
|
-
end
|
86
|
+
require 'extend_test_unit'
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/testcase'
|
3
|
+
require 'test/unit/assertions'
|
4
|
+
|
5
|
+
module Test #:nodoc:#
|
6
|
+
module Unit #:nodoc:#
|
7
|
+
|
8
|
+
# == TestCase Modifications
|
9
|
+
#
|
10
|
+
# Monkey-patch to provide a formal mechanism for appending actions to be executed after teardown.
|
11
|
+
# Use after_teardown to define one or more actions to be executed after teardown for ALL tests.
|
12
|
+
#
|
13
|
+
# COMING SOON?
|
14
|
+
# * Hook for running actions prior to setup
|
15
|
+
# * Hooks for before_teardown, after_setup, on_error
|
16
|
+
# * Options for positional control, eg, after_teardown :before_other_actions
|
17
|
+
# * Provide tagging/filtering so action execution can be controlled specifically?
|
18
|
+
#
|
19
|
+
# == Usage
|
20
|
+
#
|
21
|
+
# Invoke TestCase.after_teardown with optional parameter, which will be invoked with a reference
|
22
|
+
# to the test instance that has just been torn down.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
#
|
26
|
+
# Test::Unit::TestCase.after_teardown do |test|
|
27
|
+
# test.verify_mocks
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# == Justification
|
31
|
+
#
|
32
|
+
# There are a number of tools and libraries that play fast-n-loose with setup and teardown by
|
33
|
+
# wrapping them, and by overriding method_added as a means of upholding special setup/teardown
|
34
|
+
# behavior, usually by re-wrapping newly defined user-level setup/teardown methods.
|
35
|
+
# mocha and active_record/fixtures (and previously, hardmock) will fight for this
|
36
|
+
# territory with often unpredictable results.
|
37
|
+
#
|
38
|
+
# We wouldn't have to battle if Test::Unit provided a formal pre- and post- hook mechanism.
|
39
|
+
#
|
40
|
+
class TestCase
|
41
|
+
|
42
|
+
class << self
|
43
|
+
|
44
|
+
# Define an action to be run after teardown. Subsequent calls result in
|
45
|
+
# multiple actions. The block will be given a reference to the test
|
46
|
+
# being executed.
|
47
|
+
#
|
48
|
+
# Example:
|
49
|
+
#
|
50
|
+
# Test::Unit::TestCase.after_teardown do |test|
|
51
|
+
# test.verify_mocks
|
52
|
+
# end
|
53
|
+
def after_teardown(&block)
|
54
|
+
post_teardown_actions << block
|
55
|
+
end
|
56
|
+
|
57
|
+
# Used internally. Access the list of post teardown actions for to be
|
58
|
+
# used by all tests.
|
59
|
+
def post_teardown_actions
|
60
|
+
@@post_teardown_actions ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
# Define an action to be run before setup. Subsequent calls result in
|
64
|
+
# multiple actions, EACH BEING PREPENDED TO THE PREVIOUS.
|
65
|
+
# The block will be given a reference to the test being executed.
|
66
|
+
#
|
67
|
+
# Example:
|
68
|
+
#
|
69
|
+
# Test::Unit::TestCase.before_setup do |test|
|
70
|
+
# test.prepare_hardmock_control
|
71
|
+
# end
|
72
|
+
def before_setup(&block)
|
73
|
+
pre_setup_actions.unshift block
|
74
|
+
end
|
75
|
+
|
76
|
+
# Used internally. Access the list of post teardown actions for to be
|
77
|
+
# used by all tests.
|
78
|
+
def pre_setup_actions
|
79
|
+
@@pre_setup_actions ||= []
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# OVERRIDE: This is a reimplementation of the default "run", updated to
|
84
|
+
# execute actions after teardown.
|
85
|
+
def run(result)
|
86
|
+
yield(STARTED, name)
|
87
|
+
@_result = result
|
88
|
+
begin
|
89
|
+
execute_pre_setup_actions(self)
|
90
|
+
setup
|
91
|
+
__send__(@method_name)
|
92
|
+
rescue Test::Unit::AssertionFailedError => e
|
93
|
+
add_failure(e.message, auxiliary_backtrace_filter(e.backtrace))
|
94
|
+
rescue Exception
|
95
|
+
raise if should_passthru_exception($!) # See implementation; this is for pre-1.8.6 compat
|
96
|
+
add_error($!)
|
97
|
+
ensure
|
98
|
+
begin
|
99
|
+
teardown
|
100
|
+
rescue Test::Unit::AssertionFailedError => e
|
101
|
+
add_failure(e.message, auxiliary_backtrace_filter(e.backtrace))
|
102
|
+
rescue Exception
|
103
|
+
raise if should_passthru_exception($!) # See implementation; this is for pre-1.8.6 compat
|
104
|
+
add_error($!)
|
105
|
+
ensure
|
106
|
+
execute_post_teardown_actions(self)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
result.add_run
|
110
|
+
yield(FINISHED, name)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
# Run through the after_teardown actions, treating failures and errors
|
116
|
+
# in the same way that "run" does: they are reported, and the remaining
|
117
|
+
# actions are executed.
|
118
|
+
def execute_post_teardown_actions(test_instance)
|
119
|
+
self.class.post_teardown_actions.each do |action|
|
120
|
+
begin
|
121
|
+
action.call test_instance
|
122
|
+
rescue Test::Unit::AssertionFailedError => e
|
123
|
+
add_failure(e.message, auxiliary_backtrace_filter(e.backtrace))
|
124
|
+
rescue Exception
|
125
|
+
raise if should_passthru_exception($!)
|
126
|
+
add_error($!)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Run through the before_setup actions.
|
132
|
+
# Failures or errors cause execution to stop.
|
133
|
+
def execute_pre_setup_actions(test_instance)
|
134
|
+
self.class.pre_setup_actions.each do |action|
|
135
|
+
# begin
|
136
|
+
action.call test_instance
|
137
|
+
# rescue Test::Unit::AssertionFailedError => e
|
138
|
+
# add_failure(e.message, auxiliary_backtrace_filter(e.backtrace))
|
139
|
+
# rescue Exception
|
140
|
+
# raise if should_passthru_exception($!)
|
141
|
+
# add_error($!)
|
142
|
+
# end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Make sure that this extension doesn't show up in failure backtraces
|
147
|
+
def auxiliary_backtrace_filter(trace)
|
148
|
+
trace.reject { |x| x =~ /test_unit_before_after/ }
|
149
|
+
end
|
150
|
+
|
151
|
+
# Is the given error of the type that we allow to fly out (rather than catching it)?
|
152
|
+
def should_passthru_exception(ex)
|
153
|
+
return passthrough_exception_types.include?($!.class)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Provide a list of exception types that are to be allowed to explode out.
|
157
|
+
# Pre-ruby-1.8.6 doesn't use this functionality, so the PASSTHROUGH_EXCEPTIONS
|
158
|
+
# constant won't be defined. This methods defends against that and returns
|
159
|
+
# an empty list instead.
|
160
|
+
def passthrough_exception_types
|
161
|
+
begin
|
162
|
+
return PASSTHROUGH_EXCEPTIONS
|
163
|
+
rescue NameError
|
164
|
+
# older versions of test/unit do not have PASSTHROUGH_EXCEPTIONS constant
|
165
|
+
return []
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -51,7 +51,6 @@ class AutoVerifyTest < Test::Unit::TestCase
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it "is quiet when verification is ok" do
|
54
|
-
# def test_should_not_raise_error_if_verification_goes_according_to_plan
|
55
54
|
@test_code =<<-EOM
|
56
55
|
def test_ok
|
57
56
|
create_mock :automobile
|
@@ -71,14 +70,13 @@ class AutoVerifyTest < Test::Unit::TestCase
|
|
71
70
|
assert_output_contains(/User teardown/)
|
72
71
|
end
|
73
72
|
|
74
|
-
should "
|
75
|
-
# def test_should_not_do_verification_if_user_teardown_explodes
|
73
|
+
should "auto-verify even if user teardown explodes" do
|
76
74
|
@teardown_code =<<-EOM
|
77
75
|
def teardown
|
78
76
|
raise "self destruct"
|
79
77
|
end
|
80
78
|
EOM
|
81
|
-
@
|
79
|
+
@expect_errors = 2
|
82
80
|
write_and_execute_test
|
83
81
|
assert_output_contains(/self destruct/)
|
84
82
|
end
|
@@ -103,29 +101,6 @@ class AutoVerifyTest < Test::Unit::TestCase
|
|
103
101
|
assert_output_contains(/Test helper teardown/)
|
104
102
|
end
|
105
103
|
|
106
|
-
it "plays nice with inherited and user-defined teardowns at the same time" do
|
107
|
-
@full_code ||=<<-EOTEST
|
108
|
-
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
109
|
-
class Test::Unit::TestCase
|
110
|
-
def teardown
|
111
|
-
puts "Test helper teardown"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
require 'hardmock' # IMPORTANT TO DO THIS HERE, between the old and new teardown defs
|
115
|
-
class DummyTest < Test::Unit::TestCase
|
116
|
-
def teardown
|
117
|
-
puts "User teardown"
|
118
|
-
end
|
119
|
-
def test_prepare_to_die
|
120
|
-
create_mock :automobile
|
121
|
-
@automobile.expects.start
|
122
|
-
end
|
123
|
-
end
|
124
|
-
EOTEST
|
125
|
-
write_and_execute_test
|
126
|
-
assert_output_contains(/Test helper teardown/, /User teardown/)
|
127
|
-
end
|
128
|
-
|
129
104
|
#
|
130
105
|
# HELPERS
|
131
106
|
#
|
@@ -139,18 +114,29 @@ class AutoVerifyTest < Test::Unit::TestCase
|
|
139
114
|
@test_output = `ruby #{temp_test_file} 2>&1`
|
140
115
|
end
|
141
116
|
|
117
|
+
def formatted_test_output
|
118
|
+
if @test_output
|
119
|
+
@test_output.split(/\n/).map { |line| "> #{line}" }.join("\n")
|
120
|
+
else
|
121
|
+
"(NO TEST OUTPUT!)"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
142
125
|
def remove_temp_test_file
|
143
126
|
FileUtils::rm_f temp_test_file
|
144
127
|
end
|
145
128
|
|
146
129
|
def assert_results(h)
|
147
|
-
|
148
|
-
|
130
|
+
if @test_output !~ /#{h[:tests]} tests, [0-9]+ assertions, #{h[:failures]} failures, #{h[:errors]} errors/
|
131
|
+
flunk "Test results didn't match #{h.inspect}:\n#{formatted_test_output}"
|
132
|
+
end
|
149
133
|
end
|
150
134
|
|
151
135
|
def assert_output_contains(*patterns)
|
152
136
|
patterns.each do |pattern|
|
153
|
-
|
137
|
+
if @test_output !~ pattern
|
138
|
+
flunk "Test output didn't match #{pattern.inspect}:\n#{formatted_test_output}"
|
139
|
+
end
|
154
140
|
end
|
155
141
|
end
|
156
142
|
|
data/test/test_helper.rb
CHANGED
@@ -33,9 +33,6 @@ class Test::Unit::TestCase
|
|
33
33
|
tname = self.name.sub(/Test$/,'')
|
34
34
|
if block
|
35
35
|
define_method "test #{prefix} #{str}" do
|
36
|
-
# phrase = str
|
37
|
-
# phrase = prefix + " " + phrase unless prefix == "it"
|
38
|
-
# puts "#{tname} #{phrase}..."
|
39
36
|
instance_eval &block
|
40
37
|
end
|
41
38
|
else
|
@@ -0,0 +1,452 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
2
|
+
|
3
|
+
class TestUnitBeforeAfter < Test::Unit::TestCase
|
4
|
+
|
5
|
+
#
|
6
|
+
# after_teardown
|
7
|
+
#
|
8
|
+
|
9
|
+
it "adds TestCase.after_teardown hook for appending post-teardown actions" do
|
10
|
+
write_and_run_test :use_after_teardown => true
|
11
|
+
|
12
|
+
see_in_order "Loaded suite",
|
13
|
+
"THE SETUP",
|
14
|
+
"A TEST",
|
15
|
+
"THE TEARDOWN",
|
16
|
+
"1st after_teardown",
|
17
|
+
"2nd after_teardown",
|
18
|
+
"Finished in"
|
19
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 0
|
20
|
+
end
|
21
|
+
|
22
|
+
should "execute all after_teardowns, even if the main teardown flunks" do
|
23
|
+
write_and_run_test :use_after_teardown => true, :flunk_in_teardown => true
|
24
|
+
see_in_order "Loaded suite",
|
25
|
+
"THE SETUP",
|
26
|
+
"A TEST",
|
27
|
+
"F",
|
28
|
+
"1st after_teardown",
|
29
|
+
"2nd after_teardown",
|
30
|
+
"Finished in",
|
31
|
+
"1) Failure:",
|
32
|
+
"test_something(MyExampleTest) [_test_file_temp.rb:20]:",
|
33
|
+
"FLUNK IN TEARDOWN"
|
34
|
+
see_results :tests => 1, :assertions => 1, :failures => 1, :errors => 0
|
35
|
+
end
|
36
|
+
|
37
|
+
should "execute all after_teardowns, even if the main teardown explodes" do
|
38
|
+
write_and_run_test :use_after_teardown => true, :raise_in_teardown => true
|
39
|
+
see_in_order "Loaded suite",
|
40
|
+
"THE SETUP",
|
41
|
+
"A TEST",
|
42
|
+
"E",
|
43
|
+
"1st after_teardown",
|
44
|
+
"2nd after_teardown",
|
45
|
+
"Finished in",
|
46
|
+
"RuntimeError: ERROR IN TEARDOWN"
|
47
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 1
|
48
|
+
end
|
49
|
+
|
50
|
+
should "execute all after_teardowns, even if some of them flunk" do
|
51
|
+
write_and_run_test :use_after_teardown => true, :flunk_in_after_teardown => true
|
52
|
+
see_in_order "Loaded suite",
|
53
|
+
"THE SETUP",
|
54
|
+
"A TEST",
|
55
|
+
"THE TEARDOWN",
|
56
|
+
"1st after_teardown",
|
57
|
+
"F",
|
58
|
+
"2nd after_teardown",
|
59
|
+
"Finished in",
|
60
|
+
"1) Failure:",
|
61
|
+
"test_something(MyExampleTest) [_test_file_temp.rb:7]:",
|
62
|
+
"Flunk in first after_teardown",
|
63
|
+
"2) Failure:",
|
64
|
+
"test_something(MyExampleTest) [_test_file_temp.rb:10]:",
|
65
|
+
"Flunk in second after_teardown"
|
66
|
+
see_results :tests => 1, :assertions => 2, :failures => 2, :errors => 0
|
67
|
+
end
|
68
|
+
|
69
|
+
should "execute all after_teardowns, even if some of them explode" do
|
70
|
+
write_and_run_test :use_after_teardown => true, :raise_in_after_teardown => true
|
71
|
+
see_in_order "Loaded suite",
|
72
|
+
"THE SETUP",
|
73
|
+
"A TEST",
|
74
|
+
"THE TEARDOWN",
|
75
|
+
"1st after_teardown",
|
76
|
+
"E",
|
77
|
+
"2nd after_teardown",
|
78
|
+
"Finished in",
|
79
|
+
"RuntimeError: Error in first after_teardown",
|
80
|
+
"RuntimeError: Error in second after_teardown"
|
81
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 2
|
82
|
+
end
|
83
|
+
|
84
|
+
it "will run after_teardowns in the absence of a regular teardown" do
|
85
|
+
write_and_run_test :omit_teardown => true, :use_after_teardown => true
|
86
|
+
see_in_order "Loaded suite",
|
87
|
+
"THE SETUP",
|
88
|
+
"A TEST",
|
89
|
+
"1st after_teardown",
|
90
|
+
"2nd after_teardown",
|
91
|
+
"Finished in"
|
92
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 0
|
93
|
+
end
|
94
|
+
|
95
|
+
should "not interfere with normal test writing" do
|
96
|
+
write_and_run_test
|
97
|
+
see_in_order "Loaded suite",
|
98
|
+
"THE SETUP",
|
99
|
+
"A TEST",
|
100
|
+
"THE TEARDOWN",
|
101
|
+
"Finished in"
|
102
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 0
|
103
|
+
end
|
104
|
+
|
105
|
+
it "provides a cleaned-up backtrace" do
|
106
|
+
write_and_run_test :with_failure => true
|
107
|
+
see_in_order "Loaded suite",
|
108
|
+
"THE SETUP",
|
109
|
+
"A FAILING TEST",
|
110
|
+
"F", "THE TEARDOWN",
|
111
|
+
"Finished in",
|
112
|
+
"1) Failure:",
|
113
|
+
"test_something(MyExampleTest) [_test_file_temp.rb:17]:",
|
114
|
+
"Instrumented failure.",
|
115
|
+
"<false> is not true."
|
116
|
+
see_results :tests => 1, :assertions => 1, :failures => 1, :errors => 0
|
117
|
+
end
|
118
|
+
|
119
|
+
it "provides a cleaned-up backtrace, but not TOO cleaned up" do
|
120
|
+
write_and_run_test :with_failure => true, :use_helpers => true
|
121
|
+
see_in_order "Loaded suite",
|
122
|
+
"THE SETUP",
|
123
|
+
"A FAILING TEST",
|
124
|
+
"F", "THE TEARDOWN",
|
125
|
+
"Finished in",
|
126
|
+
"1) Failure:",
|
127
|
+
"test_something(MyExampleTest)\n",
|
128
|
+
"[_test_file_temp.rb:25:in `tripwire'",
|
129
|
+
"_test_file_temp.rb:21:in `my_helper'",
|
130
|
+
"_test_file_temp.rb:17:in `test_something']:",
|
131
|
+
"Instrumented failure.",
|
132
|
+
"<false> is not true."
|
133
|
+
see_results :tests => 1, :assertions => 1, :failures => 1, :errors => 0
|
134
|
+
end
|
135
|
+
|
136
|
+
should "not interfere with passthrough exception types" do
|
137
|
+
if is_modern_test_unit?
|
138
|
+
write_and_run_test :raise_nasty_in_test => true
|
139
|
+
see_in_no_particular_order "Loaded suite",
|
140
|
+
"THE TEARDOWN",
|
141
|
+
"_test_file_temp.rb:16:in `test_something': NASTY ERROR (NoMemoryError)"
|
142
|
+
see_no_results
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# before_setup
|
148
|
+
#
|
149
|
+
|
150
|
+
it "adds TestCase.before_setup hook for prepending pre-setup actions" do
|
151
|
+
write_and_run_test :use_before_setup => true
|
152
|
+
see_in_order "Loaded suite",
|
153
|
+
"3rd before_setup",
|
154
|
+
"2nd before_setup",
|
155
|
+
"1st before_setup",
|
156
|
+
"THE SETUP",
|
157
|
+
"A TEST",
|
158
|
+
"THE TEARDOWN",
|
159
|
+
"Finished in"
|
160
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 0
|
161
|
+
end
|
162
|
+
|
163
|
+
should "stop executing the test on the first failure withing a before_setup action" do
|
164
|
+
write_and_run_test :use_before_setup => true, :flunk_in_before_setup => true
|
165
|
+
see_in_order "Loaded suite",
|
166
|
+
"3rd before_setup",
|
167
|
+
"2nd before_setup",
|
168
|
+
"FTHE TEARDOWN",
|
169
|
+
"1) Failure:",
|
170
|
+
"test_something(MyExampleTest) [_test_file_temp.rb:10]:",
|
171
|
+
"Flunk in 2nd before_setup."
|
172
|
+
see_results :tests => 1, :assertions => 1, :failures => 1, :errors => 0
|
173
|
+
end
|
174
|
+
|
175
|
+
should "stop executing the test on the first error within a before_setup action" do
|
176
|
+
write_and_run_test :use_before_setup => true, :raise_in_before_setup => true
|
177
|
+
see_in_order "Loaded suite",
|
178
|
+
"3rd before_setup",
|
179
|
+
"2nd before_setup",
|
180
|
+
"ETHE TEARDOWN",
|
181
|
+
"Finished in",
|
182
|
+
"test_something(MyExampleTest):",
|
183
|
+
"RuntimeError: Error in 2nd before_setup",
|
184
|
+
"_test_file_temp.rb:10",
|
185
|
+
"/hardmock/lib/test_unit_before_after.rb:136:in `call'"
|
186
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 1
|
187
|
+
end
|
188
|
+
|
189
|
+
it "will run before_setup actions in the absence of a regular setup" do
|
190
|
+
write_and_run_test :omit_setup => true, :use_before_setup => true
|
191
|
+
see_in_order "Loaded suite",
|
192
|
+
"3rd before_setup",
|
193
|
+
"2nd before_setup",
|
194
|
+
"1st before_setup",
|
195
|
+
"A TEST",
|
196
|
+
"THE TEARDOWN",
|
197
|
+
"Finished in"
|
198
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 0
|
199
|
+
end
|
200
|
+
|
201
|
+
it "allows before_setup and after_teardown to be used at the same time" do
|
202
|
+
write_and_run_test :use_before_setup => true, :use_after_teardown => true
|
203
|
+
see_in_order "Loaded suite",
|
204
|
+
"3rd before_setup",
|
205
|
+
"2nd before_setup",
|
206
|
+
"1st before_setup",
|
207
|
+
"A TEST",
|
208
|
+
"THE TEARDOWN",
|
209
|
+
"1st after_teardown",
|
210
|
+
"2nd after_teardown",
|
211
|
+
"Finished in"
|
212
|
+
see_results :tests => 1, :assertions => 0, :failures => 0, :errors => 0
|
213
|
+
end
|
214
|
+
|
215
|
+
#
|
216
|
+
# HELPERS
|
217
|
+
#
|
218
|
+
|
219
|
+
def teardown
|
220
|
+
remove_test
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_filename
|
224
|
+
"_test_file_temp.rb"
|
225
|
+
end
|
226
|
+
|
227
|
+
def remove_test
|
228
|
+
rm_f test_filename
|
229
|
+
end
|
230
|
+
|
231
|
+
def write_and_run_test(opts={})
|
232
|
+
write(test_filename, generate_test_code(opts))
|
233
|
+
run_test
|
234
|
+
end
|
235
|
+
|
236
|
+
def run_test
|
237
|
+
@output = `ruby #{test_filename} 2>&1`
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
def write(fname, code)
|
242
|
+
File.open(fname,"w") do |f|
|
243
|
+
f.print code
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def show_output
|
248
|
+
puts "-- BEGIN TEST OUTPUT"
|
249
|
+
puts @output
|
250
|
+
puts "-- END TEST OUTPUT"
|
251
|
+
end
|
252
|
+
|
253
|
+
def see_in_order(*phrases)
|
254
|
+
idx = 0
|
255
|
+
phrases.each do |txt|
|
256
|
+
idx = @output.index(txt, idx)
|
257
|
+
if idx.nil?
|
258
|
+
if @output.index(txt)
|
259
|
+
flunk "Phrase '#{txt}' is out-of-order in test output:\n#{@output}"
|
260
|
+
else
|
261
|
+
flunk "Phrase '#{txt}' not found in test output:\n#{@output}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def see_in_no_particular_order(*phrases)
|
268
|
+
phrases.each do |txt|
|
269
|
+
assert_not_nil @output.index(txt), "Didn't see '#{txt}' in test output:\n#{@output}"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def see_results(opts)
|
274
|
+
if @output =~ /(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/
|
275
|
+
tests, assertions, failures, errors = [ $1, $2, $3, $4 ]
|
276
|
+
[:tests, :assertions, :failures, :errors].each do |key|
|
277
|
+
eval %{assert_equal(opts[:#{key}].to_s, #{key}, "Wrong number of #{key} in report") if opts[:#{key}]}
|
278
|
+
end
|
279
|
+
else
|
280
|
+
flunk "Didn't see the test results report line"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def see_no_results
|
285
|
+
if @output =~ /\d+ tests, \d+ assertions, \d+ failures, \d+ errors/
|
286
|
+
flunk "Should not have had a results line:\n#{@output}"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def lib_dir
|
291
|
+
File.expand_path(File.dirname(__FILE__) + "/../../lib")
|
292
|
+
end
|
293
|
+
|
294
|
+
def generate_test_code(opts={})
|
295
|
+
|
296
|
+
if opts[:with_failure] or opts[:raise_nasty_in_test]
|
297
|
+
test_method_code = generate_failing_test("test_something", opts)
|
298
|
+
else
|
299
|
+
test_method_code = generate_passing_test("test_something")
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
requires_for_ext = ''
|
304
|
+
if opts[:use_before_setup] or opts[:use_after_teardown]
|
305
|
+
requires_for_ext =<<-RFE
|
306
|
+
$: << "#{lib_dir}"
|
307
|
+
require 'test_unit_before_after'
|
308
|
+
RFE
|
309
|
+
end
|
310
|
+
|
311
|
+
before_setups = ''
|
312
|
+
if opts[:use_before_setup]
|
313
|
+
add_on_two = ""
|
314
|
+
if opts[:flunk_in_before_setup]
|
315
|
+
add_on_two = %{; test.flunk "Flunk in 2nd before_setup"}
|
316
|
+
elsif opts[:raise_in_before_setup]
|
317
|
+
add_on_two = %{; raise "Error in 2nd before_setup"}
|
318
|
+
end
|
319
|
+
before_setups =<<-BSTS
|
320
|
+
Test::Unit::TestCase.before_setup do |test|
|
321
|
+
puts "1st before_setup"
|
322
|
+
end
|
323
|
+
Test::Unit::TestCase.before_setup do |test|
|
324
|
+
puts "2nd before_setup" #{add_on_two}
|
325
|
+
end
|
326
|
+
Test::Unit::TestCase.before_setup do |test|
|
327
|
+
puts "3rd before_setup"
|
328
|
+
end
|
329
|
+
|
330
|
+
BSTS
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
setup_code =<<-SC
|
335
|
+
def setup
|
336
|
+
puts "THE SETUP"
|
337
|
+
end
|
338
|
+
SC
|
339
|
+
if opts[:omit_setup]
|
340
|
+
setup_code = ""
|
341
|
+
end
|
342
|
+
|
343
|
+
after_teardowns = ''
|
344
|
+
if opts[:use_after_teardown]
|
345
|
+
add_on_one = ""
|
346
|
+
add_on_two = ""
|
347
|
+
if opts[:flunk_in_after_teardown]
|
348
|
+
add_on_one = %{; test.flunk "Flunk in first after_teardown"}
|
349
|
+
add_on_two = %{; test.flunk "Flunk in second after_teardown"}
|
350
|
+
elsif opts[:raise_in_after_teardown]
|
351
|
+
add_on_one = %{; raise "Error in first after_teardown"}
|
352
|
+
add_on_two = %{; raise "Error in second after_teardown"}
|
353
|
+
end
|
354
|
+
after_teardowns =<<-ATDS
|
355
|
+
Test::Unit::TestCase.after_teardown do |test|
|
356
|
+
puts "1st after_teardown" #{add_on_one}
|
357
|
+
end
|
358
|
+
Test::Unit::TestCase.after_teardown do |test|
|
359
|
+
puts "2nd after_teardown" #{add_on_two}
|
360
|
+
end
|
361
|
+
ATDS
|
362
|
+
end
|
363
|
+
|
364
|
+
teardown_code =<<-TDC
|
365
|
+
def teardown
|
366
|
+
puts "THE TEARDOWN"
|
367
|
+
end
|
368
|
+
TDC
|
369
|
+
if opts[:flunk_in_teardown]
|
370
|
+
teardown_code =<<-TDC
|
371
|
+
def teardown
|
372
|
+
flunk "FLUNK IN TEARDOWN"
|
373
|
+
end
|
374
|
+
TDC
|
375
|
+
elsif opts[:raise_in_teardown]
|
376
|
+
teardown_code =<<-TDC
|
377
|
+
def teardown
|
378
|
+
raise "ERROR IN TEARDOWN"
|
379
|
+
end
|
380
|
+
TDC
|
381
|
+
end
|
382
|
+
if opts[:omit_teardown]
|
383
|
+
teardown_code = ""
|
384
|
+
end
|
385
|
+
|
386
|
+
str = <<-TCODE
|
387
|
+
require 'test/unit'
|
388
|
+
#{requires_for_ext}
|
389
|
+
|
390
|
+
#{before_setups} #{after_teardowns}
|
391
|
+
|
392
|
+
class MyExampleTest < Test::Unit::TestCase
|
393
|
+
#{setup_code}
|
394
|
+
#{teardown_code}
|
395
|
+
#{test_method_code}
|
396
|
+
end
|
397
|
+
TCODE
|
398
|
+
end
|
399
|
+
|
400
|
+
def generate_passing_test(tname)
|
401
|
+
str = <<-TMETH
|
402
|
+
def #{tname}
|
403
|
+
puts "A TEST"
|
404
|
+
end
|
405
|
+
TMETH
|
406
|
+
end
|
407
|
+
|
408
|
+
def generate_failing_test(tname, opts={})
|
409
|
+
str = "NOT DEFINED?"
|
410
|
+
if opts[:raise_nasty_in_test]
|
411
|
+
str = <<-TMETH
|
412
|
+
def #{tname}
|
413
|
+
raise NoMemoryError, "NASTY ERROR"
|
414
|
+
end
|
415
|
+
TMETH
|
416
|
+
|
417
|
+
elsif opts[:use_helpers]
|
418
|
+
str = <<-TMETH
|
419
|
+
def #{tname}
|
420
|
+
puts "A FAILING TEST"
|
421
|
+
my_helper
|
422
|
+
end
|
423
|
+
|
424
|
+
def my_helper
|
425
|
+
tripwire
|
426
|
+
end
|
427
|
+
|
428
|
+
def tripwire
|
429
|
+
assert false, "Instrumented failure"
|
430
|
+
end
|
431
|
+
TMETH
|
432
|
+
else
|
433
|
+
str = <<-TMETH
|
434
|
+
def #{tname}
|
435
|
+
puts "A FAILING TEST"
|
436
|
+
assert false, "Instrumented failure"
|
437
|
+
end
|
438
|
+
TMETH
|
439
|
+
end
|
440
|
+
return str
|
441
|
+
end
|
442
|
+
|
443
|
+
def is_modern_test_unit?
|
444
|
+
begin
|
445
|
+
Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS
|
446
|
+
return true
|
447
|
+
rescue NameError
|
448
|
+
return false
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|
metadata
CHANGED
@@ -1,36 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.0
|
3
|
-
specification_version: 1
|
4
2
|
name: hardmock
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.3.
|
7
|
-
date: 2007-12-10 00:00:00 -05:00
|
8
|
-
summary: A strict, ordered, expectation-oriented mock object library.
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: crosby@atomicobject.com
|
12
|
-
homepage: http://hardmock.rubyforge.org
|
13
|
-
rubyforge_project: hardmock
|
14
|
-
description:
|
15
|
-
autorequire: hardmock
|
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:
|
4
|
+
version: 1.3.6
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- David Crosby
|
8
|
+
autorequire: hardmock
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-12-11 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: crosby@atomicobject.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- CHANGES
|
25
|
+
- LICENSE
|
31
26
|
files:
|
32
27
|
- lib/assert_error.rb
|
33
|
-
- lib/
|
28
|
+
- lib/extend_test_unit.rb
|
34
29
|
- lib/hardmock/errors.rb
|
35
30
|
- lib/hardmock/expectation.rb
|
36
31
|
- lib/hardmock/expectation_builder.rb
|
@@ -41,18 +36,21 @@ files:
|
|
41
36
|
- lib/hardmock/stubbing.rb
|
42
37
|
- lib/hardmock/trapper.rb
|
43
38
|
- lib/hardmock/utils.rb
|
44
|
-
-
|
39
|
+
- lib/hardmock.rb
|
40
|
+
- lib/test_unit_before_after.rb
|
45
41
|
- test/functional/assert_error_test.rb
|
46
42
|
- test/functional/auto_verify_test.rb
|
47
43
|
- test/functional/direct_mock_usage_test.rb
|
48
44
|
- test/functional/hardmock_test.rb
|
49
45
|
- test/functional/stubbing_test.rb
|
46
|
+
- test/test_helper.rb
|
50
47
|
- test/unit/expectation_builder_test.rb
|
51
48
|
- test/unit/expectation_test.rb
|
52
49
|
- test/unit/expector_test.rb
|
53
50
|
- test/unit/method_cleanout_test.rb
|
54
51
|
- test/unit/mock_control_test.rb
|
55
52
|
- test/unit/mock_test.rb
|
53
|
+
- test/unit/test_unit_before_after_test.rb
|
56
54
|
- test/unit/trapper_test.rb
|
57
55
|
- test/unit/verify_error_test.rb
|
58
56
|
- Rakefile
|
@@ -63,6 +61,37 @@ files:
|
|
63
61
|
- README
|
64
62
|
- CHANGES
|
65
63
|
- LICENSE
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://hardmock.rubyforge.org
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --line-numbers
|
69
|
+
- --inline-source
|
70
|
+
- --main
|
71
|
+
- README
|
72
|
+
- --title
|
73
|
+
- Hardmock
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
version:
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
version:
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: hardmock
|
91
|
+
rubygems_version: 0.9.5
|
92
|
+
signing_key:
|
93
|
+
specification_version: 2
|
94
|
+
summary: A strict, ordered, expectation-oriented mock object library.
|
66
95
|
test_files:
|
67
96
|
- test/functional/assert_error_test.rb
|
68
97
|
- test/functional/auto_verify_test.rb
|
@@ -75,24 +104,6 @@ test_files:
|
|
75
104
|
- test/unit/method_cleanout_test.rb
|
76
105
|
- test/unit/mock_control_test.rb
|
77
106
|
- test/unit/mock_test.rb
|
107
|
+
- test/unit/test_unit_before_after_test.rb
|
78
108
|
- test/unit/trapper_test.rb
|
79
109
|
- test/unit/verify_error_test.rb
|
80
|
-
rdoc_options:
|
81
|
-
- --line-numbers
|
82
|
-
- --inline-source
|
83
|
-
- --main
|
84
|
-
- README
|
85
|
-
- --title
|
86
|
-
- Hardmock
|
87
|
-
extra_rdoc_files:
|
88
|
-
- README
|
89
|
-
- CHANGES
|
90
|
-
- LICENSE
|
91
|
-
executables: []
|
92
|
-
|
93
|
-
extensions: []
|
94
|
-
|
95
|
-
requirements: []
|
96
|
-
|
97
|
-
dependencies: []
|
98
|
-
|