qcheck

QuickCheck-inspired property-based testing with integrated shrinking for Gleam.

Rather than specifying test cases manually, you describe the invariants that values of a given type must satisfy (“properties”). Then, generators generate lots of values (test cases) on which the properties are checked. Finally, if a value is found for which a given property does not hold, that value is “shrunk” in order to find an nice, informative counter-example that is presented to you.

While there are a ton of great articles introducing quickcheck or property-based testing, here are a couple general resources that you may enjoy:

Usage

The main modules that you will be interacting with are qcheck/qtest and qcheck/generator.

Example

Here is a short example to get you started. It assumes you are using gleeunit to run the tests, but any test runner will do.

import gleeunit/should
import qcheck/generator
import qcheck/qtest
import qcheck/qtest/config as qtest_config

pub fn small_positive_or_zero_int__test() {
  qtest.run(
    config: qtest_config.default(),
    generator: generator.small_positive_or_zero_int(),
    property: fn(n) { n + 1 == 1 + n },
  )
  |> should.equal(Ok(Nil))
}

pub fn small_positive_or_zero_int__failures_shrink_to_zero__test() {
  qtest.run(
    config: qtest_config.default(),
    generator: generator.small_positive_or_zero_int(),
    property: fn(n) { n + 1 != 1 + n },
  )
  |> should.equal(Error(0))
}

More examples

The test directory of this repository has many examples of setting up tests, using the built-in generators, and creating new generators. Until more dedicated documentation is written, the tests can provide some good info, as they exercise most of the available behavior of the qtest and generator modules.

Integrating with testing frameworks

You don’t have to do anything special to integrate qcheck with a testing framework like gleeunit. The only thing required is that your testing framework of choice be able to check the return values of qtest.run (or qtest.run_result).

Roadmap

While qcheck has a lot of features needed to get started with property-based testing, there are still things that could be added or improved.

Generators

Other stuff

Acknowledgements

Very heavily inspired by the qcheck and base_quickcheck OCaml packages, and of course, the Haskell libraries from which they take inspiration.

License

license MIT or Apache 2.0

Copyright (c) 2024 Ryan M. Moore

Licensed under the Apache License, Version 2.0 or the MIT license, at your option. This program may not be copied, modified, or distributed except according to those terms.

Search Document