hardmock 1.3.5 → 1.3.6
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/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
|
-
|