prop_check 0.15.0 → 0.16.0

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: c6d76933200bf114634aaa2d53f4c0832d6c362a2051e12d760d59a8ccae14e7
4
- data.tar.gz: 452bcebdfb1b5c0113519840ce22aec73be64a5ab60c20dacd3a537eb860bb8e
3
+ metadata.gz: 912a84633a6ab5b7f209555be0086e4dcafd371f337b289113003edf765fb668
4
+ data.tar.gz: 92146dcaf693c20f4cb3021178e881495de8b63f3819c254aea186a3780891c0
5
5
  SHA512:
6
- metadata.gz: aa86451cf41305a0c9cb511b39b210768365becd0494f83e285f8cb2b7b7abf667df87ed033fb1faf730037edc116747b75f9d0ab8efce834de6e3cf0b499d6a
7
- data.tar.gz: 215c2f13f9523f93b550de01f48087385a6ae8892357248691e7556d80cea9b3fc06e7d1dd113a4d088fa4225c99247b8309614dab6ef8198c7dc96e635d7aba
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
  [![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)
6
+ [![Ruby RSpec tests build status](https://github.com/Qqwy/ruby-prop_check/actions/workflows/run_tests.yaml/badge.svg)](https://github.com/Qqwy/ruby-prop_check/actions/workflows/run_tests.yaml)
7
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)
8
+ [![RubyDoc](https://img.shields.io/badge/%F0%9F%93%9ARubyDoc-documentation-informational.svg)](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
- - [ ] Configuration option to resize all generators given to a particular Property instance.
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
- include PropCheck::Generators
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
- include PropCheck::Generators
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
- include PropCheck::Generators
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 hashes.
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 call `include PropCheck::Generators` in e.g. your testing-suite files to be able to use these.
215
- If you want to be more explicit (but somewhat more verbose) when calling these functions. feel free to e.g. create a module-alias (like `PG = PropCheck::Generators`) instead.
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
- >> Generators.choose(32..128).map(&:chr).call(10, Random.new(42))
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
- >> Generators.integer.bind { |a| Generators.integer.bind { |b| Generator.wrap([a , b]) } }.call(100, Random.new(42))
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
- >> Generators.one_of(Generators.constant(true), Generators.constant(false)).sample(5, size: 10, rng: Random.new(42))
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
- (note that for this example, you can also use `Generators.boolean`. The example happens to show how it is implemented under the hood.)
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
- >> Generators.frequency(5 => Generators.integer, 1 => Generators.printable_ascii_char).sample(size: 10, rng: Random.new(42))
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
@@ -758,7 +758,6 @@ module PropCheck
758
758
  offset_gen.map { |offset| Date.jd(epoch.jd + offset) }
759
759
  else
760
760
  offset_gen.with_config.map do |offset, config|
761
- puts config.inspect
762
761
  epoch = config.default_epoch.to_date
763
762
  Date.jd(epoch.jd + offset)
764
763
  end
@@ -36,11 +36,6 @@ module PropCheck
36
36
  return block.call(**val) if val.is_a?(Hash) && val.keys.all? { |k| k.is_a?(Symbol) }
37
37
 
38
38
  block.call(val)
39
- # if kwval != {}
40
- # block.call(**kwval)
41
- # else
42
- # block.call(*val)
43
- # end
44
39
  end
45
40
  end
46
41
  end
@@ -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
@@ -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: size,
345
+ size: generator_size,
284
346
  rng: rng,
285
347
  max_consecutive_attempts: @config.max_consecutive_attempts,
286
348
  config: @config
@@ -1,3 +1,3 @@
1
1
  module PropCheck
2
- VERSION = '0.15.0'
2
+ VERSION = '0.16.0'
3
3
  end
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.15.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.1.6
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