prop_check 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem](https://img.shields.io/gem/v/prop_check.svg)](https://rubygems.org/gems/prop_check)
|
6
|
+
[![Build Status](https://travis-ci.org/Qqwy/ruby-prop_check.svg?branch=master)](https://travis-ci.org/Qqwy/ruby-prop_check)
|
7
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/71897f5e6193a5124a53/maintainability)](https://codeclimate.com/github/Qqwy/ruby-prop_check/maintainability)
|
8
|
+
[![RubyDoc](https://img.shields.io/badge/%F0%9F%93%9ARubyDoc-documentation-informational.svg)](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
|