pbt 0.4.1 → 0.4.2

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: c1a5d4c94783e479474b521113dcad84959db11c6139780031cf52aff6748e61
4
- data.tar.gz: eb112f231d4417963341fb36b585c9b0d4fa8b14f0ac726c51b80c7424542cb1
3
+ metadata.gz: 129484c73e5be7741c4bbf70c2ab374a0e48f28926c3cd4b6b3ca004c1037b98
4
+ data.tar.gz: 83ec64585e4b33bfad802b262784b0507f341621764099279af3f6faeda273fa
5
5
  SHA512:
6
- metadata.gz: e40bde143e84c6ed1fa76cf69f3ed93261bcdae70a229359ea996190c63c24ff9b7155f9974a0d4a39c8430fb17e935539631e463a072af30439b5805c939021
7
- data.tar.gz: d082a2078753d09bf19a1bfc41931258a19db3842590c7f366a1f5fece9097b3a6668db096baa9a679ab0026df05e45ac1f03f14ceca0f1b7aeb635bc1f82c83
6
+ metadata.gz: 3c61fa019e0aff56404f4c3346b039615c368e175e98407f118be9ef55060e61f4ebacbd6cec79b5e0834cfec2550fdbdf6952be47eeacb1437455f5fd54dd5b
7
+ data.tar.gz: 209b104767846e73d8db2b94d0b4c9e2e9528c695e9d4cb766d6845de7e8c1556e523b172461c693c77e6deea3f0a764dd51c8e2a17611a2914760146e399bcc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.2] - 2024-05-23
4
+
5
+ - Fix Prism `LoadError` message [#27](https://github.com/ohbarye/pbt/pull/27) by @sambostock
6
+
3
7
  ## [0.4.1] - 2024-05-10
4
8
 
5
9
  - Fix a bug for experimental_ractor_rspec_integration mode. When a test file name starts with a number, it can't be a constant name.
data/README.md CHANGED
@@ -8,6 +8,8 @@ A property-based testing tool for Ruby with experimental features that allow you
8
8
 
9
9
  PBT stands for Property-Based Testing.
10
10
 
11
+ As for the results of the parallelization experiment, please refer the talk at RubyKaigi 2024: [Unlocking Potential of Property Based Testing with Ractor](https://rubykaigi.org/2024/presentations/ohbarye.html).
12
+
11
13
  ## What's Property-Based Testing?
12
14
 
13
15
  Property-Based Testing is a testing methodology that focuses on the properties a system should always satisfy, rather than checking individual examples. Instead of writing tests for predefined inputs and outputs, PBT allows you to specify the general characteristics that your code should adhere to and then automatically generates a wide range of inputs to verify these properties.
@@ -39,29 +41,34 @@ Off course you can install with `gem intstall pbt`.
39
41
  ### Simple property
40
42
 
41
43
  ```ruby
42
- # Let's say you have a method that returns just a multiplicative inverse.
43
- def multiplicative_inverse(number)
44
- Rational(1, number)
44
+ # Let's say you have your own sort method.
45
+ def sort(array)
46
+ return array if array.size <= 2 # Here's a bug! It should be 1.
47
+ pivot, *rest = array
48
+ left, right = rest.partition { |n| n <= pivot }
49
+ sort(left) + [pivot] + sort(right)
45
50
  end
46
51
 
47
52
  Pbt.assert do
48
- # The given block is executed 100 times with different random numbers.
53
+ # The given block is executed 100 times with different arrays with random numbers.
49
54
  # Besides, the block runs in parallel by Ractor.
50
- Pbt.property(Pbt.integer) do |number|
51
- result = multiplicative_inverse(number)
52
- raise "Result should be the multiplicative inverse of the number" if result * number != 1
55
+ Pbt.property(Pbt.array(Pbt.integer)) do |numbers|
56
+ result = sort(numbers)
57
+ result.each_cons(2) do |x, y|
58
+ raise "Sort algorithm is wrong." unless x <= y
59
+ end
53
60
  end
54
61
  end
55
62
 
56
- # If the function has a bug, the test fails with a counterexample.
57
- # For example, the multiplicative_inverse method doesn't work for 0 regardless of the behavior is intended or not.
63
+ # If the method has a bug, the test fails and it reports a minimum counterexample.
64
+ # For example, the sort method doesn't work for [0, -1].
58
65
  #
59
66
  # Pbt::PropertyFailure:
60
67
  # Property failed after 23 test(s)
61
- # { seed: 11001296583699917659214176011685741769 }
62
- # Counterexample: 0
63
- # Shrunk 3 time(s)
64
- # Got ZeroDivisionError: divided by 0
68
+ # seed: 43738985293126714007411539287084402325
69
+ # counterexample: [0, -1]
70
+ # Shrunk 40 time(s)
71
+ # Got RuntimeError: Sort algorithm is wrong.
65
72
  ```
66
73
 
67
74
  ### Explain The Snippet
@@ -92,7 +99,7 @@ Here, we used only one type of arbitrary, `Pbt.integer`. There are many other bu
92
99
  In PBT, If a test fails, it attempts to shrink the case that caused the failure into a form that is easier for humans to understand.
93
100
  In other words, instead of stopping the test itself the first time it fails and reporting the failed value, it tries to find the minimal value that causes the error.
94
101
 
95
- When there is a test that fails when given an even number, a counterexample of `2` is simpler and easier to understand than `432743417662`.
102
+ When there is a test that fails when given an even number, a counterexample of `[0, -1]` is simpler and easier to understand than any complex example like `[-897860, -930517, 577817, -16302, 310864, 856411, -304517, 86613, -78231]`.
96
103
 
97
104
  ### Arbitrary
98
105
 
@@ -103,16 +110,16 @@ There are many built-in arbitraries in `Pbt`. You can use them to generate rando
103
110
  ```ruby
104
111
  rng = Random.new
105
112
 
106
- Pbt.integer.generate(rng) # => 42
113
+ Pbt.integer.generate(rng) # => 42
107
114
  Pbt.integer(min: -1, max: 8).generate(rng) # => Integer between -1 and 8
108
115
 
109
- Pbt.symbol.generate(rng) # => :atq
116
+ Pbt.symbol.generate(rng) # => :atq
110
117
 
111
- Pbt.ascii_char.generate(rng) # => "a"
112
- Pbt.ascii_string.generate(rng) # => "aagjZfao"
118
+ Pbt.ascii_char.generate(rng) # => "a"
119
+ Pbt.ascii_string.generate(rng) # => "aagjZfao"
113
120
 
114
- Pbt.boolean.generate(rng) # => true or false
115
- Pbt.constant(42).generate(rng) # => 42 always
121
+ Pbt.boolean.generate(rng) # => true or false
122
+ Pbt.constant(42).generate(rng) # => 42 always
116
123
  ```
117
124
 
118
125
  #### Composites
@@ -120,15 +127,15 @@ Pbt.constant(42).generate(rng) # => 42 always
120
127
  ```ruby
121
128
  rng = Random.new
122
129
 
123
- Pbt.array(Pbt.integer).generate(rng) # => [121, -13141, 9825]
124
- Pbt.array(Pbt.integer, max: 1, empty: true).generate(rng) # => [] or [42] etc.
130
+ Pbt.array(Pbt.integer).generate(rng) # => [121, -13141, 9825]
131
+ Pbt.array(Pbt.integer, max: 1, empty: true).generate(rng) # => [] or [42] etc.
125
132
 
126
- Pbt.tuple(Pbt.symbol, Pbt.integer).generate(rng) # => [:atq, 42]
133
+ Pbt.tuple(Pbt.symbol, Pbt.integer).generate(rng) # => [:atq, 42]
127
134
 
128
135
  Pbt.fixed_hash(x: Pbt.symbol, y: Pbt.integer).generate(rng) # => {x: :atq, y: 42}
129
- Pbt.hash(Pbt.symbol, Pbt.integer).generate(rng) # => {atq: 121, ygab: -1142}
136
+ Pbt.hash(Pbt.symbol, Pbt.integer).generate(rng) # => {atq: 121, ygab: -1142}
130
137
 
131
- Pbt.one_of(:a, 1, 0.1).generate(rng) # => :a or 1 or 0.1
138
+ Pbt.one_of(:a, 1, 0.1).generate(rng) # => :a or 1 or 0.1
132
139
  ````
133
140
 
134
141
  See [ArbitraryMethods](https://github.com/ohbarye/pbt/blob/main/lib/pbt/arbitrary/arbitrary_methods.rb) module for more details.
@@ -144,18 +151,18 @@ When a test fails, you'll see a message like below.
144
151
  ```text
145
152
  Pbt::PropertyFailure:
146
153
  Property failed after 23 test(s)
147
- { seed: 11001296583699917659214176011685741769 }
148
- Counterexample: 0
149
- Shrunk 3 time(s)
150
- Got ZeroDivisionError: divided by 0
154
+ seed: 43738985293126714007411539287084402325
155
+ counterexample: [0, -1]
156
+ Shrunk 40 time(s)
157
+ Got RuntimeError: Sort algorithm is wrong.
151
158
  # and backtraces
152
159
  ```
153
160
 
154
161
  You can reproduce the failure by passing the seed to `Pbt.assert`.
155
162
 
156
163
  ```ruby
157
- Pbt.assert(seed: 11001296583699917659214176011685741769) do
158
- Pbt.property(Pbt.integer) do |number|
164
+ Pbt.assert(seed: 43738985293126714007411539287084402325) do
165
+ Pbt.property(Pbt.array(Pbt.integer)) do |number|
159
166
  # your test
160
167
  end
161
168
  end
@@ -177,25 +184,29 @@ The verbose mode prints the results of each tested values.
177
184
 
178
185
  ```text
179
186
  Encountered failures were:
180
- - [152477, 666997, -531468, -92182, 623948, 425913, 656138, 856463, -64529]
181
- - [76239, 666997, -531468, -92182, 623948]
182
- - [76239, 666997, -531468]
187
+ - [-897860, -930517, 577817, -16302, 310864, 856411, -304517, 86613, -78231]
188
+ - [310864, 856411, -304517, 86613, -78231]
189
+ - [-304517, 86613, -78231]
183
190
  (snipped for README)
184
- - [2, 163]
185
- - [2, 11]
191
+ - [0, -3]
192
+ - [0, -2]
193
+ - [0, -1]
186
194
 
187
195
  Execution summary:
188
- . × [152477, 666997, -531468, -92182, 623948, 425913, 656138, 856463, -64529]
189
- . . √ [152477, 666997, -531468, -92182, 623948]
190
- . . √ [-64529]
191
- . . × [76239, 666997, -531468, -92182, 623948, 425913, 656138, 856463, -64529]
192
- . . . × [76239, 666997, -531468, -92182, 623948]
196
+ . × [-897860, -930517, 577817, -16302, 310864, 856411, -304517, 86613, -78231]
197
+ . . √ [-897860, -930517, 577817, -16302, 310864]
198
+ . . √ [-930517, 577817, -16302, 310864, 856411]
199
+ . . [577817, -16302, 310864, 856411, -304517]
200
+ . . [-16302, 310864, 856411, -304517, 86613]
201
+ . . × [310864, 856411, -304517, 86613, -78231]
193
202
  (snipped for README)
194
- . . . . . . . . . . . . . . . . . √ [2, 21]
195
- . . . . . . . . . . . . . . . . . × [2, 11]
196
- . . . . . . . . . . . . . . . . . . []
197
- . . . . . . . . . . . . . . . . . . √ [2, 1]
198
- . . . . . . . . . . . . . . . . . . √ [2, 0]
203
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . √ [-2]
204
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . √ []
205
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . × [0, -1]
206
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . √ [0]
207
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . √ [-1]
208
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . √ []
209
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . √ [0, 0]
199
210
  ```
200
211
 
201
212
  ## Configuration
@@ -365,6 +376,8 @@ Once this project finishes the following, we will release v1.0.0.
365
376
  - [ ] Implement frequency arbitrary
366
377
  - [ ] Statistics feature to aggregate generated values
367
378
  - [ ] Decide DSL
379
+ - [ ] Try Fiber
380
+ - [ ] Stateful property-based testing
368
381
 
369
382
  ## Development
370
383
 
@@ -5,7 +5,7 @@ begin
5
5
  require "prism"
6
6
  rescue LoadError
7
7
  raise InvalidConfiguration,
8
- "Prism gem (https://github.com/grosser/parallel) is required to use worker `:rator` and `:experimental_ractor_rspec_integration`. Please add `gem 'parallel'` to your Gemfile."
8
+ "Prism gem (https://github.com/ruby/prism) is required to use worker `:ractor` and `:experimental_ractor_rspec_integration`. Please add `gem 'prism'` to your Gemfile."
9
9
  end
10
10
 
11
11
  module Pbt
data/lib/pbt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pbt
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pbt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ohbarye
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-09 00:00:00.000000000 Z
11
+ date: 2024-05-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
81
  requirements: []
82
- rubygems_version: 3.5.3
82
+ rubygems_version: 3.5.9
83
83
  signing_key:
84
84
  specification_version: 4
85
85
  summary: Property-Based Testing tool for Ruby, utilizing Ractor for parallelizing