Property Based Testing with Deno test runner
Want to start playing with property-based testing in Deno? Welcome to this short and concise tutorial on integrating fast-check within Deno.
:::info Runner-agnostic patterns
fast-check does not ship a dedicated connector for Deno: you use it the same way you would with any other runner. For the generic sync and async patterns, along with tips on sharing configuration via fc.configureGlobal, refer to our Manual setup page. The rest of this tutorial focuses on the Deno-specific bits.
:::
Your first test
Let's write a test for FizzBuzz using fast-check.
import { assertStringIncludes } from "jsr:@std/assert";
import fc from "npm:fast-check";
Deno.test({
name: "should print Fizz whenever divisible by 3",
fn() {
fc.assert(
fc.property(
fc.nat().map((n) => n * 3),
(n) => {
assertStringIncludes(fizzbuzz(n), "Fizz");
}
)
);
},
});
// Code under test: should rather be imported from another file
function fizzbuzz(n: number): string {
return n % 3 === 0
? n % 5 === 0
? "Fizz Buzz"
: "Fizz"
: n % 5 === 0
? "Buzz"
: String(n);
}
You can now execute it by running the following command in a terminal:
deno test
You've written and executed your first Property-Based Test using the Deno test runner 🚀
Going further
Property-based testing can be leveraged to test complex systems. This snippet was just a simple Hello-World example to give you a basic starting point. Our documentation provides advanced tricks to push the technique further, including detecting race conditions and finding vulnerabilities.
FizzBuzz alone can also be extended with more properties. You may want to refer to this article for more ideas.