Testable Class #
Testable propositions have a procedure that can generate counter-examples together with a proof that they invalidate the proposition.
This is a port of the Haskell QuickCheck library.
Creating Customized Instances #
The type classes Testable, SampleableExt and Shrinkable are the
means by which Plausible creates samples and tests them. For instance,
the proposition ∀ i j : Nat, i ≤ j has a Testable instance because Nat
is sampleable and i ≤ j is decidable. Once Plausible finds the Testable
instance, it can start using the instance to repeatedly creating samples
and checking whether they satisfy the property. Once it has found a
counter-example it will then use a Shrinkable instance to reduce the
example. This allows the user to create new instances and apply
Plausible to new situations.
What do I do if I'm testing a property about my newly defined type? #
Let us consider a type made for a new formalization:
structure MyType where
  x : Nat
  y : Nat
  h : x ≤ y
  deriving Repr
How do we test a property about MyType? For instance, let us consider
Testable.check <| ∀ a b : MyType, a.y ≤ b.x → a.x ≤ b.y. Writing this
property as is will give us an error because we do not have an instance
of Shrinkable MyType and SampleableExt MyType. We can define one as follows:
instance : Shrinkable MyType where
  shrink := fun ⟨x, y, _⟩ =>
    let proxy := Shrinkable.shrink (x, y - x)
    proxy.map (fun (fst, snd) => ⟨fst, fst + snd, by omega⟩)
instance : SampleableExt MyType :=
  SampleableExt.mkSelfContained do
    let x ← SampleableExt.interpSample Nat
    let xyDiff ← SampleableExt.interpSample Nat
    return ⟨x, x + xyDiff, by omega⟩
Again, we take advantage of the fact that other types have useful
Shrinkable implementations, in this case Prod.
Main definitions #
- Testableclass
- Testable.check: a way to test a proposition using random examples
References #
Result of trying to disprove p
- success
{p : Prop}
 : Unit ⊕' p → TestResult pSucceed when we find another example satisfying p. Insuccess h,his an optional proof of the proposition. Without the proof, all we know is that we found one example wherepholds. With a proof, the one test was sufficient to prove thatpholds and we do not need to keep finding examples.
- gaveUp
{p : Prop}
 : Nat → TestResult pGive up when a well-formed example cannot be generated. gaveUp ntells us thatninvalid examples were tried.
- failure
{p : Prop}
 : ¬p → List String → Nat → TestResult pA counter-example to p; the strings specify values for the relevant variables.failure h vs nalso carries a proof thatpdoes not hold. This way, we can guarantee that there will be no false positive. The last component,n, is the number of times that the counter-example was shrunk.
Instances For
Equations
Instances For
Configuration for testing a property.
- numInst : NatHow many test instances to generate. 
- maxSize : NatThe maximum size of the values to generate. 
- numRetries : Nat
- traceDiscarded : BoolEnable tracing of values that didn't fulfill preconditions and were thus discarded. 
- traceSuccesses : BoolEnable tracing of values that fulfilled the property and were thus discarded. 
- traceShrink : BoolEnable basic tracing of shrinking. 
- traceShrinkCandidates : BoolEnable tracing of all attempted values during shrinking. 
- Hard code the seed to use for the RNG 
- quiet : BoolDisable output. 
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Allow elaboration of Configuration arguments to tactics.
Equations
- One or more equations did not get rendered due to their size.
Instances For
PrintableProp p allows one to print a proposition so that
Plausible can indicate how values relate to each other.
It's basically a poor man's delaborator.
- printProp : String
Instances
Equations
- Plausible.instPrintableProp = { printProp := "⋯" }
Equations
- Plausible.NamedBinder _n p = p
Instances For
Equations
- (Plausible.TestResult.success (PSum.inl val)).toString = "success (no proof)"
- (Plausible.TestResult.success (PSum.inr val)).toString = "success (proof)"
- (Plausible.TestResult.gaveUp n).toString = toString "gave " ++ toString n ++ toString " times"
- (Plausible.TestResult.failure a counters a_1).toString = toString "failed " ++ toString counters
Instances For
Equations
Combine the test result for properties p and q to create a test for their conjunction.
Equations
- (Plausible.TestResult.failure h xs n).and x✝ = Plausible.TestResult.failure ⋯ xs n
- x✝.and (Plausible.TestResult.failure h xs n) = Plausible.TestResult.failure ⋯ xs n
- (Plausible.TestResult.success h1).and (Plausible.TestResult.success h2) = Plausible.TestResult.success (Plausible.TestResult.combine (Plausible.TestResult.combine (PSum.inr ⋯) h1) h2)
- (Plausible.TestResult.gaveUp n).and (Plausible.TestResult.gaveUp m) = Plausible.TestResult.gaveUp (n + m)
- (Plausible.TestResult.gaveUp n).and x✝ = Plausible.TestResult.gaveUp n
- x.and (Plausible.TestResult.gaveUp n) = Plausible.TestResult.gaveUp n
Instances For
Combine the test result for properties p and q to create a test for their disjunction.
Equations
- (Plausible.TestResult.failure h1 xs n).or (Plausible.TestResult.failure h2 ys m) = Plausible.TestResult.failure ⋯ (xs ++ ys) (n + m)
- (Plausible.TestResult.success h).or x✝ = Plausible.TestResult.success (Plausible.TestResult.combine (PSum.inr ⋯) h)
- x✝.or (Plausible.TestResult.success h) = Plausible.TestResult.success (Plausible.TestResult.combine (PSum.inr ⋯) h)
- (Plausible.TestResult.gaveUp n).or (Plausible.TestResult.gaveUp m) = Plausible.TestResult.gaveUp (n + m)
- (Plausible.TestResult.gaveUp n).or x✝ = Plausible.TestResult.gaveUp n
- x.or (Plausible.TestResult.gaveUp n) = Plausible.TestResult.gaveUp n
Instances For
If q → p, then ¬ p → ¬ q which means that testing p can allow us
to find counter-examples to q.
Equations
- Plausible.TestResult.imp h (Plausible.TestResult.failure h2 xs n) p = Plausible.TestResult.failure ⋯ xs n
- Plausible.TestResult.imp h (Plausible.TestResult.success h2) p = Plausible.TestResult.success (Plausible.TestResult.combine p h2)
- Plausible.TestResult.imp h (Plausible.TestResult.gaveUp n) p = Plausible.TestResult.gaveUp n
Instances For
Test q by testing p and proving the equivalence between the two.
Equations
- Plausible.TestResult.iff h r = Plausible.TestResult.imp ⋯ r (PSum.inr ⋯)
Instances For
When we assign a value to a universally quantified variable, we record that value using this function so that our counter-examples can be informative.
Equations
- Plausible.TestResult.addInfo x h (Plausible.TestResult.failure h2 xs n) p = Plausible.TestResult.failure ⋯ (x :: xs) n
- Plausible.TestResult.addInfo x h r p = Plausible.TestResult.imp h r p
Instances For
Add some formatting to the information recorded by addInfo.
Equations
- Plausible.TestResult.addVarInfo var x h r p = Plausible.TestResult.addInfo (toString var ++ toString " := " ++ toString (repr x)) h r p
Instances For
Instances For
A configuration with all the trace options enabled, useful for debugging.
Equations
Instances For
Equations
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Format the counter-examples found in a test failure.
Equations
- Plausible.Testable.formatFailure s xs n = "\n".intercalate ["\n===================", s, "\n".intercalate xs, toString "(" ++ toString n ++ toString " shrinks)", "-------------------"]
Instances For
Increase the number of shrinking steps in a test result.
Equations
- Plausible.Testable.addShrinks n (Plausible.TestResult.failure h2 xs n_1) = Plausible.TestResult.failure h2 xs (n_1 + n)
- Plausible.Testable.addShrinks n x✝ = x✝
Instances For
Shrink a counter-example x by using Shrinkable.shrink x, picking the first
candidate that falsifies a property and recursively shrinking that one.
The process is guaranteed to terminate because shrink x produces
a proof that all the values it produces are smaller (according to SizeOf)
than x.
Once a property fails to hold on an example, look for smaller counter-examples to show the user.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Test a universal property by creating a sample of the right type and instantiating the bound variable with it.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
- Plausible.And.printableProp = { printProp := toString (Plausible.printProp x) ++ toString " ∧ " ++ toString (Plausible.printProp y) }
Equations
- Plausible.Or.printableProp = { printProp := toString (Plausible.printProp x) ++ toString " ∨ " ++ toString (Plausible.printProp y) }
Equations
- Plausible.Iff.printableProp = { printProp := toString (Plausible.printProp x) ++ toString " ↔ " ++ toString (Plausible.printProp y) }
Equations
- Plausible.Imp.printableProp = { printProp := toString (Plausible.printProp x) ++ toString " → " ++ toString (Plausible.printProp y) }
Equations
- Plausible.Not.printableProp = { printProp := toString "¬" ++ toString (Plausible.printProp x) }
Equations
- Plausible.True.printableProp = { printProp := "True" }
Equations
- Plausible.False.printableProp = { printProp := "False" }
Execute cmd and repeat every time the result is gaveUp (at most n times).
Count the number of times the test procedure gave up.
Equations
- Plausible.giveUp x (Plausible.TestResult.success (PSum.inl PUnit.unit)) = Plausible.TestResult.gaveUp x
- Plausible.giveUp x (Plausible.TestResult.success (PSum.inr p_1)) = Plausible.TestResult.success (PSum.inr p_1)
- Plausible.giveUp x (Plausible.TestResult.gaveUp n) = Plausible.TestResult.gaveUp (n + x)
- Plausible.giveUp x (Plausible.TestResult.failure h xs n) = Plausible.TestResult.failure h xs n
Instances For
Try n times to find a counter-example for p.
Try to find a counter-example of p.
Equations
- Plausible.Testable.runSuite p cfg = Plausible.Testable.runSuiteAux p cfg (Plausible.TestResult.success (PSum.inl ())) cfg.numInst
Instances For
Run a test suite for p in IO using the global RNG in stdGenRef.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Traverse the syntax of a proposition to find universal quantifiers
quantifiers and add NamedBinder annotations next to them.
DecorationsOf p is used as a hint to mk_decorations to specify
that the goal should be satisfied with a proposition equivalent to p
with added annotations.
Equations
Instances For
In a goal of the shape ⊢ DecorationsOf p, mk_decoration examines
the syntax of p and adds NamedBinder around universal quantifications
to improve error messages. This tool can be used in the declaration of a
function as follows:
def foo (p : Prop) (p' : Decorations.DecorationsOf p := by mk_decorations) [Testable p'] : ...
p is the parameter given by the user, p' is a definitionally equivalent
proposition where the quantifiers are annotated with NamedBinder.
Equations
- Plausible.Decorations.tacticMk_decorations = Lean.ParserDescr.node `Plausible.Decorations.tacticMk_decorations 1024 (Lean.ParserDescr.nonReservedSymbol "mk_decorations" false)
Instances For
Run a test suite for p and throw an exception if p does not hold.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Plausible.«command#test_» = Lean.ParserDescr.node `Plausible.«command#test_» 1022 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "#test ") (Lean.ParserDescr.cat `term 0))