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
Fast Check
Yet another property based testing framework BUT written in TypeScript
Getting started
Install the module with: npm install fast-check
Usage
Using fast-check with mocha is really straightfoward.
It can be used directly in describe, it blocks with no extra care.
The following snippets written in Javascript shows an example featuring two properties:
const fc = require('fast-check');
// Code under tests
const contains = (text, pattern) => text.indexOf(pattern) >= 0;
// Properties
describe('properties', () => {
it('should always contain itself', () => {
fc.assert(fc.property(fc.string(), text => contains(text, text)));
});
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 tests would raise a red flag and the 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
Property failed after 1 tests (seed: 1515709471288): [,,]
Got error: Property failed by returning falseDocumentation
Properties
fc.property: define a new property ie. a list of arbitraries and a test function to assess the success
The predicate would be considered falsy if its throws or if output == null || output == true evaluate to false.
function property<T1>(
arb1: Arbitrary<T1>,
predicate: (t1:T1) => (boolean|void)): Property<[T1]>;
function property<T1,T2>(
arb1: Arbitrary<T1>, arb2: Arbitrary<T2>,
predicate: (t1:T1,t2:T2) => (boolean|void)): Property<[T1,T2]>;
...Runners
fc.assert: run the property and throws in case of failure
This function is ideal to be called in describe, it blocks.
It does not return anything in case of success.
It can be parametrized using its second argument.
export interface Parameters {
seed?: number; // optional, initial seed of the generator: Date.now() by default
num_runs?: number; // optional, number of runs before success: 100 by default
logger?: (v: string) => void; // optional, log output: console.log by default
}function assert<Ts>(property: IProperty<Ts>, params?: Parameters);fc.check: run the property and return an object containing the test status along with other useful details
It should never throw whatever the status of the test.
It can be parametrized with the same parameters than fc.assert.
The details returned by fc.check are the following:
interface Details {
boolean: failed: false, // false in case of failure, true otherwise
number: num_runs, // number of runs (all runs if success, up and including the first failure if failed)
number: num_shrinks, // number of shrinks (depth required to get the minimal failing example)
number: seed, // seed used for the test
Ts?: counterexample, // failure only: shrunk conterexample causig the property to fail
string?: error // failure only: stack trace and error details
}function check<Ts>(property: IProperty<Ts>, params?: Parameters);fc.sample: sample generated values of anArbitrary<T>orProperty<T>
It builds an array containing all the values that would have been generated for the equivalent test.
It also accept Parameters as configuration in order to help you diagnose the shape of the inputs that will be received by your property.
function sample<Ts>(generator: Arbitrary<Ts>): Ts[];
function sample<Ts>(generator: Arbitrary<Ts>, params: Parameters): Ts[];
function sample<Ts>(generator: Arbitrary<Ts>, num_generated: number): Ts[];
function sample<Ts>(generator: IProperty<Ts>): Ts[];
function sample<Ts>(generator: IProperty<Ts>, params: Parameters): Ts[];
function sample<Ts>(generator: IProperty<Ts>, num_generated: number): Ts[];fc.statistics: classify the values produced by anArbitrary<T>orProperty<T>
It provides useful statistics concerning generated values. In order to be able to gather those statistics it has to be provided with a classifier function that can classify the generated value in zero, one or more categories (free labels).
It also accept Parameters as configuration in order to help you diagnose the shape of the inputs that will be received by your property.
Statistics are dumped into console.log but can be redirected to another source by modifying the logger key in Parameters.
function statistics<Ts>(generator: Arbitrary<Ts>, classify: (v: Ts) => string): void;
function statistics<Ts>(generator: Arbitrary<Ts>, classify: (v: Ts) => string, params: Parameters): void;
function statistics<Ts>(generator: Arbitrary<Ts>, classify: (v: Ts) => string, num_generated: number): void;
function statistics<Ts>(generator: Arbitrary<Ts>, classify: (v: Ts) => string[]): void;
function statistics<Ts>(generator: Arbitrary<Ts>, classify: (v: Ts) => string[], params: Parameters): void;
function statistics<Ts>(generator: Arbitrary<Ts>, classify: (v: Ts) => string[], num_generated: number): void;
function statistics<Ts>(generator: IProperty<Ts>, classify: (v: Ts) => string): void;
function statistics<Ts>(generator: IProperty<Ts>, classify: (v: Ts) => string, params: Parameters): void;
function statistics<Ts>(generator: IProperty<Ts>, classify: (v: Ts) => string, num_generated: number): void;
function statistics<Ts>(generator: IProperty<Ts>, classify: (v: Ts) => string[]): void;
function statistics<Ts>(generator: IProperty<Ts>, classify: (v: Ts) => string[], params: Parameters): void;
function statistics<Ts>(generator: IProperty<Ts>, classify: (v: Ts) => string[], num_generated: number): void;Arbitraries
Arbitraries are responsible for the random generation (but deterministic) and shrink of datatypes. They can be combined together to build more complex datatypes.
Boolean (:boolean)
fc.boolean()eithertrueorfalse
Numeric (:number)
Integer values:
fc.integer()all possible integers ie. from -2147483648 (included) to 2147483647 (included)fc.integer(max: number)all possible integers between -2147483648 (included) and max (included)fc.integer(min: number, max: number)all possible integers between min (included) and max (included)fc.nat()all possible positive integers ie. from 0 (included) to 2147483647 (included)fc.nat(max: number)all possible positive integers between 0 (included) and max (included)
Floating point numbers:
fc.float()uniformly distributedfloatvalue between 0.0 (included) and 1.0 (excluded)fc.double()uniformly distributeddoublevalue between 0.0 (included) and 1.0 (excluded)
String (:string)
Single character only:
fc.hexa()one character in0123456789abcdef(lower case)fc.base64()one character inA-Z,a-z,0-9,+or/fc.char()between 0x20 (included) and 0x7e (included) , corresponding to printable characters (see https://www.ascii-code.com/)fc.ascii()between 0x00 (included) and 0x7f (included)fc.unicode()between 0x0000 (included) and 0xffff (included)
Multiple characters:
fc.hexaString()orfc.hexaString(maxLength: number)string based on characters generated byfc.hexa()fc.base64String()orfc.base64String(maxLength: number)string based on characters generated byfc.base64(). Provide valid base 64 strings: length always multiple of 4 padded with '=' charactersfc.string()orfc.string(maxLength: number)string based on characters generated byfc.char()fc.asciiString()orfc.asciiString(maxLength: number)string based on characters generated byfc.ascii()fc.unicodeString()orfc.unicodeString(maxLength: number)string based on characters generated byfc.unicode()
Strings that mimic real strings, with words and sentences:
fc.lorem(),fc.lorem(maxWordsCount: number)orfc.lorem(maxWordsCount: number, sentencesMode: boolean)lorem ipsum strings. Generator can be configured by giving it a maximum number of characters by usingmaxWordsCountor switching the mode to sentences by settingsentencesModetotruein which casemaxWordsCountis used to cap the number of sentences allowed. This arbitrary is not shrinkable
Combinors of arbitraries (:T)
fc.constant<T>(value: T): Arbitrary<T>constant arbitrary only able to producevalue: Tfc.oneof<T>(...arbs: Arbitrary<T>[]): Arbitrary<T>randomly chooses an arbitrary at each new generation. Should be provided with at least one arbitrary. All arbitraries are equally probable and shrink is still working for the selected arbitraryfc.option<T>(arb: Arbitrary<T>): Arbitrary<T | null>orfc.option<T>(arb: Arbitrary<T>, freq: number): Arbitrary<T | null>arbitrary able to nullify its generated value. When provided a customfreqvalue it changes the frequency ofnullvalues so that they occur one time overfreqtries (eg.:freq=5means that 20% of generated values will benulland 80% would be produced througharb). By default:freq=5fc.array<T>(arb: Arbitrary<T>): Arbitrary<T[]>orfc.array<T>(arb: Arbitrary<T>, maxLength: number): Arbitrary<T[]>array of random length containing values generated byarb. By setting the parametermaxLength, the user can change the maximal size allowed for the generated array. By default:maxLength=10fc.tuple<T1,T2,...>(arb1: Arbitrary<T1>, arb2: Arbitrary<T2>, ...): Arbitrary<[T1,T2,...]>tuple generated by aggregating the values ofarbXlikegenerate: () => [arb1.generate(), arb2.generate(), ...]. This arbitrary perfectly handle shrinks and is able to shink on all the generators