Predicates - english/speculation GitHub Wiki
Predicates are at the core of Speculation. They are used to validate simple values and are built upon to conform complex, nested and branching data structures. They enable runtime instrumentation of methods, verifying arguments and return values. In many cases they provide random data generation for free.
There are several ways to define a basic predicate:
Proc (call-able)
This is the most versatile kind of predicate. If the Proc's return value is truthy then it's valid, otherwise it's invalid.
S.valid?(->(x) { x.is_a?(Integer) }, 1) # => trueS.valid?(->(x) { x.even? }, 1) # => falseS.valid?(:odd?.to_proc, 1) # => trueS.valid?(->(x) { x.match?(/foo/) }, "bar") # => falseS.valid?(->(x) { x.nil? || x.even? }, nil) # => true
Moreover, anything that responds to #call can be used in this fashion.
class MyPredicate
def call(x)
x.between?(1..100)
end
end
S.valid?(MyPredicate.new, 5) # => true
Regexp
A regular expression is a good choice when validating a string is in the expected format,.
S.valid?(/\Afoo\z/i, "FoO") # => true
S.valid?(/\Afoo\z/i, "bar") # => false
S.valid?(/baz/, "foobarbaz") # => true
Class or Module
is_a? checks are performed when supplying a Class or Module as the predicate.
S.valid?(Integer, 1) # => true
S.valid?(Array, [1]) # => true
S.valid?(Enumerable, [1]) # => true
S.valid?(String, 1) # => false
Set
Set membership is performed when a set is given as a predicate.
S.valid?(Set[1, 2, 3], 1) # => true
S.valid?(Set[:a, :b, :c], 1) # => false
S.valid?(Set.new("a".."z"), "g") # => true