minitest-bisect 1.5.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.rdoc +6 -0
- data/lib/minitest/bisect.rb +12 -48
- data/test/minitest/test_bisect.rb +1 -12
- data/test/minitest/test_find_minimal_combination.rb +87 -74
- data.tar.gz.sig +0 -0
- metadata +18 -17
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0adf4dd9767c961c0030a23e4e200245d74505bb0c5bd79dc0ff4201adeadc63
|
4
|
+
data.tar.gz: 501678cbbf5567c3408f1e44721dcbb11bc917b8e2d77c7ca063652e5ffc133f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c9f20afc3dcd8cb7e782caaa456e8f9dded619624226c9a7123290cc8cd47abe1ec32afdc1acd61dba41b1d1d1797389296e45f7abc234c27eca3206a8f5473
|
7
|
+
data.tar.gz: 3db4728af1051d31167814e277af68ee39fc0451a3c8df5c45f417a64b7d5fac8e72a9f2b5a590fa816566f1397f91429c1f16d608cba811d361faad246e7f6b
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/History.rdoc
CHANGED
data/lib/minitest/bisect.rb
CHANGED
@@ -5,7 +5,7 @@ require "rbconfig"
|
|
5
5
|
require "path_expander"
|
6
6
|
|
7
7
|
class Minitest::Bisect
|
8
|
-
VERSION = "1.
|
8
|
+
VERSION = "1.6.0"
|
9
9
|
|
10
10
|
class PathExpander < ::PathExpander
|
11
11
|
TEST_GLOB = "**/{test_*,*_test,spec_*,*_spec}.rb" # :nodoc:
|
@@ -51,7 +51,7 @@ class Minitest::Bisect
|
|
51
51
|
RbConfig::CONFIG['ruby_install_name'] +
|
52
52
|
RbConfig::CONFIG['EXEEXT']).sub(/.*\s.*/m, '"\&"')
|
53
53
|
|
54
|
-
attr_accessor :tainted, :failures, :culprits, :
|
54
|
+
attr_accessor :tainted, :failures, :culprits, :seen_bad
|
55
55
|
alias :tainted? :tainted
|
56
56
|
|
57
57
|
def self.run files
|
@@ -78,18 +78,14 @@ class Minitest::Bisect
|
|
78
78
|
|
79
79
|
cmd = nil
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
expander = Minitest::Bisect::PathExpander.new mt_flags
|
81
|
+
mt_flags = args.dup
|
82
|
+
expander = Minitest::Bisect::PathExpander.new mt_flags
|
84
83
|
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
files = expander.process
|
85
|
+
rb_flags = expander.rb_flags
|
86
|
+
mt_flags += ["--server", $$]
|
88
87
|
|
89
|
-
|
90
|
-
else
|
91
|
-
cmd = bisect_methods bisect_files args
|
92
|
-
end
|
88
|
+
cmd = bisect_methods build_files_cmd(files, rb_flags, mt_flags)
|
93
89
|
|
94
90
|
puts "Final reproduction:"
|
95
91
|
puts
|
@@ -99,37 +95,7 @@ class Minitest::Bisect
|
|
99
95
|
Minitest::Server.stop
|
100
96
|
end
|
101
97
|
|
102
|
-
def bisect_files files
|
103
|
-
self.mode = :files
|
104
|
-
|
105
|
-
files, flags = files.partition { |arg| File.file? arg }
|
106
|
-
rb_flags, mt_flags = flags.partition { |arg| arg =~ /^-I/ }
|
107
|
-
mt_flags += ["--server", $$]
|
108
|
-
|
109
|
-
puts "reproducing..."
|
110
|
-
system "#{build_files_cmd files, rb_flags, mt_flags} #{SHH}"
|
111
|
-
abort "Reproduction run passed? Aborting. Try running with MTB_VERBOSE=2 to verify." unless tainted?
|
112
|
-
puts "reproduced"
|
113
|
-
|
114
|
-
found, count = files.find_minimal_combination_and_count do |test|
|
115
|
-
puts "# of culprit files: #{test.size}"
|
116
|
-
|
117
|
-
system "#{build_files_cmd test, rb_flags, mt_flags} #{SHH}"
|
118
|
-
|
119
|
-
self.tainted?
|
120
|
-
end
|
121
|
-
|
122
|
-
puts
|
123
|
-
puts "Minimal files found in #{count} steps:"
|
124
|
-
puts
|
125
|
-
cmd = build_files_cmd found, rb_flags, mt_flags
|
126
|
-
puts cmd
|
127
|
-
cmd
|
128
|
-
end
|
129
|
-
|
130
98
|
def bisect_methods cmd
|
131
|
-
self.mode = :methods
|
132
|
-
|
133
99
|
time_it "reproducing...", build_methods_cmd(cmd)
|
134
100
|
|
135
101
|
unless tainted? then
|
@@ -245,12 +211,10 @@ class Minitest::Bisect
|
|
245
211
|
def minitest_result file, klass, method, fails, assertions, time
|
246
212
|
fails.reject! { |fail| Minitest::Skip === fail }
|
247
213
|
|
248
|
-
if
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
self.seen_bad = true
|
253
|
-
end
|
214
|
+
if fails.empty? then
|
215
|
+
culprits << "#{klass}##{method}" unless seen_bad # UGH
|
216
|
+
else
|
217
|
+
self.seen_bad = true
|
254
218
|
end
|
255
219
|
|
256
220
|
return if fails.empty?
|
@@ -8,6 +8,7 @@ class TestMinitest::TestBisect < Minitest::Test
|
|
8
8
|
|
9
9
|
def setup
|
10
10
|
self.bisect = Minitest::Bisect.new
|
11
|
+
bisect.reset
|
11
12
|
end
|
12
13
|
|
13
14
|
def test_class_run
|
@@ -124,9 +125,6 @@ class TestMinitest::TestBisect < Minitest::Test
|
|
124
125
|
end
|
125
126
|
|
126
127
|
def test_minitest_result
|
127
|
-
bisect.mode = :methods
|
128
|
-
bisect.reset
|
129
|
-
|
130
128
|
bisect.minitest_result "file.rb", "TestClass", "test_method", [], 1, 1
|
131
129
|
|
132
130
|
assert_equal false, bisect.tainted
|
@@ -135,9 +133,6 @@ class TestMinitest::TestBisect < Minitest::Test
|
|
135
133
|
end
|
136
134
|
|
137
135
|
def test_minitest_result_skip
|
138
|
-
bisect.mode = :methods
|
139
|
-
bisect.reset
|
140
|
-
|
141
136
|
fail = Minitest::Skip.new("woot")
|
142
137
|
|
143
138
|
bisect.minitest_result "file.rb", "TestClass", "test_method", [fail], 1, 1
|
@@ -148,9 +143,6 @@ class TestMinitest::TestBisect < Minitest::Test
|
|
148
143
|
end
|
149
144
|
|
150
145
|
def test_minitest_result_fail
|
151
|
-
bisect.mode = :methods
|
152
|
-
bisect.reset
|
153
|
-
|
154
146
|
fail = Minitest::Assertion.new "msg"
|
155
147
|
|
156
148
|
bisect.minitest_result "file.rb", "TestClass", "test_method", [fail], 1, 1
|
@@ -163,9 +155,6 @@ class TestMinitest::TestBisect < Minitest::Test
|
|
163
155
|
end
|
164
156
|
|
165
157
|
def test_minitest_result_error
|
166
|
-
bisect.mode = :methods
|
167
|
-
bisect.reset
|
168
|
-
|
169
158
|
fail = Minitest::UnexpectedError.new RuntimeError.new("woot")
|
170
159
|
|
171
160
|
bisect.minitest_result "file.rb", "TestClass", "test_method", [fail], 1, 1
|
@@ -10,93 +10,99 @@ describe Array, :find_minimal_combination do
|
|
10
10
|
lambda { |sample| bad & sample == bad }
|
11
11
|
end
|
12
12
|
|
13
|
+
def record_and_check(tests, *bad)
|
14
|
+
lambda { |test| tests << test.join; bad & test == bad }
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_trials s
|
18
|
+
s.lines.map { |s| s.chomp.sub(/#.*/, '').delete " " }.reject(&:empty?)
|
19
|
+
end
|
20
|
+
|
13
21
|
def assert_steps input, bad, exp
|
14
22
|
tests = []
|
15
23
|
|
16
|
-
found = input.find_minimal_combination
|
17
|
-
tests << test
|
18
|
-
bad & test == bad
|
19
|
-
end
|
24
|
+
found = input.find_minimal_combination(&record_and_check(tests, *bad))
|
20
25
|
|
21
26
|
assert_equal bad, found, "algorithm is bad"
|
22
27
|
|
23
|
-
assert_equal exp, tests
|
28
|
+
assert_equal parse_trials(exp), tests
|
24
29
|
end
|
25
30
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
HEX = "0123456789ABCDEF".chars.to_a
|
32
|
+
|
33
|
+
# lvl collection
|
34
|
+
#
|
35
|
+
# 0 | A
|
36
|
+
# 1 | B C
|
37
|
+
# 2 | D E F G
|
38
|
+
# 3 | H I J K L M N O
|
39
|
+
# |
|
40
|
+
# 4 | 0123456789ABCDEF
|
41
|
+
|
42
|
+
def test_ordering_best_case_1
|
43
|
+
ary = HEX
|
44
|
+
bad = %w[0]
|
45
|
+
exp = <<~EOT
|
46
|
+
#123456789ABCDEF
|
47
|
+
01234567 # HIT! -- level 1 = B, C
|
48
|
+
0123 # HIT! -- level 2 = D, E
|
49
|
+
01 # HIT! -- level 3 = H, I
|
50
|
+
0 # HIT!
|
51
|
+
EOT
|
52
|
+
|
53
|
+
assert_steps ary, bad, exp
|
37
54
|
end
|
38
55
|
|
39
|
-
def
|
40
|
-
|
41
|
-
bad
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# 1 ---------------
|
53
|
-
# 1 ---------------
|
54
|
-
# 2 ------- -------
|
55
|
-
# 2 +++++++ +++++++
|
56
|
-
# 3 xxxxxxx
|
57
|
-
# 3 xxxxxxx
|
58
|
-
# 3 --- ---
|
59
|
-
# 3 +++ +++
|
60
|
-
# 4 xxx
|
61
|
-
# 4 xxx
|
62
|
-
# 4 - -
|
63
|
-
# 4 + +
|
64
|
-
#
|
65
|
-
# - = miss
|
66
|
-
# + = hit
|
67
|
-
# x = unwanted test
|
68
|
-
|
69
|
-
exp = [
|
70
|
-
# level 1 = B, C
|
71
|
-
[0, 1, 2, 3, 4, 5, 6, 7],
|
72
|
-
[8, 9, 10, 11, 12, 13, 14, 15],
|
73
|
-
|
74
|
-
# level 2 = DF, DG, EF, EG
|
75
|
-
[0, 1, 2, 3, 8, 9, 10, 11],
|
76
|
-
[0, 1, 2, 3, 12, 13, 14, 15],
|
77
|
-
|
78
|
-
# level 3
|
79
|
-
# [0, 1, 2, 3], # I think this is bad, we've tested B
|
80
|
-
# [12, 13, 14, 15], # again, bad, we've tested C
|
81
|
-
[0, 1, 12, 13],
|
82
|
-
[0, 1, 14, 15],
|
83
|
-
|
84
|
-
# level 4
|
85
|
-
# [0, 1],
|
86
|
-
# [14, 15],
|
87
|
-
[0, 14],
|
88
|
-
[0, 15],
|
89
|
-
]
|
90
|
-
|
91
|
-
assert_steps a, bad, exp
|
56
|
+
def test_ordering_best_case_2
|
57
|
+
ary = HEX
|
58
|
+
bad = %w[0 1]
|
59
|
+
exp = <<~EOT
|
60
|
+
01234567 # HIT! -- level 1 = B, C
|
61
|
+
0123 # HIT! -- level 2 = D, E
|
62
|
+
01 # HIT! -- level 3 = H, I
|
63
|
+
0 # miss -- level 4 = 0, 1, n_combos = 1
|
64
|
+
1 # miss
|
65
|
+
01 # HIT! -- level 3 = H, n_combos = 2
|
66
|
+
EOT
|
67
|
+
|
68
|
+
assert_steps ary, bad, exp
|
92
69
|
end
|
93
70
|
|
94
|
-
|
71
|
+
def test_ordering
|
72
|
+
ary = HEX
|
73
|
+
bad = %w[1 F]
|
74
|
+
exp = <<~EOT
|
75
|
+
01234567 # miss -- level 1 = B, C
|
76
|
+
89ABCDEF # miss
|
77
|
+
0123 89AB # miss -- level 2 = DF, DG, EF, EG
|
78
|
+
0123 CDEF # HIT!
|
79
|
+
01 CD # miss -- level 3 = HN, HO
|
80
|
+
01 EF # HIT!
|
81
|
+
0 E # miss -- level 4 = 0E, 0F, 1E, 1F
|
82
|
+
0 F # miss
|
83
|
+
1 E # miss
|
84
|
+
1 F # HIT!
|
85
|
+
EOT
|
86
|
+
|
87
|
+
assert_steps ary, bad, exp
|
88
|
+
end
|
95
89
|
|
96
90
|
def self.test_find_minimal_combination max, *bad
|
97
|
-
define_method "
|
91
|
+
define_method "%s_%s_%s" % [__method__, max, bad.join("_")] do
|
98
92
|
a = (1..max).to_a
|
99
|
-
|
93
|
+
|
94
|
+
assert_equal bad, a.find_minimal_combination(&check(*bad))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.test_find_minimal_combination_and_count max, nsteps, *bad
|
99
|
+
define_method "%s_%s_%s_%s" % [__method__, max, nsteps, bad.join("_")] do
|
100
|
+
a = (1..max).to_a
|
101
|
+
|
102
|
+
found, count = a.find_minimal_combination_and_count(&check(*bad))
|
103
|
+
|
104
|
+
assert_equal bad, found
|
105
|
+
assert_equal nsteps, count
|
100
106
|
end
|
101
107
|
end
|
102
108
|
|
@@ -119,7 +125,14 @@ describe Array, :find_minimal_combination do
|
|
119
125
|
test_find_minimal_combination 1023, 7, 15, 166, 1001
|
120
126
|
test_find_minimal_combination 1023, 1000, 1001, 1002
|
121
127
|
test_find_minimal_combination 1023, 1001, 1003, 1005, 1007
|
128
|
+
test_find_minimal_combination 1024, 1001, 1003, 1005, 1007
|
129
|
+
test_find_minimal_combination 1024, 1, 1024
|
130
|
+
|
131
|
+
test_find_minimal_combination_and_count 1024, 12, 1, 2
|
132
|
+
test_find_minimal_combination_and_count 1024, 23, 1, 1023
|
133
|
+
test_find_minimal_combination_and_count 1024, 24, 1, 1024
|
134
|
+
test_find_minimal_combination_and_count 1023, 26, 1, 1023
|
122
135
|
|
123
|
-
|
124
|
-
|
136
|
+
test_find_minimal_combination_and_count 1024, 93, 1001, 1003, 1005, 1007
|
137
|
+
test_find_minimal_combination_and_count 1023, 93, 1001, 1003, 1005, 1007
|
125
138
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-bisect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Davis
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
|
-
|
13
|
+
MIIDPjCCAiagAwIBAgIBBjANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu
|
14
14
|
ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
|
15
|
-
|
15
|
+
GRYDY29tMB4XDTIxMTIyMzIzMTkwNFoXDTIyMTIyMzIzMTkwNFowRTETMBEGA1UE
|
16
16
|
AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
|
17
17
|
JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
|
18
18
|
b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
|
@@ -22,14 +22,14 @@ cert_chain:
|
|
22
22
|
qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
|
23
23
|
gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
|
24
24
|
HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBCwUAA4IB
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
AQCKB5jfsuSnKb+t/Wrh3UpdkmX7TrEsjVmERC0pPqzQ5GQJgmEXDD7oMgaKXaAq
|
26
|
+
x2m+KSZDrqk7c8uho5OX6YMqg4KdxehfSLqqTZGoeV78qwf/jpPQZKTf+W9gUSJh
|
27
|
+
zsWpo4K50MP+QtdSbKXZwjAafpQ8hK0MnnZ/aeCsW9ov5vdXpYbf3dpg6ADXRGE7
|
28
|
+
lQY2y1tJ5/chqu6h7dQmnm2ABUqx9O+JcN9hbCYoA5i/EeubUEtFIh2w3SpO6YfB
|
29
|
+
JFmxn4h9YO/pVdB962BdBNNDia0kgIjI3ENnkLq0dKpYU3+F3KhEuTksLO0L6X/V
|
30
|
+
YsuyUzsMz6GQA4khyaMgKNSD
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date:
|
32
|
+
date: 2022-05-23 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: minitest-server
|
@@ -99,14 +99,14 @@ dependencies:
|
|
99
99
|
requirements:
|
100
100
|
- - "~>"
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version: '3.
|
102
|
+
version: '3.23'
|
103
103
|
type: :development
|
104
104
|
prerelease: false
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '3.
|
109
|
+
version: '3.23'
|
110
110
|
description: |-
|
111
111
|
Hunting down random test failures can be very very difficult,
|
112
112
|
sometimes impossible, but minitest-bisect makes it easy.
|
@@ -160,8 +160,9 @@ files:
|
|
160
160
|
homepage: https://github.com/seattlerb/minitest-bisect
|
161
161
|
licenses:
|
162
162
|
- MIT
|
163
|
-
metadata:
|
164
|
-
|
163
|
+
metadata:
|
164
|
+
homepage_uri: https://github.com/seattlerb/minitest-bisect
|
165
|
+
post_install_message:
|
165
166
|
rdoc_options:
|
166
167
|
- "--main"
|
167
168
|
- README.rdoc
|
@@ -178,8 +179,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
179
|
- !ruby/object:Gem::Version
|
179
180
|
version: '0'
|
180
181
|
requirements: []
|
181
|
-
rubygems_version: 3.
|
182
|
-
signing_key:
|
182
|
+
rubygems_version: 3.3.12
|
183
|
+
signing_key:
|
183
184
|
specification_version: 4
|
184
185
|
summary: Hunting down random test failures can be very very difficult, sometimes impossible,
|
185
186
|
but minitest-bisect makes it easy
|
metadata.gz.sig
CHANGED
Binary file
|