Class: PropCheck::Property
- Inherits:
-
Object
- Object
- PropCheck::Property
- Defined in:
- lib/prop_check/property.rb,
lib/prop_check/property/configuration.rb
Overview
Create and run property-checks.
For simple usage, see ‘.forall`.
For advanced usage, call ‘PropCheck::Property.new(…)` and then configure it to your liking using e.g. `#with_config`, `#before`, `#after`, `#around` etc. Each of these methods will return a new `Property`, so earlier properties are not mutated. This allows you to re-use configuration and hooks between multiple tests.
Defined Under Namespace
Modules: OutputFormatter Classes: Configuration, Shrinker
Class Method Summary collapse
-
.configuration ⇒ Object
Returns the default configuration of the library as it is configured right now for introspection.
-
.configure {|configuration| ... } ⇒ Object
Yields the library’s configuration object for you to alter.
-
.forall(*bindings, **kwbindings, &block) ⇒ Object
Main entry-point to create (and possibly immediately run) a property-test.
Instance Method Summary collapse
-
#after(&hook) ⇒ Object
Calls ‘hook` after each time a check is run with new data.
-
#around(&hook) ⇒ Object
Calls ‘hook` around each time a check is run with new data.
-
#before(&hook) ⇒ Object
Calls ‘hook` before each time a check is run with new data.
-
#check(&block) ⇒ Object
Checks the property (after settings have been altered using the other instance methods in this class.).
-
#configuration ⇒ Object
Returns the configuration of this property for introspection.
-
#growing_exponentially(&block) ⇒ Object
Resizes all generators in this property.
-
#growing_fast(&block) ⇒ Object
Resizes all generators in this property.
-
#growing_logarithmically(&block) ⇒ Object
Resizes all generators in this property.
-
#growing_quadratically(&block) ⇒ Object
Resizes all generators in this property.
-
#growing_slowly(&block) ⇒ Object
Resizes all generators in this property.
-
#initialize(*bindings, **kwbindings) ⇒ Property
constructor
A new instance of Property.
-
#resize(&block) ⇒ Object
Resizes all generators in this property with the given function.
-
#where(&condition) ⇒ Object
filters the generator using the given ‘condition`.
- #with_bindings(*bindings, **kwbindings) ⇒ Object
-
#with_config(**config, &block) ⇒ Object
Allows you to override the configuration of this property by giving a hash with new settings.
Constructor Details
#initialize(*bindings, **kwbindings) ⇒ Property
Returns a new instance of Property.
66 67 68 69 70 71 72 |
# File 'lib/prop_check/property.rb', line 66 def initialize(*bindings, **kwbindings) @config = self.class.configuration @hooks = PropCheck::Hooks.new @gen = gen_from_bindings(bindings, kwbindings) unless bindings.empty? && kwbindings.empty? freeze end |
Class Method Details
.configuration ⇒ Object
Returns the default configuration of the library as it is configured right now for introspection.
For the configuration of a single property, check its ‘configuration` instance method. See PropCheck::Property::Configuration for more info on available settings.
55 56 57 |
# File 'lib/prop_check/property.rb', line 55 def self.configuration @configuration ||= Configuration.new end |
.configure {|configuration| ... } ⇒ Object
Yields the library’s configuration object for you to alter. See PropCheck::Property::Configuration for more info on available settings.
62 63 64 |
# File 'lib/prop_check/property.rb', line 62 def self.configure yield(configuration) end |
.forall(*bindings, **kwbindings, &block) ⇒ Object
Main entry-point to create (and possibly immediately run) a property-test.
This method accepts a list of generators and a block. The block will then be executed many times, passing the values generated by the generators as respective arguments:
“‘ include PropCheck::Generators PropCheck.forall(integer(), float()) { |x, y| … } “`
It is also possible (and recommended when having more than a few generators) to use a keyword-list of generators instead:
“‘ include PropCheck::Generators PropCheck.forall(x: integer(), y: float()) { |x:, y:| … } “`
If you do not pass a block right away, a Property object is returned, which you can call the other instance methods of this class on before finally passing a block to it using ‘#check`. (so `forall(Generators.integer) do |val| … end` and forall(Generators.integer).check do |val| … end` are the same)
44 45 46 47 |
# File 'lib/prop_check/property.rb', line 44 def self.forall(*bindings, **kwbindings, &block) new(*bindings, **kwbindings) .check(&block) end |
Instance Method Details
#after(&hook) ⇒ Object
Calls ‘hook` after each time a check is run with new data.
This is useful to add teardown logic When called multiple times, earlier-added hooks will be called after ‘hook` is called.
216 217 218 219 220 221 |
# File 'lib/prop_check/property.rb', line 216 def after(&hook) duplicate = dup duplicate.instance_variable_set(:@hooks, @hooks.add_after(&hook)) duplicate.freeze duplicate end |
#around(&hook) ⇒ Object
Calls ‘hook` around each time a check is run with new data.
‘hook` should `yield` to the passed block.
When called multiple times, earlier-added hooks will be wrapped around ‘hook`.
Around hooks will be called after all ‘#before` hooks and before all `#after` hooks.
Note that if the block passed to ‘hook` raises an exception, it is possible for the code after `yield` not to be called. So make sure that cleanup logic is wrapped with the `ensure` keyword.
236 237 238 239 240 241 |
# File 'lib/prop_check/property.rb', line 236 def around(&hook) duplicate = dup duplicate.instance_variable_set(:@hooks, @hooks.add_around(&hook)) duplicate.freeze duplicate end |
#before(&hook) ⇒ Object
Calls ‘hook` before each time a check is run with new data.
This is useful to add setup logic When called multiple times, earlier-added hooks will be called before ‘hook` is called.
204 205 206 207 208 209 |
# File 'lib/prop_check/property.rb', line 204 def before(&hook) duplicate = dup duplicate.instance_variable_set(:@hooks, @hooks.add_before(&hook)) duplicate.freeze duplicate end |
#check(&block) ⇒ Object
Checks the property (after settings have been altered using the other instance methods in this class.)
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/prop_check/property.rb', line 245 def check(&block) return self unless block_given? n_runs = 0 n_successful = 0 # Loop stops at first exception attempts_enum(@gen).each do |generator_result| n_runs += 1 check_attempt(generator_result, n_successful, &block) n_successful += 1 end ensure_not_exhausted!(n_runs) end |
#configuration ⇒ Object
Returns the configuration of this property for introspection.
See PropCheck::Property::Configuration for more info on available settings.
90 91 92 |
# File 'lib/prop_check/property.rb', line 90 def configuration @config end |
#growing_exponentially(&block) ⇒ Object
Resizes all generators in this property. The new size is ‘2.pow(orig_size)`
c.f. #resize
124 125 126 127 128 |
# File 'lib/prop_check/property.rb', line 124 def growing_exponentially(&block) orig_fun = @config.resize_function fun = proc { |size| 2.pow(orig_fun.call(size)) } with_config(resize_function: fun, &block) end |
#growing_fast(&block) ⇒ Object
Resizes all generators in this property. The new size is ‘2 * orig_size`
c.f. #resize
144 145 146 147 148 |
# File 'lib/prop_check/property.rb', line 144 def growing_fast(&block) orig_fun = @config.resize_function fun = proc { |size| orig_fun.call(size) * 2 } with_config(resize_function: fun, &block) end |
#growing_logarithmically(&block) ⇒ Object
Resizes all generators in this property. The new size is ‘Math.log2(orig_size)`
c.f. #resize
164 165 166 167 168 |
# File 'lib/prop_check/property.rb', line 164 def growing_logarithmically(&block) orig_fun = @config.resize_function fun = proc { |size| Math.log2(orig_fun.call(size)) } with_config(resize_function: fun, &block) end |
#growing_quadratically(&block) ⇒ Object
Resizes all generators in this property. The new size is ‘orig_size * orig_size`
c.f. #resize
134 135 136 137 138 |
# File 'lib/prop_check/property.rb', line 134 def growing_quadratically(&block) orig_fun = @config.resize_function fun = proc { |size| orig_fun.call(size).pow(2) } with_config(resize_function: fun, &block) end |
#growing_slowly(&block) ⇒ Object
Resizes all generators in this property. The new size is ‘0.5 * orig_size`
c.f. #resize
154 155 156 157 158 |
# File 'lib/prop_check/property.rb', line 154 def growing_slowly(&block) orig_fun = @config.resize_function fun = proc { |size| orig_fun.call(size) * 0.5 } with_config(resize_function: fun, &block) end |
#resize(&block) ⇒ Object
Resizes all generators in this property with the given function.
Shorthand for manually wrapping ‘PropCheck::Property::Configuration.resize_function` with the new function.
113 114 115 116 117 118 |
# File 'lib/prop_check/property.rb', line 113 def resize(&block) raise '#resize called without a block' unless block_given? orig_fun = @config.resize_function with_config(resize_function: block) end |
#where(&condition) ⇒ Object
filters the generator using the given ‘condition`. The final property checking block will only be run if the condition is truthy.
If wanted, multiple ‘where`-conditions can be specified on a property. Be aware that if you filter away too much generated inputs, you might encounter a GeneratorExhaustedError. Only filter if you have few inputs to reject. Otherwise, improve your generators.
187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/prop_check/property.rb', line 187 def where(&condition) unless @gen raise ArgumentError, 'No generator bindings specified! #where should be called after `#forall` or `#with_bindings`.' end duplicate = dup duplicate.instance_variable_set(:@gen, @gen.where(&condition)) duplicate.freeze duplicate end |
#with_bindings(*bindings, **kwbindings) ⇒ Object
170 171 172 173 174 175 176 177 |
# File 'lib/prop_check/property.rb', line 170 def with_bindings(*bindings, **kwbindings) raise ArgumentError, 'No bindings specified!' if bindings.empty? && kwbindings.empty? duplicate = dup duplicate.instance_variable_set(:@gen, gen_from_bindings(bindings, kwbindings)) duplicate.freeze duplicate end |
#with_config(**config, &block) ⇒ Object
Allows you to override the configuration of this property by giving a hash with new settings.
If no other changes need to occur before you want to check the property, you can immediately pass a block to this method. (so ‘forall(a: Generators.integer).with_config(verbose: true) do … end` is the same as `forall(a: Generators.integer).with_config(verbose: true).check do … end`)
101 102 103 104 105 106 107 |
# File 'lib/prop_check/property.rb', line 101 def with_config(**config, &block) duplicate = dup duplicate.instance_variable_set(:@config, @config.merge(config)) duplicate.freeze duplicate.check(&block) end |