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 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