minitest-proptest 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/minitest/proptest/gen/value_generator.rb +1 -1
- data/lib/minitest/proptest/gen.rb +109 -35
- data/lib/minitest/proptest/property.rb +121 -33
- data/lib/minitest/proptest/status.rb +13 -0
- data/lib/minitest/proptest/version.rb +1 -1
- data/lib/minitest/proptest_plugin.rb +6 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61aa3a3421a7b1996cf35540600199e11d18bbf5959d96866f994be97f372bcf
|
4
|
+
data.tar.gz: f89adae15e67f595c56f274d034b18e3e325fe097865ef60f42a7d49f7509214
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c114584acb4f0d59d93958c65e665a5acde52dce3083f1a1343e8cc85962ec11f4e8e582821bf86002cb2e02cfe45d255fe653450944fdc573112168a734520
|
7
|
+
data.tar.gz: 4f23345243cb106aa1fca9e4d9a4c87c6c20e22407e2564990de246cb81c95f96a2e8138a3991121ab24a2b2bfa9bf5066a7cdc3b639f0880d6e1170bd214652
|
@@ -19,8 +19,8 @@ module Minitest
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.with_append(bound_min, bound_max, &f)
|
22
|
-
define_singleton_method(:bound_max) { bound_max }
|
23
22
|
define_singleton_method(:bound_min) { bound_min }
|
23
|
+
define_singleton_method(:bound_max) { bound_max }
|
24
24
|
define_method(:append) do |other|
|
25
25
|
@value = f.call(value, other.value)
|
26
26
|
self
|
@@ -119,28 +119,60 @@ module Minitest
|
|
119
119
|
|
120
120
|
until y == 0
|
121
121
|
candidates << (x - y)
|
122
|
-
candidates << y
|
123
|
-
# Prevent negative integral from preventing termination
|
122
|
+
candidates << y if y.abs < x.abs
|
124
123
|
y = (y / 2.0).to_i
|
125
124
|
end
|
126
125
|
|
127
126
|
candidates
|
128
|
-
|
129
|
-
|
127
|
+
end
|
128
|
+
|
129
|
+
score_float = ->(f) do
|
130
|
+
if f.nan? || f.infinite?
|
131
|
+
0
|
132
|
+
else
|
133
|
+
f.abs.ceil
|
134
|
+
end
|
130
135
|
end
|
131
136
|
|
132
137
|
float_shrink = ->(x) do
|
138
|
+
return [] if x.nan? || x.infinite? || x.zero?
|
139
|
+
|
133
140
|
candidates = [Float::NAN, Float::INFINITY]
|
134
141
|
y = x
|
135
142
|
|
136
|
-
until y
|
143
|
+
until y.zero? || y.to_f.infinite? || y.to_f.nan?
|
137
144
|
candidates << (x - y)
|
138
145
|
y = (y / 2.0).to_i
|
139
146
|
end
|
140
147
|
|
141
|
-
|
142
|
-
|
143
|
-
|
148
|
+
score = score_float.call(x)
|
149
|
+
candidates.reduce([]) do |cs, c|
|
150
|
+
cs + (score_float.call(c) < score ? [c.to_f] : [])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
score_complex = ->(c) do
|
155
|
+
r = if c.real.to_f.nan? || c.real.to_f.infinite?
|
156
|
+
0
|
157
|
+
else
|
158
|
+
c.real.abs.ceil
|
159
|
+
end
|
160
|
+
i = if c.imaginary.to_f.nan? || c.imaginary.to_f.infinite?
|
161
|
+
0
|
162
|
+
else
|
163
|
+
c.imaginary.abs.ceil
|
164
|
+
end
|
165
|
+
r + i
|
166
|
+
end
|
167
|
+
|
168
|
+
complex_shrink = ->(x) do
|
169
|
+
rs = float_shrink.call(x.real)
|
170
|
+
is = float_shrink.call(x.imaginary)
|
171
|
+
|
172
|
+
score = score_complex.call(x)
|
173
|
+
rs.flat_map { |real| is.map { |imag| Complex(real, imag) } }
|
174
|
+
.reject { |c| score_complex.call(c) >= score }
|
175
|
+
.uniq
|
144
176
|
end
|
145
177
|
|
146
178
|
# List shrink adapted from QuickCheck
|
@@ -196,6 +228,34 @@ module Minitest
|
|
196
228
|
end
|
197
229
|
end
|
198
230
|
|
231
|
+
range_shrink = ->(f, r) do
|
232
|
+
xs = f.call(r.first)
|
233
|
+
ys = f.call(r.last)
|
234
|
+
|
235
|
+
xs.flat_map { |x| ys.map { |y| x <= y ? (x..y) : (y..x) } }
|
236
|
+
end
|
237
|
+
|
238
|
+
score_rational = ->(r) do
|
239
|
+
(r.numerator * r.denominator).abs
|
240
|
+
end
|
241
|
+
|
242
|
+
rational_shrink = ->(r) do
|
243
|
+
ns = integral_shrink.call(r.numerator)
|
244
|
+
ds = integral_shrink.call(r.denominator)
|
245
|
+
|
246
|
+
score = score_rational.call(r)
|
247
|
+
ns.flat_map do |n|
|
248
|
+
ds.reduce([]) do |rs, d|
|
249
|
+
if d.zero?
|
250
|
+
rs
|
251
|
+
else
|
252
|
+
rational = Rational(n, d)
|
253
|
+
rs + (score_rational.call(rational) < score ? [rational] : [])
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
199
259
|
hash_shrink = ->(_fk, _fv, h) do
|
200
260
|
candidates = []
|
201
261
|
n = h.length
|
@@ -303,45 +363,36 @@ module Minitest
|
|
303
363
|
.unpack1('f')
|
304
364
|
end.with_shrink_function do |f|
|
305
365
|
float_shrink.call(f)
|
306
|
-
end.with_score_function
|
307
|
-
if f.nan? || f.infinite?
|
308
|
-
0
|
309
|
-
else
|
310
|
-
f.abs.ceil
|
311
|
-
end
|
312
|
-
end
|
366
|
+
end.with_score_function(&score_float)
|
313
367
|
|
314
|
-
|
315
|
-
bits = sized(0xffffffffffffffff)
|
368
|
+
float64build = ->(bits) do
|
316
369
|
(0..7)
|
317
370
|
.map { |y| ((bits & (0xff << (8 * y))) >> (8 * y)).chr }
|
318
371
|
.join
|
319
372
|
.unpack1('d')
|
373
|
+
end
|
374
|
+
|
375
|
+
generator_for(Float64) do
|
376
|
+
bits = sized(0xffffffffffffffff)
|
377
|
+
float64build.call(bits)
|
320
378
|
end.with_shrink_function do |f|
|
321
379
|
float_shrink.call(f)
|
322
|
-
end.with_score_function
|
323
|
-
if f.nan? || f.infinite?
|
324
|
-
0
|
325
|
-
else
|
326
|
-
f.abs.ceil
|
327
|
-
end
|
328
|
-
end
|
380
|
+
end.with_score_function(&score_float)
|
329
381
|
|
330
382
|
generator_for(Float) do
|
331
383
|
bits = sized(0xffffffffffffffff)
|
332
|
-
(
|
333
|
-
.map { |y| ((bits & (0xff << (8 * y))) >> (8 * y)).chr }
|
334
|
-
.join
|
335
|
-
.unpack1('d')
|
384
|
+
float64build.call(bits)
|
336
385
|
end.with_shrink_function do |f|
|
337
386
|
float_shrink.call(f)
|
338
|
-
end.with_score_function
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
end
|
387
|
+
end.with_score_function(&score_float)
|
388
|
+
|
389
|
+
generator_for(Complex) do
|
390
|
+
real = sized(0xffffffffffffffff)
|
391
|
+
imag = sized(0xffffffffffffffff)
|
392
|
+
Complex(float64build.call(real), float64build.call(imag))
|
393
|
+
end.with_shrink_function do |c|
|
394
|
+
complex_shrink.call(c)
|
395
|
+
end.with_score_function(&score_complex)
|
345
396
|
|
346
397
|
generator_for(ASCIIChar) do
|
347
398
|
sized(0x7f).chr
|
@@ -392,6 +443,29 @@ module Minitest
|
|
392
443
|
xm.merge(ym)
|
393
444
|
end.with_empty { {} }
|
394
445
|
|
446
|
+
generator_for(Range) do |x|
|
447
|
+
(x..x)
|
448
|
+
end.with_shrink_function(&range_shrink).with_score_function do |f, r|
|
449
|
+
r.to_a.reduce(1) do |c, x|
|
450
|
+
y = f.call(x).abs
|
451
|
+
c * (y > 0 ? y + 1 : 1)
|
452
|
+
end.to_i * r.to_a.length
|
453
|
+
end.with_append(2, 2) do |ra, rb|
|
454
|
+
xs = [ra.first, ra.last, rb.first, rb.last].sort
|
455
|
+
(xs.first..xs.last)
|
456
|
+
end
|
457
|
+
|
458
|
+
generator_for(Rational) do
|
459
|
+
n = sized(MAX_SIZE)
|
460
|
+
d = sized(MAX_SIZE - 1) + 1
|
461
|
+
if (n & SIGN_BIT).zero?
|
462
|
+
Rational(n, d)
|
463
|
+
else
|
464
|
+
Rational(-(((n & (MAX_SIZE ^ SIGN_BIT)) - 1) ^ (MAX_SIZE ^ SIGN_BIT)), d)
|
465
|
+
end
|
466
|
+
end.with_shrink_function(&rational_shrink)
|
467
|
+
.with_score_function(&score_rational)
|
468
|
+
|
395
469
|
generator_for(Bool) do
|
396
470
|
sized(0x1).odd?
|
397
471
|
end.with_score_function do |_|
|
@@ -4,11 +4,20 @@ module Minitest
|
|
4
4
|
module Proptest
|
5
5
|
# Property evaluation - status, scoring, shrinking
|
6
6
|
class Property
|
7
|
-
|
7
|
+
require 'minitest/assertions'
|
8
|
+
include Minitest::Assertions
|
9
|
+
|
10
|
+
attr_reader :calls, :result, :status, :trivial
|
11
|
+
|
12
|
+
attr_accessor :assertions
|
8
13
|
|
9
14
|
def initialize(
|
10
15
|
# The function which proves the property
|
11
16
|
test_proc,
|
17
|
+
# The file in which our property lives
|
18
|
+
filename,
|
19
|
+
# The method containing our property
|
20
|
+
methodname,
|
12
21
|
# Any class which provides `rand` accepting both an Integer and a Range
|
13
22
|
# is acceptable. The default value is Ruby's standard Mersenne Twister
|
14
23
|
# implementation.
|
@@ -28,6 +37,8 @@ module Minitest
|
|
28
37
|
previous_failure: []
|
29
38
|
)
|
30
39
|
@test_proc = test_proc
|
40
|
+
@filename = filename
|
41
|
+
@methodname = methodname
|
31
42
|
@random = random.call
|
32
43
|
@generator = ::Minitest::Proptest::Gen.new(@random)
|
33
44
|
@max_success = max_success
|
@@ -36,13 +47,16 @@ module Minitest
|
|
36
47
|
@max_shrinks = max_shrinks
|
37
48
|
@status = Status.unknown
|
38
49
|
@trivial = false
|
50
|
+
@valid_test_case = true
|
39
51
|
@result = nil
|
40
52
|
@exception = nil
|
41
53
|
@calls = 0
|
54
|
+
@assertions = 0
|
42
55
|
@valid_test_cases = 0
|
43
56
|
@generated = []
|
44
57
|
@arbitrary = nil
|
45
58
|
@previous_failure = previous_failure.to_a
|
59
|
+
@local_variables = {}
|
46
60
|
end
|
47
61
|
|
48
62
|
def run!
|
@@ -51,17 +65,6 @@ module Minitest
|
|
51
65
|
shrink!
|
52
66
|
end
|
53
67
|
|
54
|
-
def arbitrary(*classes)
|
55
|
-
if @arbitrary
|
56
|
-
@arbitrary.call(*classes)
|
57
|
-
else
|
58
|
-
a = @generator.for(*classes)
|
59
|
-
@generated << a
|
60
|
-
@status = Status.overrun unless @generated.length <= @max_size
|
61
|
-
a.value
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
68
|
def explain
|
66
69
|
prop = if @status.valid?
|
67
70
|
'The property was proved to satsfaction across ' \
|
@@ -77,10 +80,26 @@ module Minitest
|
|
77
80
|
elsif @status.unknown?
|
78
81
|
'The property has not yet been tested.'
|
79
82
|
elsif @status.interesting?
|
80
|
-
'
|
81
|
-
|
82
|
-
|
83
|
-
|
83
|
+
info = 'A counterexample to a property has been found after ' \
|
84
|
+
"#{@valid_test_cases} valid " \
|
85
|
+
"example#{@valid_test_cases == 1 ? '' : 's'}.\n"
|
86
|
+
var_info = if @local_variables.empty?
|
87
|
+
'Variables local to the property were unable ' \
|
88
|
+
'to be determined. This is usually a bug.'
|
89
|
+
else
|
90
|
+
"The values at the time of the failure were:\n"
|
91
|
+
end
|
92
|
+
vars = @local_variables
|
93
|
+
.map { |k, v| "\t#{k}: #{v.inspect}" }
|
94
|
+
.join("\n")
|
95
|
+
|
96
|
+
info + var_info + vars
|
97
|
+
elsif @status.exhausted?
|
98
|
+
"The property was unable to generate #{@max_success} test " \
|
99
|
+
'cases before generating ' \
|
100
|
+
"#{@max_success * @max_discard_ratio} rejected test " \
|
101
|
+
"cases. This might be a problem with the property's " \
|
102
|
+
'`where` blocks.'
|
84
103
|
end
|
85
104
|
trivial = if @trivial
|
86
105
|
"\nThe test does not appear to use any generated values " \
|
@@ -95,18 +114,47 @@ module Minitest
|
|
95
114
|
|
96
115
|
private
|
97
116
|
|
117
|
+
def arbitrary(*classes)
|
118
|
+
if @arbitrary
|
119
|
+
@arbitrary.call(*classes)
|
120
|
+
else
|
121
|
+
a = @generator.for(*classes)
|
122
|
+
@generated << a
|
123
|
+
@status = Status.overrun unless @generated.length <= @max_size
|
124
|
+
a.value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def where(&b)
|
129
|
+
@valid_test_case &= b.call
|
130
|
+
end
|
131
|
+
|
98
132
|
def iterate!
|
99
|
-
while continue_iterate? && @result.nil? && @valid_test_cases <= @max_success
|
133
|
+
while continue_iterate? && @result.nil? && @valid_test_cases <= @max_success
|
134
|
+
@valid_test_case = true
|
100
135
|
@generated = []
|
101
136
|
@generator = ::Minitest::Proptest::Gen.new(@random)
|
102
137
|
@calls += 1
|
103
|
-
|
138
|
+
|
139
|
+
success = begin
|
140
|
+
instance_eval(&@test_proc)
|
141
|
+
rescue Minitest::Assertion
|
142
|
+
if @valid_test_case
|
143
|
+
@result = @generated
|
144
|
+
@status = Status.interesting
|
145
|
+
end
|
146
|
+
rescue => e
|
147
|
+
raise e if @valid_test_case
|
148
|
+
end
|
149
|
+
if @valid_test_case && success
|
104
150
|
@status = Status.valid if @status.unknown?
|
105
151
|
@valid_test_cases += 1
|
106
|
-
|
152
|
+
elsif @valid_test_case
|
107
153
|
@result = @generated
|
108
154
|
@status = Status.interesting
|
109
155
|
end
|
156
|
+
|
157
|
+
@status = Status.exhausted if @calls >= @max_success * (@max_discard_ratio + 1)
|
110
158
|
@trivial = true if @generated.empty?
|
111
159
|
end
|
112
160
|
rescue => e
|
@@ -133,9 +181,20 @@ module Minitest
|
|
133
181
|
end
|
134
182
|
|
135
183
|
@generator = ::Minitest::Proptest::Gen.new(@random)
|
136
|
-
|
184
|
+
success = begin
|
185
|
+
instance_eval(&@test_proc)
|
186
|
+
rescue Minitest::Assertion
|
187
|
+
!@valid_test_case
|
188
|
+
rescue => e
|
189
|
+
if @valid_test_case
|
190
|
+
@status = Status.invalid
|
191
|
+
@exception = e
|
192
|
+
false
|
193
|
+
end
|
194
|
+
end
|
195
|
+
if success || !@valid_test_case
|
137
196
|
@generated = []
|
138
|
-
|
197
|
+
elsif @valid_test_case
|
139
198
|
@result = @generated
|
140
199
|
@status = Status.interesting
|
141
200
|
end
|
@@ -156,6 +215,17 @@ module Minitest
|
|
156
215
|
candidates = @generated.map(&:shrink_candidates)
|
157
216
|
old_arbitrary = @arbitrary
|
158
217
|
|
218
|
+
local_variables = {}
|
219
|
+
tracepoint = TracePoint.new(:b_return) do |trace|
|
220
|
+
if trace.path == @filename && trace.method_id.to_s == @methodname
|
221
|
+
b = trace.binding
|
222
|
+
vs = b.local_variables
|
223
|
+
known = vs.to_h { |lv| [lv.to_s, b.local_variable_get(lv)] }
|
224
|
+
local_variables.delete_if { true }
|
225
|
+
local_variables.merge!(known)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
159
229
|
to_test = candidates
|
160
230
|
.map { |x| x.map { |y| [y] } }
|
161
231
|
.reduce { |c, e| c.flat_map { |a| e.map { |b| a + b } } }
|
@@ -174,15 +244,31 @@ module Minitest
|
|
174
244
|
end
|
175
245
|
|
176
246
|
while continue_shrink? && run[:run] < to_test.length
|
177
|
-
@generated
|
178
|
-
run[:index]
|
247
|
+
@generated = []
|
248
|
+
run[:index] = -1
|
249
|
+
@valid_test_case = true
|
179
250
|
|
180
251
|
@generator = ::Minitest::Proptest::Gen.new(@random)
|
181
252
|
if to_test[run[:run]].map(&:first).reduce(&:+) < best_score
|
182
|
-
|
183
|
-
|
184
|
-
|
253
|
+
success = begin
|
254
|
+
tracepoint.enable
|
255
|
+
instance_eval(&@test_proc)
|
256
|
+
rescue Minitest::Assertion
|
257
|
+
false
|
258
|
+
rescue => e
|
259
|
+
next unless @valid_test_case
|
260
|
+
|
261
|
+
@status = Status.invalid
|
262
|
+
@excption = e
|
263
|
+
break
|
264
|
+
ensure
|
265
|
+
tracepoint.disable
|
266
|
+
end
|
267
|
+
|
268
|
+
if !success && @valid_test_case
|
269
|
+
# The first hit is guaranteed to be the best scoring since the
|
185
270
|
# shrink candidates are pre-sorted.
|
271
|
+
best_generated = @generated
|
186
272
|
break
|
187
273
|
end
|
188
274
|
end
|
@@ -190,20 +276,22 @@ module Minitest
|
|
190
276
|
@calls += 1
|
191
277
|
run[:run] += 1
|
192
278
|
end
|
279
|
+
|
193
280
|
# Clean up after we're done
|
194
|
-
@generated
|
195
|
-
@result
|
196
|
-
@generator
|
197
|
-
@random
|
198
|
-
@arbitrary
|
281
|
+
@generated = best_generated
|
282
|
+
@result = best_generated
|
283
|
+
@generator = old_generator
|
284
|
+
@random = old_random
|
285
|
+
@arbitrary = old_arbitrary
|
286
|
+
@local_variables = local_variables
|
199
287
|
end
|
200
288
|
|
201
289
|
def continue_iterate?
|
202
290
|
!@trivial &&
|
203
291
|
!@status.invalid? &&
|
204
292
|
!@status.overrun? &&
|
205
|
-
|
206
|
-
@
|
293
|
+
!@status.exhausted? &&
|
294
|
+
@valid_test_cases < @max_success
|
207
295
|
end
|
208
296
|
|
209
297
|
def continue_shrink?
|
@@ -4,6 +4,10 @@ module Minitest
|
|
4
4
|
module Proptest
|
5
5
|
# Sum type representing the possible statuses of a test run.
|
6
6
|
# Invalid, Overrun, and Interesting represent different failure classes.
|
7
|
+
# Exhausted represents having generated too many invalid test cases to
|
8
|
+
# verify the property. This precipitates as a failure class (the property is
|
9
|
+
# not proved) but can be a matter of inappropriate predicates in `where`
|
10
|
+
# blocks.
|
7
11
|
# Unknown represents a lack of information about the test run (typically
|
8
12
|
# having not run to satisfaction).
|
9
13
|
# Valid represents a test which has run to satisfaction.
|
@@ -23,16 +27,21 @@ module Minitest
|
|
23
27
|
class Valid < Status
|
24
28
|
end
|
25
29
|
|
30
|
+
class Exhausted < Status
|
31
|
+
end
|
32
|
+
|
26
33
|
invalid = Invalid.new.freeze
|
27
34
|
interesting = Interesting.new.freeze
|
28
35
|
overrun = Overrun.new.freeze
|
29
36
|
unknown = Unknown.new.freeze
|
37
|
+
exhausted = Exhausted.new.freeze
|
30
38
|
valid = Valid.new.freeze
|
31
39
|
|
32
40
|
define_singleton_method(:invalid) { invalid }
|
33
41
|
define_singleton_method(:interesting) { interesting }
|
34
42
|
define_singleton_method(:overrun) { overrun }
|
35
43
|
define_singleton_method(:unknown) { unknown }
|
44
|
+
define_singleton_method(:exhausted) { exhausted }
|
36
45
|
define_singleton_method(:valid) { valid }
|
37
46
|
|
38
47
|
def invalid?
|
@@ -47,6 +56,10 @@ module Minitest
|
|
47
56
|
self.is_a?(Unknown)
|
48
57
|
end
|
49
58
|
|
59
|
+
def exhausted?
|
60
|
+
self.is_a?(Exhausted)
|
61
|
+
end
|
62
|
+
|
50
63
|
def valid?
|
51
64
|
self.is_a?(Valid)
|
52
65
|
end
|
@@ -50,8 +50,6 @@ module Minitest
|
|
50
50
|
|
51
51
|
module Assertions
|
52
52
|
def property(&f)
|
53
|
-
self.assertions += 1
|
54
|
-
|
55
53
|
random_thunk = if Proptest.instance_variable_defined?(:@_random_seed)
|
56
54
|
r = Proptest.instance_variable_get(:@_random_seed)
|
57
55
|
->() { Proptest::DEFAULT_RANDOM.call(r) }
|
@@ -65,6 +63,8 @@ module Minitest
|
|
65
63
|
|
66
64
|
prop = Minitest::Proptest::Property.new(
|
67
65
|
f,
|
66
|
+
file,
|
67
|
+
methodname,
|
68
68
|
random: random_thunk,
|
69
69
|
max_success: Proptest.max_success,
|
70
70
|
max_discard_ratio: Proptest.max_discard_ratio,
|
@@ -73,11 +73,14 @@ module Minitest
|
|
73
73
|
previous_failure: Proptest.reporter.lookup(file, classname, methodname)
|
74
74
|
)
|
75
75
|
prop.run!
|
76
|
+
self.assertions += prop.calls
|
76
77
|
|
77
78
|
if prop.status.valid? && !prop.trivial
|
78
79
|
Proptest.strike_failure(file, classname, methodname)
|
79
80
|
else
|
80
|
-
|
81
|
+
unless prop.status.exhausted? || prop.status.invalid?
|
82
|
+
Proptest.record_failure(file, classname, methodname, prop.result.map(&:value))
|
83
|
+
end
|
81
84
|
|
82
85
|
raise Minitest::Assertion, prop.explain
|
83
86
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-proptest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tina Wuest
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|