Sleuth
Extremely opinionated testing framework generating an exact specification and reducing code to its minimal implementation.
At a Glance
This library takes the idea behind mutation testing to its extreme.
Mutation testing believes that small errors in your source code (like a > b
instead of a >= b
) are likely errors; when they happen, your tests should fail, and mutation testing frameworks make sure they do. When your test suite fails to recognize a bug, it means you need to add a new test.
Rust already has mutation testing frameworks which I admire and don't attempt to replace. This library is an experiment in mutating all of your code, proving by brute force that no function shorter than the one you've written can meet your specifications. It should encourage test-driven development without the burden of writing an exhaustive test suite beforehand; after an initial attempt, your tests and your implementation will evolve together as you encounter all the ways something might be done and eventually narrow down to what you wanted all along.
The library also takes inspiration from property-based testing like Haskell's QuickCheck
. Your tests can be written with reusable properties and told not to pass with !
, like the following:
use sleuth;
Note a few things:
roundtrip
returns a bool to indicate success or failure instead ofpanic
king like a usual test.- The
sleuth
attribute takes a function with its first argument missing (here,roundtrip
withoutf
), and that argument is filled in at compile time with the function the attribute is applied to (here,add_one
andsub_one
). - We don't spam
roundtrip
with a bunch of random inputs (though you can do that separately!). Instead, you choose your inputs (here,42
both times), and the library helps you find the minimal set that knocks out all mutations.
The library is still under development—I'm an undergrad with a chronic lack of free time—but currently, it can run a test suite of properties like above, and fairly soon it should be able to reduce common cases like the following:
to their minimal implementations:
which usual mutation testing could never (and doesn't aim to) fix. Clippy can currently fix trivial errors like these on a whitelisted basis, but this library aims to eliminate the whole class of errors from the bottom up rather than playing whack-a-mole.
How it Works
Given a function like this,
const
the sleuth
attribute rewrites it at compile time as the following:
const
You can view this expansion by running EXPAND=1 cargo expand
. The EXPAND
environment variable turns #[cfg(test)]
and #[test]
into nonsense so that cargo expand
doesn't assume we're not testing and delete the whole module.
Note that unless we're testing, the macro has no effect. It should be safe to use even in production.