Skip to content

Commit

Permalink
E2E shrink of commands along other arbitraries
Browse files Browse the repository at this point in the history
Related to #254
  • Loading branch information
dubzzz committed Dec 15, 2018
1 parent 0d66edf commit cc6ecf3
Showing 1 changed file with 54 additions and 1 deletion.
55 changes: 54 additions & 1 deletion test/e2e/model/CommandsArbitrary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,29 @@ class SuccessAlwaysCommand implements fc.Command<M1, R1> {
toString = () => 'success';
}

type M2 = {
current: { stepId: number };
validSteps: number[];
};
type R2 = {};

class SuccessCommand implements fc.Command<M2, R2> {
check = (m: Readonly<M2>) => m.validSteps.includes(m.current.stepId++);
run = (m: M2, r: R2) => {};
toString = () => 'success';
}
class FailureCommand implements fc.Command<M2, R2> {
check = (m: Readonly<M2>) => m.validSteps.includes(m.current.stepId++);
run = (m: M2, r: R2) => {
throw 'failure';
};
toString = () => 'failure';
}

const seed = Date.now();
describe(`CommandsArbitrary (seed: ${seed})`, () => {
describe('commands', () => {
it('Should print only the commands corresponding to the failure', () => {
it('Should shrink up sto the shortest failing commands list', () => {
const out = fc.check(
fc.property(
fc.commands(
Expand Down Expand Up @@ -90,5 +109,39 @@ describe(`CommandsArbitrary (seed: ${seed})`, () => {
assert.ok(out.failed, 'Should have failed');
assert.equal([...out.counterexample![0]].length, 0);
});
it('Should shrink towards minimal case even with other arbitraries', () => {
// Why this test?
//
// fc.commands is one of the rare Arbitrary relying on an internal state.
// By generating commands along with other arbitraries, we could highlight states issues.
// Basically shrinking will re-use the generated commands multiple times along with a shrunk array.
//
// First version was failing on this test with the following output:
// Expected the only played command to be 'failure', got: -,success,failure for steps 2
// The output for 'steps 2' should have been '-,-,failure'
const out = fc.check(
fc.property(
fc.array(fc.nat(9), 0, 3),
fc.commands([fc.constant(new FailureCommand()), fc.constant(new SuccessCommand())]),
fc.array(fc.nat(9), 0, 3),
(validSteps1, cmds, validSteps2) => {
const setup = () => ({
model: { current: { stepId: 0 }, validSteps: [...validSteps1, ...validSteps2] },
real: {}
});
fc.modelRun(setup, cmds);
}
),
{ seed: seed }
);
assert.ok(out.failed, 'Should have failed');
const cmdsRepr = out.counterexample![1].toString();
const validSteps = [...out.counterexample![0], ...out.counterexample![2]];
assert.equal(
cmdsRepr,
'failure',
`Expected the only played command to be 'failure', got: ${cmdsRepr} for steps ${validSteps.sort().join(',')}`
);
});
});
});

0 comments on commit cc6ecf3

Please sign in to comment.