minitest-proptest 0.2.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/property.rb +58 -25
- data/lib/minitest/proptest/version.rb +1 -1
- data/lib/minitest/proptest_plugin.rb +2 -0
- 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
|
@@ -14,6 +14,10 @@ module Minitest
|
|
14
14
|
def initialize(
|
15
15
|
# The function which proves the property
|
16
16
|
test_proc,
|
17
|
+
# The file in which our property lives
|
18
|
+
filename,
|
19
|
+
# The method containing our property
|
20
|
+
methodname,
|
17
21
|
# Any class which provides `rand` accepting both an Integer and a Range
|
18
22
|
# is acceptable. The default value is Ruby's standard Mersenne Twister
|
19
23
|
# implementation.
|
@@ -33,6 +37,8 @@ module Minitest
|
|
33
37
|
previous_failure: []
|
34
38
|
)
|
35
39
|
@test_proc = test_proc
|
40
|
+
@filename = filename
|
41
|
+
@methodname = methodname
|
36
42
|
@random = random.call
|
37
43
|
@generator = ::Minitest::Proptest::Gen.new(@random)
|
38
44
|
@max_success = max_success
|
@@ -50,6 +56,7 @@ module Minitest
|
|
50
56
|
@generated = []
|
51
57
|
@arbitrary = nil
|
52
58
|
@previous_failure = previous_failure.to_a
|
59
|
+
@local_variables = {}
|
53
60
|
end
|
54
61
|
|
55
62
|
def run!
|
@@ -58,21 +65,6 @@ module Minitest
|
|
58
65
|
shrink!
|
59
66
|
end
|
60
67
|
|
61
|
-
def arbitrary(*classes)
|
62
|
-
if @arbitrary
|
63
|
-
@arbitrary.call(*classes)
|
64
|
-
else
|
65
|
-
a = @generator.for(*classes)
|
66
|
-
@generated << a
|
67
|
-
@status = Status.overrun unless @generated.length <= @max_size
|
68
|
-
a.value
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def where(&b)
|
73
|
-
@valid_test_case &= b.call
|
74
|
-
end
|
75
|
-
|
76
68
|
def explain
|
77
69
|
prop = if @status.valid?
|
78
70
|
'The property was proved to satsfaction across ' \
|
@@ -88,10 +80,20 @@ module Minitest
|
|
88
80
|
elsif @status.unknown?
|
89
81
|
'The property has not yet been tested.'
|
90
82
|
elsif @status.interesting?
|
91
|
-
'
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
95
97
|
elsif @status.exhausted?
|
96
98
|
"The property was unable to generate #{@max_success} test " \
|
97
99
|
'cases before generating ' \
|
@@ -112,6 +114,21 @@ module Minitest
|
|
112
114
|
|
113
115
|
private
|
114
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
|
+
|
115
132
|
def iterate!
|
116
133
|
while continue_iterate? && @result.nil? && @valid_test_cases <= @max_success
|
117
134
|
@valid_test_case = true
|
@@ -198,6 +215,17 @@ module Minitest
|
|
198
215
|
candidates = @generated.map(&:shrink_candidates)
|
199
216
|
old_arbitrary = @arbitrary
|
200
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
|
+
|
201
229
|
to_test = candidates
|
202
230
|
.map { |x| x.map { |y| [y] } }
|
203
231
|
.reduce { |c, e| c.flat_map { |a| e.map { |b| a + b } } }
|
@@ -223,6 +251,7 @@ module Minitest
|
|
223
251
|
@generator = ::Minitest::Proptest::Gen.new(@random)
|
224
252
|
if to_test[run[:run]].map(&:first).reduce(&:+) < best_score
|
225
253
|
success = begin
|
254
|
+
tracepoint.enable
|
226
255
|
instance_eval(&@test_proc)
|
227
256
|
rescue Minitest::Assertion
|
228
257
|
false
|
@@ -232,10 +261,12 @@ module Minitest
|
|
232
261
|
@status = Status.invalid
|
233
262
|
@excption = e
|
234
263
|
break
|
264
|
+
ensure
|
265
|
+
tracepoint.disable
|
235
266
|
end
|
236
267
|
|
237
268
|
if !success && @valid_test_case
|
238
|
-
# The first hit is guaranteed to be the best scoring
|
269
|
+
# The first hit is guaranteed to be the best scoring since the
|
239
270
|
# shrink candidates are pre-sorted.
|
240
271
|
best_generated = @generated
|
241
272
|
break
|
@@ -245,12 +276,14 @@ module Minitest
|
|
245
276
|
@calls += 1
|
246
277
|
run[:run] += 1
|
247
278
|
end
|
279
|
+
|
248
280
|
# Clean up after we're done
|
249
|
-
@generated
|
250
|
-
@result
|
251
|
-
@generator
|
252
|
-
@random
|
253
|
-
@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
|
254
287
|
end
|
255
288
|
|
256
289
|
def continue_iterate?
|
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.2.
|
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
|