consistency tutorial
This page is for contributors: it shows how to run the cross-package agreement
tests and how to add one when you add an operation to both immut and
mutable. The reasoning is in the consistency design.
Quick start
From the repository root:
moon test -p consistency
All tests run on the default target; the package has no target-specific code.
Everyday tasks
Add an agreement test
Build the same input in both packages, apply the operation, and compare a
common observation. The shape of such a test, as it would appear in
src/consistency/core_wbtest.mbt:
///|
test "anti_trace stays aligned" {
let imm = @immut.Matrix::from_2d_array([[1, 2], [3, 4]])
let mut_m = @mutable.Matrix::from_2d_array([[1, 2], [3, 4]])
inspect(
imm.anti_trace().unwrap(),
content=mut_m.anti_trace().unwrap().to_string(),
)
}
Add a law as a property
Use quick_check_fn with tuples of small integers, and return a Bool that
compares both sides of the law in both packages. Integers keep the comparison
exact.
The same idea works in your own code. This check, compiled with the manual, compares the two packages on a product:
///|
test "products agree across packages" {
let rows = [[1, -2], [3, 4]]
let i = @immut.Matrix::from_2d_array(rows)
let m = @mutable.Matrix::from_2d_array(rows)
debug_inspect((i * i).to_array() == (m * m).to_array(), content="true")
}
Going further
When an operation is intentionally different between the packages, add a test that states the difference and mention it in both API pages.
Common pitfalls
- Comparing
Doubleresults with==. Kernels sum in different orders; keep agreement tests on integers. - Comparing
to_stringacross element types. Useto_arraywhen the printed forms may differ only in formatting.
Next steps
- consistency API for the list of tests.
- immut API and mutable API.