The qc function

qc(prop, generators...)

This function executes a check of the function prop using generators. It uses the following algorithm:

  1. Set size to 0.
  2. Generate a value for each generator by calling it with size.
  3. Call prop with all generated values and capture the result.
  4. If the result is false, start the shrinking process and then return the failure object.
  5. If the result is undefined, increment size and repeat from step 2 unless undefined has been returned 200 times, in that case return the failure object.
  6. If the result is a string, count how many times this string has been returned and calculate a histogram. Repeat from step 2.
  7. Otherwise repeat from step 2.
  8. When this has been repeated 100 times, return the success object

As you can see, the return values of the prop function determine the behaviour of this method. This allows properties like this:

var prop = function(int) {
  if (int !== 0) {
    return test(int);
  }
};
prop = (int) ->
  unless int is 0
    test(int)
let prop = int => {
  if (int !== 0) {
    return test(int);
  }
};

to work seamlessly. The string return type is useful for debugging tests if you want to see if certain code paths are excersized.

The return objects look like this (both failure and success):

KeyTypeValue
passBooleanfalse if failure, true if success.
examplesArrayThe last set of example values prop was executed with. This is more useful with failure.
minimalExamplesArrayThese are examples that have been shrunk.
messageStringIf failure this will explain why the test failed. If success this will give some statistics on the test as well as a potential histogram of string return types.

qc.forall(generators..., prop)

This is like the qc function, but it ignores the return value of prop completely (i.e. prop will run 100 times regardless of its behaviour unless it throws). This is useful as a control flow construct around which you can use another tools expectations, i.e.

qc.forAll(qc.int, function(i) { 
  expect(i + i).toBe(2 * i);
});
qc.forAll qc.int, (i) -> 
  expect(i + i).toBe(2 * i)
qc.forAll(qc.int, function(i: number) { 
  expect(i + i).toBe(2 * i);
});

Furthermore it collects the return values of the properties and returns them. This can be used with promises:

var promises = qc.forAll(qc.string, function(name) {
  return http.get('/api/' + name);
});

Promise.all(promises).then(function(results) {
  var result = results.every(function(result) {
    return result === 200;
  });
  expect(result).toBe(true);
  done();
}):
promises = qc.forAll qc.string, (name) -> http.get('/api/' + name)

Promise.all(promises).then (results) ->
  result = results.every (result) -> result === 200
  expect(result).toBe(true)
  done()
let promises = qc.forAll(qc.string, (name) => http.get('/api/' + name));

Promise.all(promises).then(function(results) {
  var result = results.every((result) => result === 200);
  expect(result).toBe(true);
  done();
}):