Package Exports
- fast-check
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (fast-check) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Property based testing framework for JavaScript/TypeScript
Getting started
Hands-on tutorial and definition of Property Based Testing: 🏁 see tutorial.
Property based testing frameworks check the truthfulness of properties. A property is a statement like: for all (x, y, ...) such as precondition(x, y, ...) holds property(x, y, ...) is true.
Install the module with: npm install fast-check --save-dev
Example of integration in mocha:
const fc = require('fast-check');
// Code under tests
const contains = (text, pattern) => text.indexOf(pattern) >= 0;
// Properties
describe('properties', () => {
// string text always contains itself
it('should always contain itself', () => {
fc.assert(fc.property(fc.string(), text => contains(text, text)));
});
// string a + b + c always contains b, whatever the values of a, b and c
it('should always contain its substrings', () => {
fc.assert(fc.property(fc.string(), fc.string(), fc.string(), (a,b,c) => contains(a+b+c, b)));
});
});In case of failure, the test raises a red flag. Its output should help you to diagnose what went wrong in your implementation. Example with a failing implementation of contain:
1) should always contain its substrings
Error: Property failed after 1 tests (seed: 1527422598337, path: 0:0): ["","",""]
Shrunk 1 time(s)
Got error: Property failed by returning false
Hint: Enable verbose mode in order to have the list of all failing values encountered during the runIntegration with other test frameworks: ava, jasmine, jest, mocha and tape.
More examples: simple examples, fuzzing and against various algorithms.
Useful documentations:
- 🏁 Introduction to Property Based & Hands On
- 🐣 Built-in arbitraries
- 🔧 Custom arbitraries
- 🏃♂️ Property based runners
- 💥 Tips
- 🔍 Generated documentation
In a web-page
In order to use fast-check from a web-page (for instance with QUnit or other testing tools), you have to reference the web-aware script as follow:
<script src="https://cdn.jsdelivr.net/npm/fast-check/lib/bundle.js"></script>You can also reference a precise version by setting the version you want in the url:
<script src="https://cdn.jsdelivr.net/npm/fast-check@0.0.11/lib/bundle.js"></script>Once it has been included, fast-check becomes accessible directly by calling fastcheck (in window.fastcheck). I highly recommend you to alias it by fc whenever possible by running const fc = fastcheck at the beginning of the scripts using it.
Why should I migrate to fast-check?
fast-check has initially be designed in an attempt to cope with limitations I encountered while using other property based testing frameworks designed for JavaScript:
- strong and up-to-date types - thanks to TypeScript
- ability to shrink on
fc.oneof- surprisingly some frameworks don't - easy
mapmethod to derive existing arbitraries while keeping shrink - some frameworks ask the user to provide both a->b and b->a mappings in order to keep a shrinker - kind of flatMap-operation called
chain- able to bind the output of an arbitrary as input of another one while keeping the shrink working - biased by default - by default it generates both small and large values, making it easier to dig into counterexamples without having to tweak a size parameter manually
- verbose mode - easier troubleshooting with verbose mode enabled
- replay directly on the minimal counterexample - no need to replay the whole sequence, you get directly the counterexample
For more details, refer to the documentation in the links above.
Issues found by fast-check in famous packages
fast-check has been able to find some unexpected behaviour among famous npm packages. Here are some of the errors detected using fast-check:
js-yaml
Issue detected: enabling !!int: binary style when dumping negative integers produces invalid content [more]
Code example: yaml.dump({toto: -10}, {styles:{'!!int':'binary'}}) produces toto: 0b-1010 not toto: -0b1010
left-pad
Issue detected: unicode characters outside of the BMP plan are not handled consistently [more]
Code example:
leftPad('a\u{1f431}b', 4, 'x') //=> 'a\u{1f431}b' -- in: 3 code points, out: 3 code points
leftPad('abc', 4, '\u{1f431}') //=> '\u{1f431}abc' -- in: 3 code points, out: 4 code pointsquery-string
Issue detected: enabling the bracket setting when exporting arrays containing null values produces an invalid output for the parser [more]
Code example:
m.stringify({bar: ['a', null, 'b']}, {arrayFormat: 'bracket'}) //=> "bar[]=a&bar&bar[]=b"
m.parse('bar[]=a&bar&bar[]=b', {arrayFormat: 'bracket'}) //=> {bar: [null, 'b']}