https://github.com/jobjo/popper
Property-based testing at ease
https://github.com/jobjo/popper
Last synced: 8 months ago
JSON representation
Property-based testing at ease
- Host: GitHub
- URL: https://github.com/jobjo/popper
- Owner: jobjo
- License: isc
- Created: 2021-03-30T09:13:57.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2021-08-15T17:42:03.000Z (over 4 years ago)
- Last Synced: 2024-08-04T01:28:31.290Z (over 1 year ago)
- Language: OCaml
- Homepage:
- Size: 1.36 MB
- Stars: 43
- Watchers: 5
- Forks: 1
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGES.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-list - popper - based testing at ease | jobjo | 29 | (OCaml)
README
# Property-based testing at ease
[](https://github.com/jobjo/popper/actions)
[](https://jobjo.github.io/popper/api)
[Popper](https://github.com/jobjo/popper) is an OCaml testing library that can
be used for writing simple *unit-tests* as well as *property-based* ones. Its
underlying design is inspired by the Python library
[Hypothesis](https://hypothesis.readthedocs.io/en/latest/).
See the [documentation page](https://jobjo.github.io/popper/) for information on
how to get started.
## Overview
High-level features of Popper include:
- A uniform API for defining regular unit- and property-based tests.
- Embedded shrinking — invariants used when constructing samples for property-based tests are always respected.
- Compositional design — tests may be bundled and nested arbitrarily.
- Ships with a `ppx` for automatically deriving *comparator* and *sample* functions for custom data types.
- Deterministic (and reproducible) results.
- Colorful output (cred goes to [Alcotest](https://github.com/mirage/alcotest), couldn't resist some inspiration).
- Support for line-number reporting, timing and logging.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for how to build and contribute to
Popper.
## Learn
- Check out the [getting started](https://jobjo.github.io/popper/getting_started) section for a step by step introduction.
- Take a look at some examples in the [examples](https://github.com/jobjo/popper/tree/main/examples) folder.
- Browse the [API docs](https://jobjo.github.io/popper/api).
## Show me an example
Here's what test output might look like:
It was generated from the following code:
```ocaml
open Popper
open Sample.Syntax
type exp =
| Lit of bool
| And of exp * exp
| Or of exp * exp
| Not of exp
[@@deriving show, ord, popper]
(* A buggy evaluator function *)
let rec eval = function
| Lit b -> b
| And (e1, e2) -> eval e1 || eval e2
| Or (e1, e2) -> eval e1 || eval e2
| Not b -> not @@ eval b
(* A simple unit test *)
let test_hello_world =
test @@ fun () ->
equal Comparator.string "hello world" (String.lowercase_ascii "Hello World")
(* Another unit test *)
let test_lit_true = test @@ fun () -> is_true (eval (Lit true) = true)
(* A property-based test *)
let test_false_ident_or =
test @@ fun () ->
let* e = exp_sample in
is_true (eval e = eval (Or (Lit false, e)))
(* Another property-based test *)
let test_true_ident_and =
test @@ fun () ->
let* e = Sample.with_log "e" pp_exp exp_sample in
is_true ~loc:__LOC__ (eval e = eval (And (Lit true, e)))
(* Bundle some tests together *)
let exp_suite =
suite
[ ("Lit true", test_lit_true)
; ("False ident or", test_false_ident_or)
; ("True ident and", test_true_ident_and)
]
(* Top-level test-suite *)
let suite =
suite [ ("Hello World", test_hello_world); ("Expression", exp_suite) ]
let () = run suite
```
## Comparing with other libraries
Popper is designed with the following objectives in mind:
1. Make it as seamless as possible to write property-based tests — for instance
by using a ppx to derive *sample* functions for custom data-types.
2. Use embedded shrinking (ala
[Hypothesis](https://hypothesis.readthedocs.io/en/latest/)) and eliminate the
need for writing *shrinkers* manually.
The property-based aspects overlap with the OCaml libraries
[QCheck](https://github.com/c-cube/qcheck) and
[Crowbar](https://github.com/stedolan/crowbar).
Popper also supports writing simple unit tests and the ability to compose tests
into suites. This API and the output is partly inspired by the testing
library [Alcotest](https://github.com/mirage/alcotest).
Here's a table comparing features across different OCaml testing libraries:
| Library | Test suites | Property-based | Embeded shrinking | PPX generators | Fuzzying
| --------------------------------------------------------------------------|:-------------:|:--------------:|:-----------------:|:--------------:|:---------:|
| [Popper](https://github.com/jobjo/popper) | ✅ | ✅ | ✅ | ✅ | ❌
| [Alcotest](https://github.com/mirage/alcotest) | ✅ | ❌ | - | ❌ | -
| [OUnit](https://github.com/gildor478/ounit) | ✅ | ❌ | - | ❌ | -
| [QCheck](https://github.com/c-cube/qcheck) | ✅ | ✅ | ❌ | ❌ | ❌
| [Crowbar](https://github.com/stedolan/crowbar) | ❌ | ✅ | ❌ | ❌ | ✅
| [Base_quickcheck](https://opensource.janestreet.com/base_quickcheck/) | ❌ | ✅ | ❌ | ✅ | ❌
It might be possible to write some adaptors to be able to integrate with
these libraries but nothing such exists at the moment.