prop_check 0.6.2 → 0.10.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: 4beba1b773706a7e7f75696a7040667172e44646246dc9ccdbc87faa03f70f55
4
- data.tar.gz: 2c6e0c8aabc7c9c69da74c11ad2e79461ed5f6e1c5e550b0eb32923366f84c84
3
+ metadata.gz: aaa23e40547bec5672e806d62c567947cd596e1c11ed2bc80fbe6912cd75a777
4
+ data.tar.gz: a0263cddf3efb8ee55f29395004915c38b6e78c7fc7bbf2c1b456f344013b8da
5
5
  SHA512:
6
- metadata.gz: 25a28c29aaedcfcff34a5fa8f3c7164b6df7536eed2134416467dd46b7c8502530c6511cf6b54d0ca2f1b8ee3b59ffaa62dc6a132667a0179f0dbead7fcf6b41
7
- data.tar.gz: d9d9790f110d56920570e25d2ed2b6ee0657ec99bc46b509593215405fe19de6545ecaa990a096fd75259d9122c7a7404a9f2e6194cc808707ed01f8489201ed
6
+ metadata.gz: b7976fb344d4c7135cd858ca86606beb97cd9e9f57c40e2bb322a3c76287de46491d4feb1dd3a65158ffef8ea98894490edc7eb9bc506d80ddb110b2f026de8d
7
+ data.tar.gz: f80bffd3b08d1a1cf120a70645b548c2f70b540ae5be317b7635f7416cc4e7be94d3a1bfca10acd117166e08fd0a0c6cd8ab08bf68097182fc064519600cfb55
data/.gitignore CHANGED
@@ -11,4 +11,5 @@
11
11
  .rspec_status
12
12
 
13
13
  # .gem version files
14
- *.gem
14
+ *.gem
15
+ Gemfile.lock
@@ -1 +1 @@
1
- ruby 2.5.1
1
+ ruby 2.6.5
@@ -0,0 +1 @@
1
+ - 0.8.0 New syntax that is more explicit, passng generated values to blocks as parameters.
data/Gemfile CHANGED
@@ -3,5 +3,9 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in prop_check.gemspec
4
4
  gemspec
5
5
 
6
- gem 'simplecov', require: false, group: :test
7
- gem 'doctest-rspec', require: false, group: :test
6
+ gem "bundler", "~> 2.0"
7
+ gem "rake", "~> 12.3", require: false, group: :test
8
+ gem "rspec", "~> 3.0", require: false, group: :test
9
+ gem "doctest-rspec", require: false, group: :test
10
+ gem "simplecov", require: false, group: :test
11
+
data/README.md CHANGED
@@ -14,7 +14,7 @@ It features:
14
14
  - Shrinking to a minimal counter-example on failure.
15
15
 
16
16
 
17
- ## TODOs before release
17
+ ## TODOs before stable release
18
18
 
19
19
  Before releasing this gem on Rubygems, the following things need to be finished:
20
20
 
@@ -26,11 +26,12 @@ Before releasing this gem on Rubygems, the following things need to be finished:
26
26
  - [x] Stop after a ludicrous amount of generator runs, to prevent malfunctioning (infinitely looping) generators from blowing up someone's computer.
27
27
  - [x] Look into customization of settings from e.g. command line arguments.
28
28
  - [x] Good, unicode-compliant, string generators.
29
- - [ ] Filtering generator outputs.
29
+ - [x] Filtering generator outputs.
30
+ - [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.
30
31
 
31
32
  # Nice-to-haves
32
33
 
33
- - [ ] Basic integration with RSpec. See also https://groups.google.com/forum/#!msg/rspec/U-LmL0OnO-Y/iW_Jcd6JBAAJ for progress on this.
34
+ - [x] Basic integration with RSpec. See also https://groups.google.com/forum/#!msg/rspec/U-LmL0OnO-Y/iW_Jcd6JBAAJ for progress on this.
34
35
  - [ ] `aggregate` , `resize` and similar generator-modifying calls (c.f. PropEr's variants of these) which will help with introspection/metrics.
35
36
  - [ ] Integration with other Ruby test frameworks.
36
37
  - Stateful property testing. If implemented at some point, will probably happen in a separate add-on library.
@@ -66,8 +67,9 @@ _(to be precise: a method on the execution context is defined which returns the
66
67
  Raise an exception from the block if there is a problem. If there is no problem, just return normally.
67
68
 
68
69
  ```ruby
70
+ include PropCheck::Generators
69
71
  # testing that Enumerable#sort sorts in ascending order
70
- PropCheck.forall(numbers: array(integer())) do
72
+ PropCheck.forall(array(integer)) do |numbers|
71
73
  sorted_numbers = numbers.sort
72
74
 
73
75
  # Check that no number is smaller than the previous number
@@ -77,6 +79,64 @@ PropCheck.forall(numbers: array(integer())) do
77
79
  end
78
80
  ```
79
81
 
82
+
83
+ Here is another example, using it inside a test case.
84
+ Here we check if `naive_average` indeed always returns an integer for all arrays of numbers we can pass it:
85
+
86
+ ```ruby
87
+ # Somewhere you have this function definition:
88
+ def naive_average(array)
89
+ array.sum / array.length
90
+ end
91
+ ```
92
+ ```ruby
93
+ # And then in a test case:
94
+ include PropCheck::Generators
95
+ PropCheck.forall(numbers: array(integer)) do |numbers:|
96
+ result = naive_average(numbers)
97
+ unless result.is_a?(Integer) do
98
+ raise "Expected the average to be an integer!"
99
+ end
100
+ end
101
+
102
+ # Or if you e.g. are using RSpec:
103
+ describe "#naive_average" do
104
+ include PropCheck
105
+ include PropCheck::Generators
106
+
107
+ it "returns an integer for any input" do
108
+ forall(numbers: array(integer)) do |numbers:|
109
+ result = naive_average(numbers)
110
+ expect(result).to be_a(Integer)
111
+ end
112
+ end
113
+ end
114
+ ```
115
+
116
+ When running this particular example PropCheck very quickly finds out that we have made a programming mistake:
117
+
118
+ ```ruby
119
+ ZeroDivisionError:
120
+ (after 6 successful property test runs)
121
+ Failed on:
122
+ `{
123
+ :numbers => []
124
+ }`
125
+
126
+ Exception message:
127
+ ---
128
+ divided by 0
129
+ ---
130
+
131
+ (shrinking impossible)
132
+ ---
133
+ ```
134
+
135
+ Clearly we forgot to handle the case of an empty array being passed to the function.
136
+ This is a good example of the kind of conceptual bugs that PropCheck (and property-based testing in general)
137
+ are able to check for.
138
+
139
+
80
140
  #### Shrinking
81
141
 
82
142
  When a failure is found, PropCheck will re-run the block given to `forall` to test
@@ -88,8 +148,8 @@ PropCheck will see if the failure still happens with `x = 50`.
88
148
  If it does , it will try `x = 25`. If not, it will try `x = 75`, and so on.
89
149
 
90
150
  This means if something only goes wrong for `x = 2`, the program will try:
91
- - `x = 100`(fails),`
92
- - x = 50`(fails),
151
+ - `x = 100`(fails),
152
+ - `x = 50`(fails),
93
153
  - `x = 25`(fails),
94
154
  - `x = 12`(fails),
95
155
  - `x = 6`(fails),
@@ -106,21 +166,28 @@ A short summary:
106
166
  - Arrays and hashes shrink to fewer elements, as well as shrinking their elements.
107
167
  - Strings shrink to shorter strings, as well as characters earlier in their alphabet.
108
168
 
169
+ ### Builtin Generators
170
+
171
+ PropCheck comes with [many builtin generators in the PropCheck::Generators](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/PropCheck/Generators) module.
172
+
173
+ It contains generators for:
174
+ - (any, positive, negative, etc.) integers,
175
+ - (any, only real-valued) floats,
176
+ - (any, printable only, alphanumeric only, etc) strings and symbols
177
+ - fixed-size arrays and hashes
178
+ - as well as varying-size arrays and hashes.
179
+ - and many more!
180
+
181
+ It is common to call `include PropCheck::Generators` in e.g. your testing-suite files to be able to use these.
182
+ 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.
109
183
 
110
184
  ### Writing Custom Generators
111
185
 
112
- PropCheck comes bundled with a bunch of common generators, for:
113
- - integers
114
- - floats
115
- - strings
116
- - symbols
117
- - arrays
118
- - hashes
119
- etc.
186
+ As described in the previous section, PropCheck already comes bundled with a bunch of common generators.
120
187
 
121
188
  However, you can easily adapt them to generate your own datatypes:
122
189
 
123
- #### Generator#wrap
190
+ #### Generators#constant / Generator#wrap
124
191
 
125
192
  Always returns the given value. No shrinking.
126
193
 
@@ -9,6 +9,13 @@ require 'prop_check/helper'
9
9
  # You probably want to look at the documentation of
10
10
  # PropCheck::Generator and PropCheck::Generators
11
11
  # to find out more about how to use generators.
12
+ #
13
+ # Common usage is to call `extend PropCheck` in your (testing) modules.
14
+ #
15
+ # This will:
16
+ # 1. Add the local method `forall` which will call `PropCheck.forall`
17
+ # 2. `include PropCheck::Generators`.
18
+ #
12
19
  module PropCheck
13
20
  module Errors
14
21
  class Error < StandardError; end
@@ -72,7 +72,7 @@ module PropCheck
72
72
  # end.flatten
73
73
  # end
74
74
  Generator.new do |size, rng|
75
- outer_result = generate(size, rng)
75
+ outer_result = self.generate(size, rng)
76
76
  outer_result.bind do |outer_val|
77
77
  inner_generator = generator_proc.call(outer_val)
78
78
  inner_generator.generate(size, rng)
@@ -91,5 +91,24 @@ module PropCheck
91
91
  result.map(&proc)
92
92
  end
93
93
  end
94
+
95
+ ##
96
+ # Creates a new Generator that only produces a value when the block `condition` returns a truthy value.
97
+ def where(&condition)
98
+ self.map do |result|
99
+ if condition.call(*result)
100
+ result
101
+ else
102
+ :"_PropCheck.filter_me"
103
+ end
104
+ end
105
+ # self.map do |*result|
106
+ # if condition.call(*result)
107
+ # result
108
+ # else
109
+ # :'_PropCheck.filter_me'
110
+ # end
111
+ # end
112
+ end
94
113
  end
95
114
  end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Contains the logic to combine potentially many before/after/around hooks
5
+ # into a single pair of procedures called `before` and `after`.
6
+ #
7
+ # _Note: This module is an implementation detail of PropCheck._
8
+ #
9
+ # These can be invoked by manually calling `#before` and `#after`.
10
+ # Important:
11
+ # - Always call first `#before` and then `#after`.
12
+ # This is required to make sure that `around` callbacks will work properly.
13
+ # - Make sure that if you call `#before`, to also call `#after`.
14
+ # It is thus highly recommended to call `#after` inside an `ensure`.
15
+ # This is to make sure that `around` callbacks indeed perform their proper cleanup.
16
+ #
17
+ # Alternatively, check out `PropCheck::Hooks::Enumerable` which allows
18
+ # wrapping the elements of an enumerable with hooks.
19
+ class PropCheck::Hooks
20
+ # attr_reader :before, :after, :around
21
+ def initialize()
22
+ @before = proc {}
23
+ @after = proc {}
24
+ @around = proc { |*args, &block| block.call(*args) }
25
+ end
26
+
27
+ def wrap_enum(enumerable)
28
+ PropCheck::Hooks::Enumerable.new(enumerable, self)
29
+ end
30
+
31
+
32
+ ##
33
+ # Wraps a block with all hooks that were configured this far.
34
+ #
35
+ # This means that whenever the block is called,
36
+ # the before/around/after hooks are called before/around/after it.
37
+ def wrap_block(&block)
38
+ proc { |*args| call(*args, &block) }
39
+ end
40
+
41
+ ##
42
+ # Wraps a block with all hooks that were configured this far,
43
+ # and immediately calls it using the given `*args`.
44
+ #
45
+ # See also #wrap_block
46
+ def call(*args, &block)
47
+ begin
48
+ @before.call()
49
+ @around.call do
50
+ block.call(*args)
51
+ end
52
+ ensure
53
+ @after.call()
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Adds `hook` to the `before` proc.
59
+ # It is called after earlier-added `before` procs.
60
+ def add_before(&hook)
61
+ old_before = @before
62
+ @before = proc {
63
+ old_before.call
64
+ hook.call
65
+ }
66
+ end
67
+
68
+ ##
69
+ # Adds `hook` to the `after` proc.
70
+ # It is called before earlier-added `after` procs.
71
+ def add_after(&hook)
72
+ old_after = @after
73
+ @after = proc {
74
+ hook.call
75
+ old_after.call
76
+ }
77
+ end
78
+
79
+ ##
80
+ # Adds `hook` to the `around` proc.
81
+ # It is called _inside_ earlier-added `around` procs.
82
+ def add_around(&hook)
83
+ old_around = @around
84
+ @around = proc do |&block|
85
+ old_around.call do |*args|
86
+ hook.call(*args, &block)
87
+ end
88
+ end
89
+ end
90
+
91
+ ##
92
+ # Wraps enumerable `inner` with a `PropCheck::Hooks` object
93
+ # such that the before/after/around hooks are called
94
+ # before/after/around each element that is fetched from `inner`.
95
+ #
96
+ # This is very helpful if you need to perform cleanup logic
97
+ # before/after/around e.g. data is generated or fetched.
98
+ #
99
+ # Note that whatever is after a `yield` in an `around` hook
100
+ # is not guaranteed to be called (for instance when a StopIteration is raised).
101
+ # Thus: make sure you use `ensure` to clean up resources.
102
+ class Enumerable
103
+ include ::Enumerable
104
+
105
+ def initialize(inner, hooks)
106
+ @inner = inner
107
+ @hooks = hooks
108
+ end
109
+
110
+ def each(&task)
111
+ return to_enum(:each) unless block_given?
112
+
113
+ enum = @inner.to_enum
114
+
115
+ wrapped_yielder = @hooks.wrap_block do
116
+ yield enum.next(&task)
117
+ end
118
+
119
+ loop(&wrapped_yielder)
120
+ end
121
+ end
122
+ end
@@ -73,7 +73,8 @@ module PropCheck
73
73
  [tree.root].lazy_append(new_children)
74
74
  end
75
75
 
76
- squish.call(self, [])
76
+ squish
77
+ .call(self, [])
77
78
 
78
79
  # base = [root]
79
80
  # recursive = children.map(&:each)
@@ -99,7 +100,8 @@ module PropCheck
99
100
  # >> LazyTree.new(1, [LazyTree.new(2, [LazyTree.new(3)]), LazyTree.new(4)]).to_a
100
101
  # => [1, 4, 2, 3]
101
102
  def to_a
102
- each.force
103
+ each
104
+ .force
103
105
  end
104
106
 
105
107
  # TODO: fix implementation
@@ -1,24 +1,41 @@
1
1
  require 'stringio'
2
+ require "awesome_print"
2
3
 
3
4
  require 'prop_check/property/configuration'
4
- require 'prop_check/property/check_evaluator'
5
+ require 'prop_check/hooks'
5
6
  module PropCheck
6
7
  ##
7
8
  # Run properties
8
9
  class Property
9
10
 
10
11
  ##
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.
12
+ # Main entry-point to create (and possibly immediately run) a property-test.
13
+ #
14
+ # This method accepts a list of generators and a block.
15
+ # The block will then be executed many times, passing the values generated by the generators
16
+ # as respective arguments:
17
+ #
18
+ # ```
19
+ # include PropCheck::Generators
20
+ # PropCheck.forall(integer(), float()) { |x, y| ... }
21
+ # ```
22
+ #
23
+ # It is also possible (and recommended when having more than a few generators) to use a keyword-list
24
+ # of generators instead:
25
+ #
26
+ # ```
27
+ # include PropCheck::Generators
28
+ # PropCheck.forall(x: integer(), y: float()) { |x:, y:| ... }
29
+ # ```
30
+ #
14
31
  #
15
32
  # If you do not pass a block right away,
16
33
  # a Property object is returned, which you can call the other instance methods
17
34
  # 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)
19
- def self.forall(**bindings, &block)
35
+ # (so `forall(Generators.integer) do |val| ... end` and forall(Generators.integer).check do |val| ... end` are the same)
36
+ def self.forall(*bindings, &block)
20
37
 
21
- property = new(bindings)
38
+ property = new(*bindings)
22
39
 
23
40
  return property.check(&block) if block_given?
24
41
 
@@ -44,12 +61,14 @@ module PropCheck
44
61
 
45
62
  attr_reader :bindings, :condition
46
63
 
47
- def initialize(**bindings)
48
- raise ArgumentError, 'No bindings specified!' if bindings.empty?
64
+ def initialize(*bindings, **kwbindings)
65
+ raise ArgumentError, 'No bindings specified!' if bindings.empty? && kwbindings.empty?
49
66
 
50
67
  @bindings = bindings
51
- @condition = -> { true }
68
+ @kwbindings = kwbindings
69
+ @condition = proc { true }
52
70
  @config = self.class.configuration
71
+ @hooks = PropCheck::Hooks.new
53
72
  end
54
73
 
55
74
  ##
@@ -86,21 +105,46 @@ module PropCheck
86
105
  # Only filter if you have few inputs to reject. Otherwise, improve your generators.
87
106
  def where(&condition)
88
107
  original_condition = @condition.dup
89
- @condition = -> { instance_exec(&original_condition) && instance_exec(&condition) }
108
+ @condition = proc do |*args|
109
+ original_condition.call(*args) && condition.call(*args)
110
+ end
111
+
112
+ self
113
+ end
90
114
 
115
+ def before(&hook)
116
+ @hooks.add_before(&hook)
117
+ self
118
+ end
119
+
120
+ def after(&hook)
121
+ @hooks.add_after(&hook)
122
+ self
123
+ end
124
+
125
+ def around(&hook)
126
+ @hooks.add_around(&hook)
91
127
  self
92
128
  end
93
129
 
94
130
  ##
95
131
  # Checks the property (after settings have been altered using the other instance methods in this class.)
96
132
  def check(&block)
97
- binding_generator = PropCheck::Generators.fixed_hash(bindings)
133
+ gens =
134
+ if @kwbindings != {}
135
+ kwbinding_generator = PropCheck::Generators.fixed_hash(**@kwbindings)
136
+ @bindings + [kwbinding_generator]
137
+ else
138
+ @bindings
139
+ end
140
+ binding_generator = PropCheck::Generators.tuple(*gens)
141
+ # binding_generator = PropCheck::Generators.fixed_hash(**@kwbindings)
98
142
 
99
143
  n_runs = 0
100
144
  n_successful = 0
101
145
 
102
146
  # Loop stops at first exception
103
- attempts_enumerator(binding_generator).each do |generator_result|
147
+ attempts_enum(binding_generator).each do |generator_result|
104
148
  n_runs += 1
105
149
  check_attempt(generator_result, n_successful, &block)
106
150
  n_successful += 1
@@ -112,6 +156,10 @@ module PropCheck
112
156
  private def ensure_not_exhausted!(n_runs)
113
157
  return if n_runs >= @config.n_runs
114
158
 
159
+ raise_generator_exhausted!
160
+ end
161
+
162
+ private def raise_generator_exhausted!()
115
163
  raise Errors::GeneratorExhaustedError, """
116
164
  Could not perform `n_runs = #{@config.n_runs}` runs,
117
165
  (exhausted #{@config.max_generate_attempts} tries)
@@ -123,7 +171,7 @@ module PropCheck
123
171
  end
124
172
 
125
173
  private def check_attempt(generator_result, n_successful, &block)
126
- CheckEvaluator.new(generator_result.root, &block).call
174
+ block.call(*generator_result.root)
127
175
 
128
176
  # immediately stop (without shrinnking) for when the app is asked
129
177
  # to close by outside intervention
@@ -151,23 +199,26 @@ module PropCheck
151
199
  raise e, output_string, e.backtrace
152
200
  end
153
201
 
154
- private def attempts_enumerator(binding_generator)
202
+ private def attempts_enum(binding_generator)
203
+ @hooks
204
+ .wrap_enum(raw_attempts_enum(binding_generator))
205
+ .lazy
206
+ .take(@config.n_runs)
207
+ end
155
208
 
209
+ private def raw_attempts_enum(binding_generator)
156
210
  rng = Random::DEFAULT
157
- n_runs = 0
158
211
  size = 1
159
212
  (0...@config.max_generate_attempts)
160
213
  .lazy
161
214
  .map { binding_generator.generate(size, rng) }
162
- .reject { |val| val.root == :"_PropCheck.filter_me" }
163
- .select { |val| CheckEvaluator.new(val.root, &@condition).call }
215
+ .reject { |val| val.root.any? { |elem| elem == :"_PropCheck.filter_me" }}
216
+ .select { |val| @condition.call(*val.root) }
164
217
  .map do |result|
165
- n_runs += 1
166
218
  size += 1
167
219
 
168
220
  result
169
221
  end
170
- .take_while { n_runs <= @config.n_runs }
171
222
  end
172
223
 
173
224
  private def show_problem_output(problem, generator_results, n_successful, &block)
@@ -193,31 +244,36 @@ module PropCheck
193
244
  end
194
245
 
195
246
  private def post_output(output, n_shrink_steps, shrunken_result, shrunken_exception)
196
- output.puts ''
197
- output.puts "Shrunken input (after #{n_shrink_steps} shrink steps):"
198
- output.puts "`#{print_roots(shrunken_result)}`"
199
- output.puts ""
200
- output.puts "Shrunken exception:\n---\n#{shrunken_exception}"
201
- output.puts "---"
202
- output.puts ""
203
-
247
+ if n_shrink_steps == 0
248
+ output.puts '(shrinking impossible)'
249
+ else
250
+ output.puts ''
251
+ output.puts "Shrunken input (after #{n_shrink_steps} shrink steps):"
252
+ output.puts "`#{print_roots(shrunken_result)}`"
253
+ output.puts ""
254
+ output.puts "Shrunken exception:\n---\n#{shrunken_exception}"
255
+ output.puts "---"
256
+ output.puts ""
257
+ end
204
258
  output
205
259
  end
206
260
 
207
- private def print_roots(lazy_tree_hash)
208
- lazy_tree_hash.map do |name, val|
209
- "#{name} = #{val.inspect}"
210
- end.join(", ")
261
+ private def print_roots(lazy_tree_val)
262
+ if lazy_tree_val.is_a?(Array) && lazy_tree_val.length == 1 && lazy_tree_val[0].is_a?(Hash)
263
+ lazy_tree_val[0].ai
264
+ else
265
+ lazy_tree_val.ai
266
+ end
211
267
  end
212
268
 
213
- private def shrink(bindings_tree, io, &fun)
269
+ private def shrink(bindings_tree, io, &block)
214
270
  io.puts 'Shrinking...' if @config.verbose
215
271
  problem_child = bindings_tree
216
272
  siblings = problem_child.children.lazy
217
273
  parent_siblings = nil
218
274
  problem_exception = nil
219
275
  shrink_steps = 0
220
- (0..@config.max_shrink_steps).each do
276
+ @hooks.wrap_enum(0..@config.max_shrink_steps).lazy.each do
221
277
  begin
222
278
  sibling = siblings.next
223
279
  rescue StopIteration
@@ -232,7 +288,7 @@ module PropCheck
232
288
  io.print '.' if @config.verbose
233
289
 
234
290
  begin
235
- CheckEvaluator.new(sibling.root, &fun).call
291
+ block.call(*sibling.root)
236
292
  rescue Exception => e
237
293
  problem_child = sibling
238
294
  parent_siblings = siblings
@@ -1,3 +1,3 @@
1
1
  module PropCheck
2
- VERSION = "0.6.2"
2
+ VERSION = '0.10.0'
3
3
  end
@@ -36,7 +36,5 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  spec.required_ruby_version = '>= 2.5.1'
38
38
 
39
- spec.add_development_dependency "bundler", "~> 2.0"
40
- spec.add_development_dependency "rake", "~> 10.0"
41
- spec.add_development_dependency "rspec", "~> 3.0"
39
+ spec.add_dependency 'awesome_print', '~> 1.8'
42
40
  end
metadata CHANGED
@@ -1,57 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prop_check
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Qqwy/Wiebe-Marten Wijnja
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-04 00:00:00.000000000 Z
11
+ date: 2020-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: awesome_print
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
19
+ version: '1.8'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '3.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '3.0'
26
+ version: '1.8'
55
27
  description: PropCheck allows you to do property-based testing, including shrinking.
56
28
  (akin to Haskell's QuickCheck, Erlang's PropEr, Elixir's StreamData). This means
57
29
  that your test are run many times with different, autogenerated inputs, and as soon
@@ -71,7 +43,6 @@ files:
71
43
  - CHANGELOG.md
72
44
  - CODE_OF_CONDUCT.md
73
45
  - Gemfile
74
- - Gemfile.lock
75
46
  - LICENSE.txt
76
47
  - README.md
77
48
  - Rakefile
@@ -82,11 +53,10 @@ files:
82
53
  - lib/prop_check/generators.rb
83
54
  - lib/prop_check/helper.rb
84
55
  - lib/prop_check/helper/lazy_append.rb
56
+ - lib/prop_check/hooks.rb
85
57
  - lib/prop_check/lazy_tree.rb
86
58
  - lib/prop_check/property.rb
87
- - lib/prop_check/property/check_evaluator.rb
88
59
  - lib/prop_check/property/configuration.rb
89
- - lib/prop_check/rspec.rb
90
60
  - lib/prop_check/version.rb
91
61
  - prop_check.gemspec
92
62
  homepage: https://github.com/Qqwy/ruby-prop_check/
@@ -96,7 +66,7 @@ metadata:
96
66
  homepage_uri: https://github.com/Qqwy/ruby-prop_check/
97
67
  source_code_uri: https://github.com/Qqwy/ruby-prop_check/
98
68
  changelog_uri: https://github.com/Qqwy/ruby-prop_check/CHANGELOG.md
99
- post_install_message:
69
+ post_install_message:
100
70
  rdoc_options: []
101
71
  require_paths:
102
72
  - lib
@@ -111,9 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
81
  - !ruby/object:Gem::Version
112
82
  version: '0'
113
83
  requirements: []
114
- rubyforge_project:
115
- rubygems_version: 2.7.6
116
- signing_key:
84
+ rubygems_version: 3.0.3
85
+ signing_key:
117
86
  specification_version: 4
118
87
  summary: PropCheck allows you to do property-based testing, including shrinking.
119
88
  test_files: []
@@ -1,48 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- prop_check (0.6.1)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- diff-lcs (1.3)
10
- docile (1.3.2)
11
- doctest-core (0.0.2)
12
- doctest-rspec (0.0.3)
13
- doctest-core (~> 0.0.2)
14
- rspec
15
- json (2.2.0)
16
- rake (10.5.0)
17
- rspec (3.8.0)
18
- rspec-core (~> 3.8.0)
19
- rspec-expectations (~> 3.8.0)
20
- rspec-mocks (~> 3.8.0)
21
- rspec-core (3.8.1)
22
- rspec-support (~> 3.8.0)
23
- rspec-expectations (3.8.4)
24
- diff-lcs (>= 1.2.0, < 2.0)
25
- rspec-support (~> 3.8.0)
26
- rspec-mocks (3.8.1)
27
- diff-lcs (>= 1.2.0, < 2.0)
28
- rspec-support (~> 3.8.0)
29
- rspec-support (3.8.2)
30
- simplecov (0.16.1)
31
- docile (~> 1.1)
32
- json (>= 1.8, < 3)
33
- simplecov-html (~> 0.10.0)
34
- simplecov-html (0.10.2)
35
-
36
- PLATFORMS
37
- ruby
38
-
39
- DEPENDENCIES
40
- bundler (~> 2.0)
41
- doctest-rspec
42
- prop_check!
43
- rake (~> 10.0)
44
- rspec (~> 3.0)
45
- simplecov
46
-
47
- BUNDLED WITH
48
- 2.0.2
@@ -1,45 +0,0 @@
1
- module PropCheck
2
- class Property
3
- ##
4
- # A wrapper class that implements the 'Cloaker' concept
5
- # which allows us to refer to variables set in 'bindings',
6
- # while still being able to access things that are only in scope
7
- # in the creator of '&block'.
8
- #
9
- # This allows us to bind the variables specified in `bindings`
10
- # one way during checking and another way during shrinking.
11
- class CheckEvaluator
12
- include RSpec::Matchers if Object.const_defined?('RSpec')
13
-
14
- def initialize(bindings, &block)
15
- @caller = block.binding.receiver
16
- @block = block
17
- define_named_instance_methods(bindings)
18
- end
19
-
20
- def call
21
- self.instance_exec(&@block)
22
- end
23
-
24
- private def define_named_instance_methods(results)
25
- results.each do |name, result|
26
- define_singleton_method(name) { result }
27
- end
28
- end
29
-
30
- ##
31
- # Dispatches to caller whenever something is not part of `bindings`.
32
- # (No need to invoke this method manually)
33
- def method_missing(method, *args, &block)
34
- @caller.__send__(method, *args, &block) || super
35
- end
36
-
37
- ##
38
- # Checks respond_to of caller whenever something is not part of `bindings`.
39
- # (No need to invoke this method manually)
40
- def respond_to_missing?(*args)
41
- @caller.respond_to?(*args) || super
42
- end
43
- end
44
- end
45
- end
@@ -1,14 +0,0 @@
1
- module PropCheck
2
- ##
3
- # Integration with RSpec
4
- module RSpec
5
- # To make it available within examples
6
- def self.extend_object(obj)
7
- obj.define_method(:forall) do |*args, **kwargs, &block|
8
- PropCheck::Property.forall(*args, **kwargs) do
9
- instance_exec(self, &block)
10
- end
11
- end
12
- end
13
- end
14
- end