minitest-proptest 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0596e6f6a66614dba0199eccc4e18a5bf6b869fd0db46dff7636a8772eacb75b'
4
- data.tar.gz: a956c579c5bb355a5b687f64109917918870dd7dac1323a18a72d44e4ca623a6
3
+ metadata.gz: 61aa3a3421a7b1996cf35540600199e11d18bbf5959d96866f994be97f372bcf
4
+ data.tar.gz: f89adae15e67f595c56f274d034b18e3e325fe097865ef60f42a7d49f7509214
5
5
  SHA512:
6
- metadata.gz: d6206c7a778b9b55e0674e204afea71721eb8b6e4fe2257691cc1cefd5e76885eff08d648f9a61172806872f1abe5f1b232186fcc803e6fcc560241fd71fac8c
7
- data.tar.gz: 1ca1d04ddcdecb9f661e0af6cffc87dda30af6a9b06bb6fe406a5f27ec445a0cf3cd9ac4d9050b4a243ab40d76d066358f6cf9612181cc546a2076b76a7d9041
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
- 'The property has found the following counterexample after ' \
92
- "#{@valid_test_cases} valid " \
93
- "example#{@valid_test_cases == 1 ? '' : 's'}:\n" \
94
- "#{@generated.map(&:value).inspect}"
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 due to the
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 = best_generated
250
- @result = best_generated
251
- @generator = old_generator
252
- @random = old_random
253
- @arbitrary = old_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?
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Minitest
4
4
  module Proptest
5
- VERSION = '0.2.0'
5
+ VERSION = '0.2.1'
6
6
  end
7
7
  end
@@ -63,6 +63,8 @@ module Minitest
63
63
 
64
64
  prop = Minitest::Proptest::Property.new(
65
65
  f,
66
+ file,
67
+ methodname,
66
68
  random: random_thunk,
67
69
  max_success: Proptest.max_success,
68
70
  max_discard_ratio: Proptest.max_discard_ratio,
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.0
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-03-21 00:00:00.000000000 Z
11
+ date: 2024-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest