prop_check 0.6.1 → 0.6.2
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/.travis.yml +12 -1
- data/Gemfile.lock +1 -1
- data/README.md +8 -0
- data/lib/prop_check.rb +16 -4
- data/lib/prop_check/generators.rb +87 -15
- data/lib/prop_check/helper/lazy_append.rb +18 -0
- data/lib/prop_check/lazy_tree.rb +4 -13
- data/lib/prop_check/property.rb +49 -7
- data/lib/prop_check/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4beba1b773706a7e7f75696a7040667172e44646246dc9ccdbc87faa03f70f55
|
4
|
+
data.tar.gz: 2c6e0c8aabc7c9c69da74c11ad2e79461ed5f6e1c5e550b0eb32923366f84c84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25a28c29aaedcfcff34a5fa8f3c7164b6df7536eed2134416467dd46b7c8502530c6511cf6b54d0ca2f1b8ee3b59ffaa62dc6a132667a0179f0dbead7fcf6b41
|
7
|
+
data.tar.gz: d9d9790f110d56920570e25d2ed2b6ee0657ec99bc46b509593215405fe19de6545ecaa990a096fd75259d9122c7a7404a9f2e6194cc808707ed01f8489201ed
|
data/.travis.yml
CHANGED
@@ -4,4 +4,15 @@ language: ruby
|
|
4
4
|
cache: bundler
|
5
5
|
rvm:
|
6
6
|
- 2.5.1
|
7
|
-
before_install: gem install bundler -v 2.0.
|
7
|
+
before_install: gem install bundler -v 2.0.2
|
8
|
+
env:
|
9
|
+
global:
|
10
|
+
- CC_TEST_REPORTER_ID=9d18f5b43e49eecd6c3da64d85ea9c765d3606c129289d7c8cadf6d448713311
|
11
|
+
before_script:
|
12
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
13
|
+
- chmod +x ./cc-test-reporter
|
14
|
+
- ./cc-test-reporter before-build
|
15
|
+
script:
|
16
|
+
- bundle exec rspec
|
17
|
+
after_script:
|
18
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
PropCheck allows you to do Property Testing in Ruby.
|
4
4
|
|
5
|
+
[](https://rubygems.org/gems/prop_check)
|
6
|
+
[](https://travis-ci.org/Qqwy/ruby-prop_check)
|
7
|
+
[](https://codeclimate.com/github/Qqwy/ruby-prop_check/maintainability)
|
8
|
+
[](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/PropCheck)
|
9
|
+
|
5
10
|
It features:
|
6
11
|
|
7
12
|
- Generators for common datatypes.
|
@@ -157,6 +162,9 @@ you can use `Generators.frequency` which takes a hash of (integer_frequency => g
|
|
157
162
|
There are even more functions in the `Generator` class and the `Generators` module that you might want to use,
|
158
163
|
although above are the most generally useful ones.
|
159
164
|
|
165
|
+
[PropCheck::Generator documentation](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/PropCheck/Generator)
|
166
|
+
[PropCheck::Generators documentation](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/PropCheck/Generators)
|
167
|
+
|
160
168
|
## Development
|
161
169
|
|
162
170
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/prop_check.rb
CHANGED
@@ -3,14 +3,26 @@ require 'prop_check/property'
|
|
3
3
|
require 'prop_check/generator'
|
4
4
|
require 'prop_check/generators'
|
5
5
|
require 'prop_check/helper'
|
6
|
+
##
|
7
|
+
# Main module of the PropCheck library.
|
8
|
+
#
|
9
|
+
# You probably want to look at the documentation of
|
10
|
+
# PropCheck::Generator and PropCheck::Generators
|
11
|
+
# to find out more about how to use generators.
|
6
12
|
module PropCheck
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
module Errors
|
14
|
+
class Error < StandardError; end
|
15
|
+
class UserError < Error; end
|
16
|
+
class GeneratorExhaustedError < UserError; end
|
17
|
+
class MaxShrinkStepsExceededError < UserError; end
|
18
|
+
end
|
11
19
|
|
12
20
|
extend self
|
13
21
|
|
22
|
+
##
|
23
|
+
# Runs a property.
|
24
|
+
#
|
25
|
+
# See the README for more details.
|
14
26
|
def forall(*args, **kwargs, &block)
|
15
27
|
PropCheck::Property.forall(*args, **kwargs, &block)
|
16
28
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'prop_check/generator'
|
2
5
|
require 'prop_check/lazy_tree'
|
3
6
|
module PropCheck
|
@@ -116,27 +119,40 @@ module PropCheck
|
|
116
119
|
end
|
117
120
|
|
118
121
|
##
|
119
|
-
# Generates floating
|
122
|
+
# Generates floating-point numbers
|
120
123
|
# These start small (around 0)
|
121
124
|
# and become more extreme (large positive and large negative numbers)
|
122
125
|
#
|
126
|
+
# Will only generate 'reals',
|
127
|
+
# that is: no infinity, no NaN,
|
128
|
+
# no numbers testing the limits of floating-point arithmetic.
|
123
129
|
#
|
124
130
|
# Shrinks to numbers closer to zero.
|
125
131
|
#
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
# integer.bind do |b|
|
130
|
-
# integer.bind do |c|
|
131
|
-
# Generator.wrap(fraction(a, b, c))
|
132
|
-
# end
|
133
|
-
# end
|
134
|
-
# end
|
132
|
+
# >> Generators.real_float().sample(10, size: 10, rng: Random.new(42))
|
133
|
+
# => [-2.2, -0.2727272727272727, 4.0, 1.25, -3.7272727272727275, -8.833333333333334, -8.090909090909092, 1.1428571428571428, 0.0, 8.0]
|
134
|
+
def real_float
|
135
135
|
tuple(integer, integer, integer).map do |a, b, c|
|
136
136
|
fraction(a, b, c)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
+
@special_floats = [Float::NAN, Float::INFINITY, -Float::INFINITY, Float::MAX, Float::MIN, 0.0.next_float, 0.0.prev_float]
|
141
|
+
##
|
142
|
+
# Generates floating-point numbers
|
143
|
+
# Will generate NaN, Infinity, -Infinity,
|
144
|
+
# as well as Float::EPSILON, Float::MAX, Float::MIN,
|
145
|
+
# 0.0.next_float, 0.0.prev_float,
|
146
|
+
# to test the handling of floating-point edge cases.
|
147
|
+
# Approx. 1/100 generated numbers is a special one.
|
148
|
+
#
|
149
|
+
# Shrinks to smaller, real floats.
|
150
|
+
# >> Generators.float().sample(10, size: 10, rng: Random.new(42))
|
151
|
+
# => [4.0, 9.555555555555555, 0.0, -Float::INFINITY, 5.5, -5.818181818181818, 1.1428571428571428, 0.0, 8.0, 7.857142857142858]
|
152
|
+
def float
|
153
|
+
frequency(99 => real_float, 1 => one_of(*@special_floats.map(&method(:constant))))
|
154
|
+
end
|
155
|
+
|
140
156
|
##
|
141
157
|
# Picks one of the given generators in `choices` at random uniformly every time.
|
142
158
|
#
|
@@ -156,6 +172,9 @@ module PropCheck
|
|
156
172
|
# (representing the relative frequency of this generator)
|
157
173
|
# and values to be generators.
|
158
174
|
#
|
175
|
+
# Side note: If you want to use the same frequency number for multiple generators,
|
176
|
+
# Ruby syntax requires you to send an array of two-element arrays instead of a hash.
|
177
|
+
#
|
159
178
|
# Shrinks to arbitrary elements (since hashes are not ordered).
|
160
179
|
#
|
161
180
|
# >> Generators.frequency(5 => Generators.integer, 1 => Generators.printable_ascii_char).sample(size: 10, rng: Random.new(42))
|
@@ -174,7 +193,7 @@ module PropCheck
|
|
174
193
|
#
|
175
194
|
# Shrinks element generators, one at a time (trying last one first).
|
176
195
|
#
|
177
|
-
# >> Generators.tuple(Generators.integer, Generators.
|
196
|
+
# >> Generators.tuple(Generators.integer, Generators.real_float).call(10, Random.new(42))
|
178
197
|
# => [-4, 13.0]
|
179
198
|
def tuple(*generators)
|
180
199
|
Generator.new do |size, rng|
|
@@ -191,7 +210,7 @@ module PropCheck
|
|
191
210
|
#
|
192
211
|
# Shrinks element generators.
|
193
212
|
#
|
194
|
-
# >> Generators.fixed_hash(a: Generators.integer(), b: Generators.
|
213
|
+
# >> Generators.fixed_hash(a: Generators.integer(), b: Generators.real_float(), c: Generators.integer()).call(10, Random.new(42))
|
195
214
|
# => {:a=>-4, :b=>13.0, :c=>-3}
|
196
215
|
def fixed_hash(hash)
|
197
216
|
keypair_generators =
|
@@ -242,7 +261,9 @@ module PropCheck
|
|
242
261
|
# containing one of a..z, A..Z, 0..9
|
243
262
|
#
|
244
263
|
# Shrinks towards lowercase 'a'.
|
245
|
-
#
|
264
|
+
#
|
265
|
+
# >> Generators.alphanumeric_char.sample(5, size: 10, rng: Random.new(42))
|
266
|
+
# => ["M", "Z", "C", "o", "Q"]
|
246
267
|
def alphanumeric_char
|
247
268
|
one_of(*@alphanumeric_chars.map(&method(:constant)))
|
248
269
|
end
|
@@ -250,7 +271,11 @@ module PropCheck
|
|
250
271
|
##
|
251
272
|
# Generates a string
|
252
273
|
# containing only the characters a..z, A..Z, 0..9
|
274
|
+
#
|
253
275
|
# Shrinks towards fewer characters, and towards lowercase 'a'.
|
276
|
+
#
|
277
|
+
# >> Generators.alphanumeric_string.sample(5, size: 10, rng: Random.new(42))
|
278
|
+
# => ["ZCoQ", "8uM", "wkkx0JNx", "v0bxRDLb", "Gl5v8RyWA6"]
|
254
279
|
def alphanumeric_string
|
255
280
|
array(alphanumeric_char).map(&:join)
|
256
281
|
end
|
@@ -272,7 +297,11 @@ module PropCheck
|
|
272
297
|
##
|
273
298
|
# Generates strings
|
274
299
|
# from the printable ASCII character set.
|
300
|
+
#
|
275
301
|
# Shrinks towards fewer characters, and towards ' '.
|
302
|
+
#
|
303
|
+
# >> Generators.printable_ascii_string.sample(5, size: 10, rng: Random.new(42))
|
304
|
+
# => ["S|.g", "rvjjw7\"5T!", "=", "!_[4@", "Y"]
|
276
305
|
def printable_ascii_string
|
277
306
|
array(printable_ascii_char).map(&:join)
|
278
307
|
end
|
@@ -295,7 +324,11 @@ module PropCheck
|
|
295
324
|
##
|
296
325
|
# Generates a single-character string
|
297
326
|
# from the printable ASCII character set.
|
327
|
+
#
|
298
328
|
# Shrinks towards '\n'.
|
329
|
+
#
|
330
|
+
# >> Generators.ascii_char.sample(size: 10, rng: Random.new(42))
|
331
|
+
# => ["d", "S", "|", ".", "g", "\\", "4", "d", "r", "v"]
|
299
332
|
def ascii_char
|
300
333
|
one_of(*@ascii_chars.map(&method(:constant)))
|
301
334
|
end
|
@@ -303,7 +336,11 @@ module PropCheck
|
|
303
336
|
##
|
304
337
|
# Generates strings
|
305
338
|
# from the printable ASCII character set.
|
339
|
+
#
|
306
340
|
# Shrinks towards fewer characters, and towards '\n'.
|
341
|
+
#
|
342
|
+
# >> Generators.ascii_string.sample(5, size: 10, rng: Random.new(42))
|
343
|
+
# => ["S|.g", "drvjjw\b\a7\"", "!w=E!_[4@k", "x", "zZI{[o"]
|
307
344
|
def ascii_string
|
308
345
|
array(ascii_char).map(&:join)
|
309
346
|
end
|
@@ -321,6 +358,8 @@ module PropCheck
|
|
321
358
|
#
|
322
359
|
# Shrinks towards characters with lower codepoints, e.g. ASCII
|
323
360
|
#
|
361
|
+
# >> Generators.printable_char.sample(size: 10, rng: Random.new(42))
|
362
|
+
# => ["吏", "", "", "", "", "", "", "", "", "Ȍ"]
|
324
363
|
def printable_char
|
325
364
|
one_of(*@printable_chars.map(&method(:constant)))
|
326
365
|
end
|
@@ -331,6 +370,8 @@ module PropCheck
|
|
331
370
|
#
|
332
371
|
# Shrinks towards shorter strings, and towards characters with lower codepoints, e.g. ASCII
|
333
372
|
#
|
373
|
+
# >> Generators.printable_string.sample(5, size: 10, rng: Random.new(42))
|
374
|
+
# => ["", "Ȍ", "𐁂", "Ȕ", ""]
|
334
375
|
def printable_string
|
335
376
|
array(printable_char).map(&:join)
|
336
377
|
end
|
@@ -341,6 +382,8 @@ module PropCheck
|
|
341
382
|
#
|
342
383
|
# Shrinks towards characters with lower codepoints, e.g. ASCII
|
343
384
|
#
|
385
|
+
# >> Generators.printable_char.sample(size: 10, rng: Random.new(42))
|
386
|
+
# => ["吏", "", "", "", "", "", "", "", "", "Ȍ"]
|
344
387
|
def char
|
345
388
|
choose(0..0x10FFFF).map do |num|
|
346
389
|
[num].pack('U')
|
@@ -353,6 +396,8 @@ module PropCheck
|
|
353
396
|
#
|
354
397
|
# Shrinks towards characters with lower codepoints, e.g. ASCII
|
355
398
|
#
|
399
|
+
# >> Generators.string.sample(5, size: 10, rng: Random.new(42))
|
400
|
+
# => ["\u{A3DB3}𠍜\u{3F46A}\u{1AEBC}", "𡡹\u{DED74}𪱣\u{43E97}ꂂ\u{50695}\u{C0301}", "\u{4FD9D}", "\u{C14BF}\u{193BB}𭇋\u{76B58}", "𦐺\u{9FDDB}\u{80ABB}\u{9E3CF}𐂽\u{14AAE}"]
|
356
401
|
def string
|
357
402
|
array(char).map(&:join)
|
358
403
|
end
|
@@ -361,7 +406,9 @@ module PropCheck
|
|
361
406
|
# Generates either `true` or `false`
|
362
407
|
#
|
363
408
|
# Shrinks towards `false`
|
364
|
-
#
|
409
|
+
#
|
410
|
+
# >> Generators.boolean.sample(5, size: 10, rng: Random.new(42))
|
411
|
+
# => [false, true, false, false, false]
|
365
412
|
def boolean
|
366
413
|
one_of(constant(false), constant(true))
|
367
414
|
end
|
@@ -370,6 +417,9 @@ module PropCheck
|
|
370
417
|
# Generates always `nil`.
|
371
418
|
#
|
372
419
|
# Does not shrink.
|
420
|
+
#
|
421
|
+
# >> Generators.nil.sample(5, size: 10, rng: Random.new(42))
|
422
|
+
# => [nil, nil, nil, nil, nil]
|
373
423
|
def nil
|
374
424
|
constant(nil)
|
375
425
|
end
|
@@ -379,15 +429,34 @@ module PropCheck
|
|
379
429
|
#
|
380
430
|
# Shrinks towards `nil`.
|
381
431
|
#
|
432
|
+
# >> Generators.falsey.sample(5, size: 10, rng: Random.new(42))
|
433
|
+
# => [nil, false, nil, nil, nil]
|
382
434
|
def falsey
|
383
435
|
one_of(constant(nil), constant(false))
|
384
436
|
end
|
385
437
|
|
438
|
+
##
|
439
|
+
# Generates symbols consisting of lowercase letters and potentially underscores.
|
440
|
+
#
|
441
|
+
# Shrinks towards shorter symbols and the letter 'a'.
|
442
|
+
#
|
443
|
+
# >> Generators.simple_symbol.sample(5, size: 10, rng: Random.new(42))
|
444
|
+
# => [:tokh, :gzswkkxudh, :vubxlfbu, :lzvlyq__jp, :oslw]
|
445
|
+
def simple_symbol
|
446
|
+
alphabet = ('a'..'z').to_a
|
447
|
+
alphabet << '_'
|
448
|
+
array(one_of(*alphabet.map(&method(:constant))))
|
449
|
+
.map(&:join)
|
450
|
+
.map(&:to_sym)
|
451
|
+
end
|
452
|
+
|
386
453
|
##
|
387
454
|
# Generates common terms that are not `nil` or `false`.
|
388
455
|
#
|
389
456
|
# Shrinks towards simpler terms, like `true`, an empty array, a single character or an integer.
|
390
457
|
#
|
458
|
+
# >> Generators.truthy.sample(5, size: 10, rng: Random.new(42))
|
459
|
+
# => [[4, 0, -3, 10, -4, 8, 0, 0, 10], -3, [5.5, -5.818181818181818, 1.1428571428571428, 0.0, 8.0, 7.857142857142858, -0.6666666666666665, 5.25], [], ["\u{9E553}\u{DD56E}\u{A5BBB}\u{8BDAB}\u{3E9FC}\u{C4307}\u{DAFAE}\u{1A022}\u{938CD}\u{70631}", "\u{C4C01}\u{32D85}\u{425DC}"]]
|
391
460
|
def truthy
|
392
461
|
one_of(constant(true),
|
393
462
|
constant([]),
|
@@ -399,7 +468,7 @@ module PropCheck
|
|
399
468
|
array(float),
|
400
469
|
array(char),
|
401
470
|
array(string),
|
402
|
-
hash(
|
471
|
+
hash(simple_symbol, integer),
|
403
472
|
hash(string, integer),
|
404
473
|
hash(string, string)
|
405
474
|
)
|
@@ -408,6 +477,9 @@ module PropCheck
|
|
408
477
|
##
|
409
478
|
# Generates whatever `other_generator` generates
|
410
479
|
# but sometimes instead `nil`.`
|
480
|
+
#
|
481
|
+
# >> Generators.nillable(Generators.integer).sample(20, size: 10, rng: Random.new(42))
|
482
|
+
# => [9, 10, 8, 0, 10, -3, -8, 10, 1, -9, -10, nil, 1, 6, nil, 1, 9, -8, 8, 10]
|
411
483
|
def nillable(other_generator)
|
412
484
|
frequency(9 => other_generator, 1 => constant(nil))
|
413
485
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PropCheck
|
2
|
+
module Helper
|
3
|
+
##
|
4
|
+
# A refinement for enumerators
|
5
|
+
# to allow lazy appending of two (potentially lazy) enumerators:
|
6
|
+
# >> [1,2,3].lazy_append([4,5.6]).to_a
|
7
|
+
# => [1,2,3,4,5,6]
|
8
|
+
module LazyAppend
|
9
|
+
refine Enumerable do
|
10
|
+
## >> [1,2,3].lazy_append([4,5.6]).to_a
|
11
|
+
## => [1,2,3,4,5,6]
|
12
|
+
def lazy_append(other_enumerator)
|
13
|
+
[self, other_enumerator].lazy.flat_map(&:lazy)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/prop_check/lazy_tree.rb
CHANGED
@@ -1,22 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
module LazyAppend
|
5
|
-
refine Enumerable do
|
6
|
-
## >> [1,2,3].lazy_append([4,5.6]).to_a
|
7
|
-
## => [1,2,3,4,5,6]
|
8
|
-
def lazy_append(other_enumerator)
|
9
|
-
[self, other_enumerator].lazy.flat_map(&:lazy)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prop_check/helper/lazy_append'
|
13
4
|
|
14
5
|
module PropCheck
|
15
6
|
##
|
16
7
|
# A Rose tree with the root being eager,
|
17
8
|
# and the children computed lazily, on demand.
|
18
9
|
class LazyTree
|
19
|
-
using LazyAppend
|
10
|
+
using PropCheck::Helper::LazyAppend
|
20
11
|
|
21
12
|
attr_accessor :root, :children
|
22
13
|
def initialize(root, children = [].lazy)
|
data/lib/prop_check/property.rb
CHANGED
@@ -3,8 +3,19 @@ require 'stringio'
|
|
3
3
|
require 'prop_check/property/configuration'
|
4
4
|
require 'prop_check/property/check_evaluator'
|
5
5
|
module PropCheck
|
6
|
+
##
|
7
|
+
# Run properties
|
6
8
|
class Property
|
7
9
|
|
10
|
+
##
|
11
|
+
# Call this with a keyword argument list of (symbol => generators) and a block.
|
12
|
+
# The block will then be executed many times, with the respective symbol names
|
13
|
+
# being defined as having a single generated value.
|
14
|
+
#
|
15
|
+
# If you do not pass a block right away,
|
16
|
+
# a Property object is returned, which you can call the other instance methods
|
17
|
+
# of this class on before finally passing a block to it using `#check`.
|
18
|
+
# (so `forall(a: Generators.integer) do ... end` and forall(a: Generators.integer).check do ... end` are the same)
|
8
19
|
def self.forall(**bindings, &block)
|
9
20
|
|
10
21
|
property = new(bindings)
|
@@ -14,10 +25,19 @@ module PropCheck
|
|
14
25
|
property
|
15
26
|
end
|
16
27
|
|
28
|
+
##
|
29
|
+
# Returns the default configuration of the library as it is configured right now
|
30
|
+
# for introspection.
|
31
|
+
#
|
32
|
+
# For the configuration of a single property, check its `configuration` instance method.
|
33
|
+
# See PropCheck::Property::Configuration for more info on available settings.
|
17
34
|
def self.configuration
|
18
35
|
@configuration ||= Configuration.new
|
19
36
|
end
|
20
37
|
|
38
|
+
##
|
39
|
+
# Yields the library's configuration object for you to alter.
|
40
|
+
# See PropCheck::Property::Configuration for more info on available settings.
|
21
41
|
def self.configure
|
22
42
|
yield(configuration)
|
23
43
|
end
|
@@ -32,10 +52,22 @@ module PropCheck
|
|
32
52
|
@config = self.class.configuration
|
33
53
|
end
|
34
54
|
|
55
|
+
##
|
56
|
+
# Returns the configuration of this property
|
57
|
+
# for introspection.
|
58
|
+
#
|
59
|
+
# See PropCheck::Property::Configuration for more info on available settings.
|
35
60
|
def configuration
|
36
61
|
@config
|
37
62
|
end
|
38
63
|
|
64
|
+
##
|
65
|
+
# Allows you to override the configuration of this property
|
66
|
+
# by giving a hash with new settings.
|
67
|
+
#
|
68
|
+
# If no other changes need to occur before you want to check the property,
|
69
|
+
# you can immediately pass a block to this method.
|
70
|
+
# (so `forall(a: Generators.integer).with_config(verbose: true) do ... end` is the same as `forall(a: Generators.integer).with_config(verbose: true).check do ... end`)
|
39
71
|
def with_config(**config, &block)
|
40
72
|
@config = @config.merge(config)
|
41
73
|
|
@@ -44,13 +76,23 @@ module PropCheck
|
|
44
76
|
self
|
45
77
|
end
|
46
78
|
|
47
|
-
|
79
|
+
##
|
80
|
+
# filters the generator using the given `condition`.
|
81
|
+
# The final property checking block will only be run if the condition is truthy.
|
82
|
+
#
|
83
|
+
# If wanted, multiple `where`-conditions can be specified on a property.
|
84
|
+
# Be aware that if you filter away too much generated inputs,
|
85
|
+
# you might encounter a GeneratorExhaustedError.
|
86
|
+
# Only filter if you have few inputs to reject. Otherwise, improve your generators.
|
87
|
+
def where(&condition)
|
48
88
|
original_condition = @condition.dup
|
49
|
-
@condition = -> { instance_exec(&original_condition) && instance_exec(&
|
89
|
+
@condition = -> { instance_exec(&original_condition) && instance_exec(&condition) }
|
50
90
|
|
51
91
|
self
|
52
92
|
end
|
53
93
|
|
94
|
+
##
|
95
|
+
# Checks the property (after settings have been altered using the other instance methods in this class.)
|
54
96
|
def check(&block)
|
55
97
|
binding_generator = PropCheck::Generators.fixed_hash(bindings)
|
56
98
|
|
@@ -70,7 +112,7 @@ module PropCheck
|
|
70
112
|
private def ensure_not_exhausted!(n_runs)
|
71
113
|
return if n_runs >= @config.n_runs
|
72
114
|
|
73
|
-
raise GeneratorExhaustedError, """
|
115
|
+
raise Errors::GeneratorExhaustedError, """
|
74
116
|
Could not perform `n_runs = #{@config.n_runs}` runs,
|
75
117
|
(exhausted #{@config.max_generate_attempts} tries)
|
76
118
|
because too few generator results were adhering to
|
@@ -131,7 +173,7 @@ module PropCheck
|
|
131
173
|
private def show_problem_output(problem, generator_results, n_successful, &block)
|
132
174
|
output = @config.verbose ? STDOUT : StringIO.new
|
133
175
|
output = pre_output(output, n_successful, generator_results.root, problem)
|
134
|
-
shrunken_result, shrunken_exception, n_shrink_steps =
|
176
|
+
shrunken_result, shrunken_exception, n_shrink_steps = shrink(generator_results, output, &block)
|
135
177
|
output = post_output(output, n_shrink_steps, shrunken_result, shrunken_exception)
|
136
178
|
|
137
179
|
[output, shrunken_result, shrunken_exception, n_shrink_steps]
|
@@ -168,7 +210,7 @@ module PropCheck
|
|
168
210
|
end.join(", ")
|
169
211
|
end
|
170
212
|
|
171
|
-
private def
|
213
|
+
private def shrink(bindings_tree, io, &fun)
|
172
214
|
io.puts 'Shrinking...' if @config.verbose
|
173
215
|
problem_child = bindings_tree
|
174
216
|
siblings = problem_child.children.lazy
|
@@ -191,11 +233,11 @@ module PropCheck
|
|
191
233
|
|
192
234
|
begin
|
193
235
|
CheckEvaluator.new(sibling.root, &fun).call
|
194
|
-
rescue Exception =>
|
236
|
+
rescue Exception => e
|
195
237
|
problem_child = sibling
|
196
238
|
parent_siblings = siblings
|
197
239
|
siblings = problem_child.children.lazy
|
198
|
-
problem_exception =
|
240
|
+
problem_exception = e
|
199
241
|
end
|
200
242
|
end
|
201
243
|
|
data/lib/prop_check/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prop_check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Qqwy/Wiebe-Marten Wijnja
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- lib/prop_check/generator.rb
|
82
82
|
- lib/prop_check/generators.rb
|
83
83
|
- lib/prop_check/helper.rb
|
84
|
+
- lib/prop_check/helper/lazy_append.rb
|
84
85
|
- lib/prop_check/lazy_tree.rb
|
85
86
|
- lib/prop_check/property.rb
|
86
87
|
- lib/prop_check/property/check_evaluator.rb
|