prop_check 0.15.0 → 0.16.0
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/.github/workflows/run_tests.yaml +31 -0
- data/CHANGELOG.md +4 -0
- data/README.md +26 -21
- data/lib/prop_check/generators.rb +0 -1
- data/lib/prop_check/helper.rb +0 -5
- data/lib/prop_check/property/configuration.rb +6 -1
- data/lib/prop_check/property.rb +63 -1
- data/lib/prop_check/version.rb +1 -1
- metadata +3 -4
- data/.travis.yml +0 -18
- data/lib/prop_check/helper/lazy_append.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 912a84633a6ab5b7f209555be0086e4dcafd371f337b289113003edf765fb668
|
4
|
+
data.tar.gz: 92146dcaf693c20f4cb3021178e881495de8b63f3819c254aea186a3780891c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 192ed9c6887dc19f29fc3d8aba9278eeb0fd389aab9fae546c940e2831833ea8064ea53e1e903c599d7d7ec2a8fe5bdc04a2c3122c2374a2d1d933b2184a2ab0
|
7
|
+
data.tar.gz: 63005af74e5f0d1757930f64ce031f5cc922e34b4e876cdaebbbf139280e9e923d134440f20ab63129c4fd1647d1e524b07b6ed3800828b29d22ad7e2cc5e394
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Ruby RSpec tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
permissions:
|
10
|
+
contents: read
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
test:
|
14
|
+
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
strategy:
|
17
|
+
matrix:
|
18
|
+
ruby-version: ['2.5', '2.6', '2.7', '3.0']
|
19
|
+
|
20
|
+
steps:
|
21
|
+
- uses: actions/checkout@v3
|
22
|
+
- name: Set up Ruby
|
23
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
24
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
25
|
+
# uses: ruby/setup-ruby@v1
|
26
|
+
uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
|
27
|
+
with:
|
28
|
+
ruby-version: ${{ matrix.ruby-version }}
|
29
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
30
|
+
- name: Run tests
|
31
|
+
run: bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
- 0.16.0
|
2
|
+
- Features:
|
3
|
+
- New option in `PropCheck::Property::Configuration` to resize all generators at once.
|
4
|
+
- Wrapper functions to modify this easily in `PropCheck::Property` called `#resize`, `#grow_fast`, `#grow_slowly`, `#grow_exponentially`, `#grow_quadratically`, `#grow_logarithmically`.
|
1
5
|
- 0.15.0
|
2
6
|
- Features:
|
3
7
|
- Generators for `Date`, `Time` and `DateTime`.
|
data/README.md
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
PropCheck allows you to do Property Testing in Ruby.
|
4
4
|
|
5
5
|
[](https://rubygems.org/gems/prop_check)
|
6
|
-
[](https://github.com/Qqwy/ruby-prop_check/actions/workflows/run_tests.yaml)
|
7
7
|
[](https://codeclimate.com/github/Qqwy/ruby-prop_check/maintainability)
|
8
|
-
[](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/
|
8
|
+
[](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/)
|
9
9
|
|
10
10
|
It features:
|
11
11
|
|
@@ -61,11 +61,11 @@ Before releasing v1.0, we want to finish the following:
|
|
61
61
|
- [x] Before/after/around hooks to add setup/teardown logic to be called before/after/around each time a check is run with new data.
|
62
62
|
- [x] Possibility to resize generators.
|
63
63
|
- [x] `#instance` generator to allow the easy creation of generators for custom datatypes.
|
64
|
-
- [ ] A usage guide.
|
65
|
-
- [ ] A simple way to create recursive generators
|
66
64
|
- [x] Builtin generation of `Set`s
|
67
65
|
- [x] Builtin generation of `Date`s, `Time`s and `DateTime`s.
|
68
|
-
- [
|
66
|
+
- [x] Configuration option to resize all generators given to a particular Property instance.
|
67
|
+
- [ ] A simple way to create recursive generators
|
68
|
+
- [ ] A usage guide.
|
69
69
|
|
70
70
|
## Nice-to-haves
|
71
71
|
|
@@ -100,9 +100,9 @@ The value(s) generated from the generator(s) passed to the `forall` will be give
|
|
100
100
|
Raise an exception from the block if there is a problem. If there is no problem, just return normally.
|
101
101
|
|
102
102
|
```ruby
|
103
|
-
|
103
|
+
G = PropCheck::Generators
|
104
104
|
# testing that Enumerable#sort sorts in ascending order
|
105
|
-
PropCheck.forall(array(integer)) do |numbers|
|
105
|
+
PropCheck.forall(G.array(G.integer)) do |numbers|
|
106
106
|
sorted_numbers = numbers.sort
|
107
107
|
|
108
108
|
# Check that no number is smaller than the previous number
|
@@ -124,8 +124,8 @@ end
|
|
124
124
|
```
|
125
125
|
```ruby
|
126
126
|
# And then in a test case:
|
127
|
-
|
128
|
-
PropCheck.forall(numbers: array(integer)) do |numbers:|
|
127
|
+
G = PropCheck::Generators
|
128
|
+
PropCheck.forall(numbers: G.array(G.integer)) do |numbers:|
|
129
129
|
result = naive_average(numbers)
|
130
130
|
unless result.is_a?(Integer) do
|
131
131
|
raise "Expected the average to be an integer!"
|
@@ -135,10 +135,10 @@ end
|
|
135
135
|
# Or if you e.g. are using RSpec:
|
136
136
|
describe "#naive_average" do
|
137
137
|
include PropCheck
|
138
|
-
|
138
|
+
G = PropCheck::Generators
|
139
139
|
|
140
140
|
it "returns an integer for any input" do
|
141
|
-
forall(numbers: array(integer)) do |numbers:|
|
141
|
+
forall(numbers: G.array(G.integer)) do |numbers:|
|
142
142
|
result = naive_average(numbers)
|
143
143
|
expect(result).to be_a(Integer)
|
144
144
|
end
|
@@ -208,11 +208,12 @@ It contains generators for:
|
|
208
208
|
- (any, only real-valued) floats,
|
209
209
|
- (any, printable only, alphanumeric only, etc) strings and symbols
|
210
210
|
- fixed-size arrays and hashes
|
211
|
-
- as well as varying-size arrays and
|
211
|
+
- as well as varying-size arrays, hashes and sets.
|
212
|
+
- dates, times, datetimes.
|
212
213
|
- and many more!
|
213
214
|
|
214
|
-
It is common to
|
215
|
-
|
215
|
+
It is common and recommended to set up a module alias by using `G = PropCheck::Generators` in e.g. your testing-suite files to be able to refer to all of them.
|
216
|
+
_(Earlier versions of the library recommended including the module instead. But this will make it very simple to accidentally shadow a generator with a local variable named `float` or `array` and similar.)_
|
216
217
|
|
217
218
|
### Writing Custom Generators
|
218
219
|
|
@@ -228,33 +229,37 @@ Always returns the given value. No shrinking.
|
|
228
229
|
|
229
230
|
Allows you to take the result of one generator and transform it into something else.
|
230
231
|
|
231
|
-
>>
|
232
|
-
=> "S"
|
232
|
+
>> G.choose(32..128).map(&:chr).sample(1, size: 10, Random.new(42))
|
233
|
+
=> ["S"]
|
233
234
|
|
234
235
|
#### Generator#bind
|
235
236
|
|
236
237
|
Allows you to create one or another generator conditionally on the output of another generator.
|
237
238
|
|
238
|
-
>>
|
239
|
-
=> [2, 79]
|
239
|
+
>> G.integer.bind { |a| G.integer.bind { |b| G.constant([a , b]) } }.sample(1, size: 100, rng: Random.new(42)
|
240
|
+
=> [[2, 79]]
|
241
|
+
|
242
|
+
This is an advanced feature. Often, you can use a combination of `Generators.tuple` and `Generator#map` instead:
|
240
243
|
|
244
|
+
>> G.tuple(integer, integer).sample(1, size: 100, rng: Random.new(42)
|
245
|
+
=> [[2, 79]]
|
241
246
|
|
242
247
|
#### Generators.one_of
|
243
248
|
|
244
249
|
Useful if you want to be able to generate a value to be one of multiple possibilities:
|
245
250
|
|
246
251
|
|
247
|
-
>>
|
252
|
+
>> G.one_of(G.constant(true), G.constant(false)).sample(5, size: 10, rng: Random.new(42))
|
248
253
|
=> [true, false, true, true, true]
|
249
254
|
|
250
|
-
(
|
255
|
+
(Note that for this example, you can also use `G.boolean`. The example happens to show how it is implemented under the hood.)
|
251
256
|
|
252
257
|
#### Generators.frequency
|
253
258
|
|
254
259
|
If `one_of` does not give you enough flexibility because you want some results to be more common than others,
|
255
260
|
you can use `Generators.frequency` which takes a hash of (integer_frequency => generator) keypairs.
|
256
261
|
|
257
|
-
>>
|
262
|
+
>> G.frequency(5 => G.integer, 1 => G.printable_ascii_char).sample(size: 10, rng: Random.new(42))
|
258
263
|
=> [4, -3, 10, 8, 0, -7, 10, 1, "E", 10]
|
259
264
|
|
260
265
|
#### Others
|
data/lib/prop_check/helper.rb
CHANGED
@@ -18,6 +18,9 @@ module PropCheck
|
|
18
18
|
# - `default_epoch:` The 'base' value to use for date/time generators like
|
19
19
|
# `PropCheck::Generators#date` `PropCheck::Generators#future_date` `PropCheck::Generators#time`, etc.
|
20
20
|
# (Default: `DateTime.now`)
|
21
|
+
# - `resize_function` A proc that can be used to resize _all_ generators.
|
22
|
+
# Takes the current size as integer and should return a new integer.
|
23
|
+
# (Default: `proc { |size| size }`)
|
21
24
|
Configuration = Struct.new(
|
22
25
|
:verbose,
|
23
26
|
:n_runs,
|
@@ -25,6 +28,7 @@ module PropCheck
|
|
25
28
|
:max_shrink_steps,
|
26
29
|
:max_consecutive_attempts,
|
27
30
|
:default_epoch,
|
31
|
+
:resize_function,
|
28
32
|
keyword_init: true
|
29
33
|
) do
|
30
34
|
def initialize(
|
@@ -33,7 +37,8 @@ module PropCheck
|
|
33
37
|
max_generate_attempts: 10_000,
|
34
38
|
max_shrink_steps: 10_000,
|
35
39
|
max_consecutive_attempts: 30,
|
36
|
-
default_epoch: DateTime.now
|
40
|
+
default_epoch: DateTime.now,
|
41
|
+
resize_function: proc { |size| size }
|
37
42
|
)
|
38
43
|
super
|
39
44
|
end
|
data/lib/prop_check/property.rb
CHANGED
@@ -111,6 +111,67 @@ module PropCheck
|
|
111
111
|
duplicate
|
112
112
|
end
|
113
113
|
|
114
|
+
##
|
115
|
+
# Resizes all generators in this property with the given function.
|
116
|
+
#
|
117
|
+
# Shorthand for manually wrapping `PropCheck::Property::Configuration.resize_function` with the new function.
|
118
|
+
def resize(&block)
|
119
|
+
raise '#resize called without a block' unless block_given?
|
120
|
+
|
121
|
+
orig_fun = @config.resize_function
|
122
|
+
with_config(resize_function: block)
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Resizes all generators in this property. The new size is `2.pow(orig_size)`
|
127
|
+
#
|
128
|
+
# c.f. #resize
|
129
|
+
def growing_exponentially(&block)
|
130
|
+
orig_fun = @config.resize_function
|
131
|
+
fun = proc { |size| 2.pow(orig_fun.call(size)) }
|
132
|
+
with_config(resize_function: fun, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Resizes all generators in this property. The new size is `orig_size * orig_size`
|
137
|
+
#
|
138
|
+
# c.f. #resize
|
139
|
+
def growing_quadratically(&block)
|
140
|
+
orig_fun = @config.resize_function
|
141
|
+
fun = proc { |size| orig_fun.call(size).pow(2) }
|
142
|
+
with_config(resize_function: fun, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# Resizes all generators in this property. The new size is `2 * orig_size`
|
147
|
+
#
|
148
|
+
# c.f. #resize
|
149
|
+
def growing_fast(&block)
|
150
|
+
orig_fun = @config.resize_function
|
151
|
+
fun = proc { |size| orig_fun.call(size) * 2 }
|
152
|
+
with_config(resize_function: fun, &block)
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Resizes all generators in this property. The new size is `0.5 * orig_size`
|
157
|
+
#
|
158
|
+
# c.f. #resize
|
159
|
+
def growing_slowly(&block)
|
160
|
+
orig_fun = @config.resize_function
|
161
|
+
fun = proc { |size| orig_fun.call(size) * 0.5 }
|
162
|
+
with_config(resize_function: fun, &block)
|
163
|
+
end
|
164
|
+
|
165
|
+
##
|
166
|
+
# Resizes all generators in this property. The new size is `Math.log2(orig_size)`
|
167
|
+
#
|
168
|
+
# c.f. #resize
|
169
|
+
def growing_logarithmically(&block)
|
170
|
+
orig_fun = @config.resize_function
|
171
|
+
fun = proc { |size| Math.log2(orig_fun.call(size)) }
|
172
|
+
with_config(resize_function: fun, &block)
|
173
|
+
end
|
174
|
+
|
114
175
|
def with_bindings(*bindings, **kwbindings)
|
115
176
|
raise ArgumentError, 'No bindings specified!' if bindings.empty? && kwbindings.empty?
|
116
177
|
|
@@ -279,8 +340,9 @@ c.f. https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-k
|
|
279
340
|
(0...@config.max_generate_attempts)
|
280
341
|
.lazy
|
281
342
|
.map do
|
343
|
+
generator_size = @config.resize_function.call(size).to_i
|
282
344
|
binding_generator.generate(
|
283
|
-
size:
|
345
|
+
size: generator_size,
|
284
346
|
rng: rng,
|
285
347
|
max_consecutive_attempts: @config.max_consecutive_attempts,
|
286
348
|
config: @config
|
data/lib/prop_check/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prop_check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Qqwy/Wiebe-Marten Wijnja
|
@@ -35,11 +35,11 @@ executables: []
|
|
35
35
|
extensions: []
|
36
36
|
extra_rdoc_files: []
|
37
37
|
files:
|
38
|
+
- ".github/workflows/run_tests.yaml"
|
38
39
|
- ".gitignore"
|
39
40
|
- ".rspec"
|
40
41
|
- ".rubocop.yml"
|
41
42
|
- ".tool-versions"
|
42
|
-
- ".travis.yml"
|
43
43
|
- CHANGELOG.md
|
44
44
|
- CODE_OF_CONDUCT.md
|
45
45
|
- Gemfile
|
@@ -53,7 +53,6 @@ files:
|
|
53
53
|
- lib/prop_check/generator.rb
|
54
54
|
- lib/prop_check/generators.rb
|
55
55
|
- lib/prop_check/helper.rb
|
56
|
-
- lib/prop_check/helper/lazy_append.rb
|
57
56
|
- lib/prop_check/hooks.rb
|
58
57
|
- lib/prop_check/lazy_tree.rb
|
59
58
|
- lib/prop_check/property.rb
|
@@ -84,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
83
|
- !ruby/object:Gem::Version
|
85
84
|
version: '0'
|
86
85
|
requirements: []
|
87
|
-
rubygems_version: 3.
|
86
|
+
rubygems_version: 3.2.3
|
88
87
|
signing_key:
|
89
88
|
specification_version: 4
|
90
89
|
summary: PropCheck allows you to do property-based testing, including shrinking.
|
data/.travis.yml
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sudo: false
|
3
|
-
language: ruby
|
4
|
-
cache: bundler
|
5
|
-
rvm:
|
6
|
-
- 2.6.5
|
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
|
@@ -1,18 +0,0 @@
|
|
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
|