minitest 5.27.0 → 6.0.0.a1
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.rdoc +80 -0
- data/Manifest.txt +13 -4
- data/README.rdoc +5 -88
- data/Rakefile +5 -16
- data/bin/minitest +5 -0
- data/lib/minitest/assertions.rb +24 -56
- data/lib/minitest/autorun.rb +0 -1
- data/lib/minitest/bisect.rb +306 -0
- data/lib/minitest/complete.rb +56 -0
- data/lib/minitest/find_minimal_combination.rb +127 -0
- data/lib/minitest/manual_plugins.rb +4 -16
- data/lib/minitest/parallel.rb +3 -3
- data/lib/minitest/path_expander.rb +418 -0
- data/lib/minitest/pride.rb +1 -1
- data/lib/minitest/server.rb +45 -0
- data/lib/minitest/server_plugin.rb +84 -0
- data/lib/minitest/spec.rb +2 -31
- data/lib/minitest/sprint.rb +104 -0
- data/lib/minitest/sprint_plugin.rb +39 -0
- data/lib/minitest/test.rb +6 -11
- data/lib/minitest/test_task.rb +4 -6
- data/lib/minitest.rb +56 -84
- data/test/minitest/metametameta.rb +1 -1
- data/test/minitest/test_bisect.rb +235 -0
- data/test/minitest/test_find_minimal_combination.rb +138 -0
- data/test/minitest/test_minitest_assertions.rb +33 -47
- data/test/minitest/test_minitest_spec.rb +38 -102
- data/test/minitest/test_minitest_test.rb +20 -99
- data/test/minitest/test_path_expander.rb +229 -0
- data/test/minitest/test_server.rb +149 -0
- data.tar.gz.sig +0 -0
- metadata +47 -27
- metadata.gz.sig +0 -0
- data/.autotest +0 -34
- data/lib/minitest/mock.rb +0 -327
- data/lib/minitest/unit.rb +0 -42
- data/test/minitest/test_minitest_mock.rb +0 -1213
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
require "minitest/autorun"
|
|
2
|
+
require "minitest/server"
|
|
3
|
+
require "minitest/server_plugin"
|
|
4
|
+
|
|
5
|
+
require "minitest"
|
|
6
|
+
require "minitest/test"
|
|
7
|
+
require "minitest/server"
|
|
8
|
+
require "minitest/server_plugin"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
|
|
11
|
+
class BogoTests < Minitest::Test
|
|
12
|
+
def pass_test
|
|
13
|
+
assert true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def fail_test
|
|
17
|
+
assert false, "fail"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def error_test
|
|
21
|
+
raise "error"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def unmarshalable_ivar_test
|
|
25
|
+
raise "error"
|
|
26
|
+
rescue => e
|
|
27
|
+
e.instance_variable_set :@binding, binding
|
|
28
|
+
raise
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def unmarshalable_class_test
|
|
32
|
+
exc = Class.new RuntimeError
|
|
33
|
+
raise exc, "error"
|
|
34
|
+
rescue => e
|
|
35
|
+
e.instance_variable_set :@binding, binding
|
|
36
|
+
raise
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def wtf_test
|
|
40
|
+
assert false, "wtf"
|
|
41
|
+
rescue Minitest::Assertion => e
|
|
42
|
+
e.instance_variable_set :@proc, proc { 42 }
|
|
43
|
+
raise e
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class TestServerReporter < Minitest::ServerReporter
|
|
48
|
+
def record o
|
|
49
|
+
super
|
|
50
|
+
|
|
51
|
+
Marshal.dump o
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Client
|
|
56
|
+
def run pid, type
|
|
57
|
+
reporter = TestServerReporter.new pid
|
|
58
|
+
|
|
59
|
+
unless Minitest.respond_to? :run_one_method then # MT6
|
|
60
|
+
BogoTests.run BogoTests, "#{type}_test", reporter
|
|
61
|
+
else
|
|
62
|
+
reporter.start
|
|
63
|
+
reporter.record Minitest.run_one_method(BogoTests, "#{type}_test")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Server
|
|
69
|
+
attr_accessor :results
|
|
70
|
+
|
|
71
|
+
def self.run type = nil
|
|
72
|
+
s = self.new
|
|
73
|
+
s.run type
|
|
74
|
+
s.results
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def run type = nil
|
|
78
|
+
Minitest::Server.run self
|
|
79
|
+
|
|
80
|
+
Client.new.run $$, type
|
|
81
|
+
ensure
|
|
82
|
+
Minitest::Server.stop
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def minitest_start
|
|
86
|
+
# do nothing
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def minitest_result(*vals)
|
|
90
|
+
self.results = vals
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class ServerTest < Minitest::Test
|
|
95
|
+
def test_pass
|
|
96
|
+
assert_run "pass", [], 1
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_fail
|
|
100
|
+
assert_run "fail", ["fail"], 1
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
FILE = __FILE__.delete_prefix "#{Dir.pwd}/"
|
|
104
|
+
|
|
105
|
+
def test_error
|
|
106
|
+
msg = <<~EOM.chomp
|
|
107
|
+
RuntimeError: error
|
|
108
|
+
#{FILE}:21:in `error_test'
|
|
109
|
+
EOM
|
|
110
|
+
|
|
111
|
+
assert_run "error", [msg], 0
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_error_unmarshalable__ivar
|
|
115
|
+
msg = <<~EOM.chomp
|
|
116
|
+
RuntimeError: error
|
|
117
|
+
#{FILE}:25:in `unmarshalable_ivar_test'
|
|
118
|
+
EOM
|
|
119
|
+
|
|
120
|
+
assert_run "unmarshalable_ivar", [msg], 0
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_error_unmarshalable__class
|
|
124
|
+
msg = <<~EOM.chomp
|
|
125
|
+
RuntimeError: Neutered Exception #<Class:0xXXXXXX>: error
|
|
126
|
+
#{FILE}:33:in `unmarshalable_class_test'
|
|
127
|
+
EOM
|
|
128
|
+
|
|
129
|
+
assert_run "unmarshalable_class", [msg], 0
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def test_wtf
|
|
133
|
+
assert_run "wtf", ["wtf"], 1
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def assert_run type, e, n
|
|
137
|
+
e[0] = e[0].sub "`", "'BogoTests#" if RUBY_VERSION > "3.4" if e[0]
|
|
138
|
+
|
|
139
|
+
act = Server.run type
|
|
140
|
+
act[-1] = 0 # time
|
|
141
|
+
act[-3].map!(&:message)
|
|
142
|
+
|
|
143
|
+
act[-3][0] = act[-3][0].gsub(/0x\h+/, "0xXXXXXX") if act[-3][0]
|
|
144
|
+
|
|
145
|
+
exp = ["test/minitest/test_server.rb", "BogoTests", "#{type}_test", e, n, 0]
|
|
146
|
+
|
|
147
|
+
assert_equal exp, act
|
|
148
|
+
end
|
|
149
|
+
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: minitest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.0.a1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Davis
|
|
@@ -30,6 +30,20 @@ cert_chain:
|
|
|
30
30
|
-----END CERTIFICATE-----
|
|
31
31
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
32
32
|
dependencies:
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: prism
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.5'
|
|
40
|
+
type: :runtime
|
|
41
|
+
prerelease: false
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.5'
|
|
33
47
|
- !ruby/object:Gem::Dependency
|
|
34
48
|
name: rdoc
|
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -50,6 +64,20 @@ dependencies:
|
|
|
50
64
|
- - "<"
|
|
51
65
|
- !ruby/object:Gem::Version
|
|
52
66
|
version: '7'
|
|
67
|
+
- !ruby/object:Gem::Dependency
|
|
68
|
+
name: simplecov
|
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - "~>"
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0.21'
|
|
74
|
+
type: :development
|
|
75
|
+
prerelease: false
|
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - "~>"
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0.21'
|
|
53
81
|
- !ruby/object:Gem::Dependency
|
|
54
82
|
name: hoe
|
|
55
83
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,7 +94,7 @@ dependencies:
|
|
|
66
94
|
version: '4.3'
|
|
67
95
|
description: |-
|
|
68
96
|
minitest provides a complete suite of testing facilities supporting
|
|
69
|
-
TDD, BDD,
|
|
97
|
+
TDD, BDD, and benchmarking.
|
|
70
98
|
|
|
71
99
|
"I had a class with Jim Weirich on testing last week and we were
|
|
72
100
|
allowed to choose our testing frameworks. Kirk Haines and I were
|
|
@@ -92,9 +120,6 @@ description: |-
|
|
|
92
120
|
co-worker doesn't replace your linear algorithm with an exponential
|
|
93
121
|
one!
|
|
94
122
|
|
|
95
|
-
minitest/mock by Steven Baker, is a beautifully tiny mock (and stub)
|
|
96
|
-
object framework.
|
|
97
|
-
|
|
98
123
|
minitest/pride shows pride in testing and adds coloring to your test
|
|
99
124
|
output. I guess it is an example of how to write IO pipes too. :P
|
|
100
125
|
|
|
@@ -120,45 +145,55 @@ description: |-
|
|
|
120
145
|
extract-method refactorings still apply.
|
|
121
146
|
email:
|
|
122
147
|
- ryand-ruby@zenspider.com
|
|
123
|
-
executables:
|
|
148
|
+
executables:
|
|
149
|
+
- minitest
|
|
124
150
|
extensions: []
|
|
125
151
|
extra_rdoc_files:
|
|
126
152
|
- History.rdoc
|
|
127
153
|
- Manifest.txt
|
|
128
154
|
- README.rdoc
|
|
129
155
|
files:
|
|
130
|
-
- ".autotest"
|
|
131
156
|
- History.rdoc
|
|
132
157
|
- Manifest.txt
|
|
133
158
|
- README.rdoc
|
|
134
159
|
- Rakefile
|
|
160
|
+
- bin/minitest
|
|
135
161
|
- design_rationale.rb
|
|
136
162
|
- lib/hoe/minitest.rb
|
|
137
163
|
- lib/minitest.rb
|
|
138
164
|
- lib/minitest/assertions.rb
|
|
139
165
|
- lib/minitest/autorun.rb
|
|
140
166
|
- lib/minitest/benchmark.rb
|
|
167
|
+
- lib/minitest/bisect.rb
|
|
168
|
+
- lib/minitest/complete.rb
|
|
141
169
|
- lib/minitest/compress.rb
|
|
142
170
|
- lib/minitest/error_on_warning.rb
|
|
143
171
|
- lib/minitest/expectations.rb
|
|
172
|
+
- lib/minitest/find_minimal_combination.rb
|
|
144
173
|
- lib/minitest/hell.rb
|
|
145
174
|
- lib/minitest/manual_plugins.rb
|
|
146
|
-
- lib/minitest/mock.rb
|
|
147
175
|
- lib/minitest/parallel.rb
|
|
176
|
+
- lib/minitest/path_expander.rb
|
|
148
177
|
- lib/minitest/pride.rb
|
|
149
178
|
- lib/minitest/pride_plugin.rb
|
|
179
|
+
- lib/minitest/server.rb
|
|
180
|
+
- lib/minitest/server_plugin.rb
|
|
150
181
|
- lib/minitest/spec.rb
|
|
182
|
+
- lib/minitest/sprint.rb
|
|
183
|
+
- lib/minitest/sprint_plugin.rb
|
|
151
184
|
- lib/minitest/test.rb
|
|
152
185
|
- lib/minitest/test_task.rb
|
|
153
|
-
- lib/minitest/unit.rb
|
|
154
186
|
- test/minitest/metametameta.rb
|
|
187
|
+
- test/minitest/test_bisect.rb
|
|
188
|
+
- test/minitest/test_find_minimal_combination.rb
|
|
155
189
|
- test/minitest/test_minitest_assertions.rb
|
|
156
190
|
- test/minitest/test_minitest_benchmark.rb
|
|
157
|
-
- test/minitest/test_minitest_mock.rb
|
|
158
191
|
- test/minitest/test_minitest_reporter.rb
|
|
159
192
|
- test/minitest/test_minitest_spec.rb
|
|
160
193
|
- test/minitest/test_minitest_test.rb
|
|
161
194
|
- test/minitest/test_minitest_test_task.rb
|
|
195
|
+
- test/minitest/test_path_expander.rb
|
|
196
|
+
- test/minitest/test_server.rb
|
|
162
197
|
homepage: https://minite.st/
|
|
163
198
|
licenses:
|
|
164
199
|
- MIT
|
|
@@ -167,21 +202,6 @@ metadata:
|
|
|
167
202
|
source_code_uri: https://github.com/minitest/minitest
|
|
168
203
|
bug_tracker_uri: https://github.com/minitest/minitest/issues
|
|
169
204
|
changelog_uri: https://github.com/minitest/minitest/blob/master/History.rdoc
|
|
170
|
-
post_install_message: |
|
|
171
|
-
NOTE: minitest 5 will be the last in the minitest family to support
|
|
172
|
-
ruby 1.8 to 2.7. If you need to keep using these versions,
|
|
173
|
-
you need to pin your dependency to minitest with something
|
|
174
|
-
like "~> 5.0". See History.rdoc to locate compatible
|
|
175
|
-
versions.
|
|
176
|
-
|
|
177
|
-
Further, minitest 6 will be dropping the following:
|
|
178
|
-
|
|
179
|
-
+ MiniTest (it's been Minitest for >10 years)
|
|
180
|
-
+ MiniTest::Unit
|
|
181
|
-
+ MiniTest::Unit::TestCase
|
|
182
|
-
+ assert_send (unless you argue for it well)
|
|
183
|
-
+ assert_equal nil, obj
|
|
184
|
-
+ mocks and stubs: moving minitest/mock.rb to its own gem
|
|
185
205
|
rdoc_options:
|
|
186
206
|
- "--main"
|
|
187
207
|
- README.rdoc
|
|
@@ -191,7 +211,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
191
211
|
requirements:
|
|
192
212
|
- - ">="
|
|
193
213
|
- !ruby/object:Gem::Version
|
|
194
|
-
version: '3.
|
|
214
|
+
version: '3.2'
|
|
195
215
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
216
|
requirements:
|
|
197
217
|
- - ">="
|
|
@@ -201,5 +221,5 @@ requirements: []
|
|
|
201
221
|
rubygems_version: 3.7.2
|
|
202
222
|
specification_version: 4
|
|
203
223
|
summary: minitest provides a complete suite of testing facilities supporting TDD,
|
|
204
|
-
BDD,
|
|
224
|
+
BDD, and benchmarking
|
|
205
225
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|
data/.autotest
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# -*- ruby -*-
|
|
2
|
-
|
|
3
|
-
require 'autotest/restart'
|
|
4
|
-
require 'autotest/rcov' if ENV['RCOV']
|
|
5
|
-
|
|
6
|
-
Autotest.add_hook :initialize do |at|
|
|
7
|
-
at.testlib = 'minitest/autorun'
|
|
8
|
-
|
|
9
|
-
bench_tests = %w(TestMinitestBenchmark)
|
|
10
|
-
mock_tests = %w(TestMinitestMock TestMinitestStub)
|
|
11
|
-
spec_tests = %w(TestMinitestReporter TestMetaStatic TestMeta
|
|
12
|
-
TestSpecInTestCase)
|
|
13
|
-
unit_tests = %w(TestMinitestGuard TestMinitestRunnable
|
|
14
|
-
TestMinitestRunner TestMinitestTest TestMinitestUnit
|
|
15
|
-
TestMinitestUnitInherited TestMinitestUnitOrder
|
|
16
|
-
TestMinitestUnitRecording TestMinitestUnitTestCase)
|
|
17
|
-
|
|
18
|
-
{
|
|
19
|
-
bench_tests => "test/minitest/test_minitest_benchmark.rb",
|
|
20
|
-
mock_tests => "test/minitest/test_minitest_mock.rb",
|
|
21
|
-
spec_tests => "test/minitest/test_minitest_reporter.rb",
|
|
22
|
-
unit_tests => "test/minitest/test_minitest_unit.rb",
|
|
23
|
-
}.each do |klasses, file|
|
|
24
|
-
klasses.each do |klass|
|
|
25
|
-
at.extra_class_map[klass] = file
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
at.add_exception 'coverage.info'
|
|
30
|
-
at.add_exception 'coverage'
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# require 'autotest/rcov'
|
|
34
|
-
# Autotest::RCov.command = 'rcov_info'
|
data/lib/minitest/mock.rb
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
class MockExpectationError < StandardError; end # :nodoc:
|
|
2
|
-
|
|
3
|
-
module Minitest # :nodoc:
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
# A simple and clean mock object framework.
|
|
7
|
-
#
|
|
8
|
-
# All mock objects are an instance of Mock
|
|
9
|
-
|
|
10
|
-
class Mock
|
|
11
|
-
alias __respond_to? respond_to?
|
|
12
|
-
|
|
13
|
-
overridden_methods = %i[
|
|
14
|
-
===
|
|
15
|
-
class
|
|
16
|
-
inspect
|
|
17
|
-
instance_eval
|
|
18
|
-
instance_variables
|
|
19
|
-
object_id
|
|
20
|
-
public_send
|
|
21
|
-
respond_to_missing?
|
|
22
|
-
send
|
|
23
|
-
to_s
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
overridden_methods << :singleton_method_added if defined?(::DEBUGGER__)
|
|
27
|
-
|
|
28
|
-
instance_methods.each do |m|
|
|
29
|
-
undef_method m unless overridden_methods.include?(m) || m =~ /^__/
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
overridden_methods.map(&:to_sym).each do |method_id|
|
|
33
|
-
old_w, $-w = $-w, nil
|
|
34
|
-
define_method method_id do |*args, **kwargs, &b|
|
|
35
|
-
if @expected_calls.key? method_id then
|
|
36
|
-
method_missing(method_id, *args, **kwargs, &b)
|
|
37
|
-
else
|
|
38
|
-
super(*args, **kwargs, &b)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
ensure
|
|
42
|
-
$-w = old_w
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def initialize delegator = nil # :nodoc:
|
|
46
|
-
@delegator = delegator
|
|
47
|
-
@expected_calls = Hash.new { |calls, name| calls[name] = [] }
|
|
48
|
-
@actual_calls = Hash.new { |calls, name| calls[name] = [] }
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
@@KW_WARNED = false # :nodoc:
|
|
52
|
-
|
|
53
|
-
##
|
|
54
|
-
# Expect that method +name+ is called, optionally with +args+ (and
|
|
55
|
-
# +kwargs+ or a +blk+), and returns +retval+.
|
|
56
|
-
#
|
|
57
|
-
# @mock.expect(:meaning_of_life, 42)
|
|
58
|
-
# @mock.meaning_of_life # => 42
|
|
59
|
-
#
|
|
60
|
-
# @mock.expect(:do_something_with, true, [some_obj, true])
|
|
61
|
-
# @mock.do_something_with(some_obj, true) # => true
|
|
62
|
-
#
|
|
63
|
-
# @mock.expect(:do_something_else, true) do |a1, a2|
|
|
64
|
-
# a1 == "buggs" && a2 == :bunny
|
|
65
|
-
# end
|
|
66
|
-
#
|
|
67
|
-
# +args+ is compared to the expected args using case equality (ie, the
|
|
68
|
-
# '===' operator), allowing for less specific expectations.
|
|
69
|
-
#
|
|
70
|
-
# @mock.expect(:uses_any_string, true, [String])
|
|
71
|
-
# @mock.uses_any_string("foo") # => true
|
|
72
|
-
# @mock.verify # => true
|
|
73
|
-
#
|
|
74
|
-
# @mock.expect(:uses_one_string, true, ["foo"])
|
|
75
|
-
# @mock.uses_one_string("bar") # => raises MockExpectationError
|
|
76
|
-
#
|
|
77
|
-
# If a method will be called multiple times, specify a new expect for each one.
|
|
78
|
-
# They will be used in the order you define them.
|
|
79
|
-
#
|
|
80
|
-
# @mock.expect(:ordinal_increment, 'first')
|
|
81
|
-
# @mock.expect(:ordinal_increment, 'second')
|
|
82
|
-
#
|
|
83
|
-
# @mock.ordinal_increment # => 'first'
|
|
84
|
-
# @mock.ordinal_increment # => 'second'
|
|
85
|
-
# @mock.ordinal_increment # => raises MockExpectationError "No more expects available for :ordinal_increment"
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
def expect name, retval, args = [], **kwargs, &blk
|
|
89
|
-
name = name.to_sym
|
|
90
|
-
|
|
91
|
-
if blk then
|
|
92
|
-
raise ArgumentError, "args ignored when block given" unless args.empty?
|
|
93
|
-
raise ArgumentError, "kwargs ignored when block given" unless kwargs.empty?
|
|
94
|
-
@expected_calls[name] << { :retval => retval, :block => blk }
|
|
95
|
-
else
|
|
96
|
-
raise ArgumentError, "args must be an array" unless Array === args
|
|
97
|
-
|
|
98
|
-
if ENV["MT_KWARGS_HAC\K"] && (Hash === args.last ||
|
|
99
|
-
Hash == args.last) then
|
|
100
|
-
if kwargs.empty? then
|
|
101
|
-
kwargs = args.pop
|
|
102
|
-
else
|
|
103
|
-
unless @@KW_WARNED then
|
|
104
|
-
from = caller(1..1).first
|
|
105
|
-
warn "Using MT_KWARGS_HAC\K yet passing kwargs. From #{from}"
|
|
106
|
-
@@KW_WARNED = true
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
@expected_calls[name] <<
|
|
112
|
-
{ :retval => retval, :args => args, :kwargs => kwargs }
|
|
113
|
-
end
|
|
114
|
-
self
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def __call name, data # :nodoc:
|
|
118
|
-
case data
|
|
119
|
-
when Hash then
|
|
120
|
-
args = data[:args].inspect[1..-2]
|
|
121
|
-
kwargs = data[:kwargs]
|
|
122
|
-
if kwargs && !kwargs.empty? then
|
|
123
|
-
args << ", " unless args.empty?
|
|
124
|
-
args << kwargs.inspect[1..-2]
|
|
125
|
-
end
|
|
126
|
-
"#{name}(#{args}) => #{data[:retval].inspect}"
|
|
127
|
-
else
|
|
128
|
-
data.map { |d| __call name, d }.join ", "
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
##
|
|
133
|
-
# Verify that all methods were called as expected. Raises
|
|
134
|
-
# +MockExpectationError+ if the mock object was not called as
|
|
135
|
-
# expected.
|
|
136
|
-
|
|
137
|
-
def verify
|
|
138
|
-
@expected_calls.each do |name, expected|
|
|
139
|
-
actual = @actual_calls.fetch name, nil # defaults to []
|
|
140
|
-
raise MockExpectationError, "Expected #{__call name, expected[0]}" unless actual
|
|
141
|
-
raise MockExpectationError, "Expected #{__call name, expected[actual.size]}, got [#{__call name, actual}]" if
|
|
142
|
-
actual.size < expected.size
|
|
143
|
-
end
|
|
144
|
-
true
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def method_missing sym, *args, **kwargs, &block # :nodoc:
|
|
148
|
-
unless @expected_calls.key? sym then
|
|
149
|
-
if @delegator && @delegator.respond_to?(sym)
|
|
150
|
-
return @delegator.public_send(sym, *args, **kwargs, &block)
|
|
151
|
-
else
|
|
152
|
-
raise NoMethodError, "unmocked method %p, expected one of %p" %
|
|
153
|
-
[sym, @expected_calls.keys.sort_by(&:to_s)]
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
index = @actual_calls[sym].length
|
|
158
|
-
expected_call = @expected_calls[sym][index]
|
|
159
|
-
|
|
160
|
-
unless expected_call then
|
|
161
|
-
raise MockExpectationError, "No more expects available for %p: %p %p" %
|
|
162
|
-
[sym, args, kwargs]
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
expected_args, expected_kwargs, retval, val_block =
|
|
166
|
-
expected_call.values_at :args, :kwargs, :retval, :block
|
|
167
|
-
|
|
168
|
-
expected_kwargs = kwargs.to_h { |ak, av| [ak, Object] } if
|
|
169
|
-
Hash == expected_kwargs
|
|
170
|
-
|
|
171
|
-
if val_block then
|
|
172
|
-
# keep "verify" happy
|
|
173
|
-
@actual_calls[sym] << expected_call
|
|
174
|
-
|
|
175
|
-
raise MockExpectationError, "mocked method %p failed block w/ %p %p" %
|
|
176
|
-
[sym, args, kwargs] unless val_block.call(*args, **kwargs, &block)
|
|
177
|
-
|
|
178
|
-
return retval
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
if expected_args.size != args.size then
|
|
182
|
-
raise ArgumentError, "mocked method %p expects %d arguments, got %p" %
|
|
183
|
-
[sym, expected_args.size, args]
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
if expected_kwargs.size != kwargs.size then
|
|
187
|
-
raise ArgumentError, "mocked method %p expects %d keyword arguments, got %p" %
|
|
188
|
-
[sym, expected_kwargs.size, kwargs]
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
zipped_args = expected_args.zip args
|
|
192
|
-
fully_matched = zipped_args.all? { |mod, a|
|
|
193
|
-
mod === a or mod == a
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
unless fully_matched then
|
|
197
|
-
fmt = "mocked method %p called with unexpected arguments %p"
|
|
198
|
-
raise MockExpectationError, fmt % [sym, args]
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
unless expected_kwargs.keys.sort == kwargs.keys.sort then
|
|
202
|
-
fmt = "mocked method %p called with unexpected keywords %p vs %p"
|
|
203
|
-
raise MockExpectationError, fmt % [sym, expected_kwargs.keys, kwargs.keys]
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
zipped_kwargs = expected_kwargs.to_h { |ek, ev|
|
|
207
|
-
av = kwargs[ek]
|
|
208
|
-
[ek, [ev, av]]
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
fully_matched = zipped_kwargs.all? { |ek, (ev, av)|
|
|
212
|
-
ev === av or ev == av
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
unless fully_matched then
|
|
216
|
-
fmt = "mocked method %p called with unexpected keyword arguments %p vs %p"
|
|
217
|
-
raise MockExpectationError, fmt % [sym, expected_kwargs, kwargs]
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
@actual_calls[sym] << {
|
|
221
|
-
:retval => retval,
|
|
222
|
-
:args => zipped_args.map { |e, a| e === a ? e : a },
|
|
223
|
-
:kwargs => zipped_kwargs.to_h { |k, (e, a)| [k, e === a ? e : a] },
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
retval
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
def respond_to? sym, include_private = false # :nodoc:
|
|
230
|
-
return true if @expected_calls.key? sym.to_sym
|
|
231
|
-
return true if @delegator && @delegator.respond_to?(sym, include_private)
|
|
232
|
-
__respond_to? sym, include_private
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
module Minitest::Assertions
|
|
238
|
-
##
|
|
239
|
-
# Assert that the mock verifies correctly and fail if not.
|
|
240
|
-
|
|
241
|
-
def assert_mock mock, msg = nil
|
|
242
|
-
assert mock.verify
|
|
243
|
-
rescue MockExpectationError => e
|
|
244
|
-
msg = message(msg) { e.message }
|
|
245
|
-
flunk msg
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
module Minitest::Expectations
|
|
250
|
-
##
|
|
251
|
-
# See Minitest::Assertions#assert_mock.
|
|
252
|
-
#
|
|
253
|
-
# _(collection).must_verify
|
|
254
|
-
#
|
|
255
|
-
# :method: must_verify
|
|
256
|
-
|
|
257
|
-
infect_an_assertion :assert_mock, :must_verify, :unary if
|
|
258
|
-
defined?(infect_an_assertion)
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
##
|
|
262
|
-
# Object extensions for Minitest::Mock.
|
|
263
|
-
|
|
264
|
-
class Object
|
|
265
|
-
|
|
266
|
-
##
|
|
267
|
-
# Add a temporary stubbed method replacing +name+ for the duration
|
|
268
|
-
# of the +block+. If +val_or_callable+ responds to #call, then it
|
|
269
|
-
# returns the result of calling it, otherwise returns the value
|
|
270
|
-
# as-is. If stubbed method yields a block, +block_args+ will be
|
|
271
|
-
# passed along. Cleans up the stub at the end of the +block+. The
|
|
272
|
-
# method +name+ must exist before stubbing.
|
|
273
|
-
#
|
|
274
|
-
# def test_stale_eh
|
|
275
|
-
# obj_under_test = Something.new
|
|
276
|
-
# refute obj_under_test.stale?
|
|
277
|
-
#
|
|
278
|
-
# Time.stub :now, Time.at(0) do
|
|
279
|
-
# assert obj_under_test.stale?
|
|
280
|
-
# end
|
|
281
|
-
# end
|
|
282
|
-
#--
|
|
283
|
-
# NOTE: keyword args in callables are NOT checked for correctness
|
|
284
|
-
# against the existing method. Too many edge cases to be worth it.
|
|
285
|
-
|
|
286
|
-
def stub name, val_or_callable, *block_args, **block_kwargs, &block
|
|
287
|
-
new_name = "__minitest_stub__#{name}"
|
|
288
|
-
|
|
289
|
-
metaclass = class << self; self; end
|
|
290
|
-
|
|
291
|
-
if respond_to? name and not methods.map(&:to_s).include? name.to_s then
|
|
292
|
-
metaclass.send :define_method, name do |*args, **kwargs|
|
|
293
|
-
super(*args, **kwargs)
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
metaclass.send :alias_method, new_name, name
|
|
298
|
-
|
|
299
|
-
if ENV["MT_KWARGS_HAC\K"] then
|
|
300
|
-
metaclass.send :define_method, name do |*args, &blk|
|
|
301
|
-
if val_or_callable.respond_to? :call then
|
|
302
|
-
val_or_callable.call(*args, &blk)
|
|
303
|
-
else
|
|
304
|
-
blk.call(*block_args, **block_kwargs) if blk
|
|
305
|
-
val_or_callable
|
|
306
|
-
end
|
|
307
|
-
end
|
|
308
|
-
else
|
|
309
|
-
metaclass.send :define_method, name do |*args, **kwargs, &blk|
|
|
310
|
-
if val_or_callable.respond_to? :call then
|
|
311
|
-
val_or_callable.call(*args, **kwargs, &blk)
|
|
312
|
-
else
|
|
313
|
-
if blk then
|
|
314
|
-
blk.call(*block_args, **block_kwargs)
|
|
315
|
-
end
|
|
316
|
-
val_or_callable
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
block[self]
|
|
322
|
-
ensure
|
|
323
|
-
metaclass.send :undef_method, name
|
|
324
|
-
metaclass.send :alias_method, name, new_name
|
|
325
|
-
metaclass.send :undef_method, new_name
|
|
326
|
-
end
|
|
327
|
-
end
|