Skip to content

Commit

Permalink
Report the configuration, that has been used, in RunDetails (#623)
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz authored Jun 11, 2020
1 parent e5bff9c commit 078e111
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 9 deletions.
5 changes: 5 additions & 0 deletions documentation/1-Guides/Runners.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ The details returned by `fc.check` are the following:
```typescript
interface RunDetails<Ts> {
failed: boolean; // true in case of failure or too many skips, false otherwise
interrupted: boolean; // true in case of interrupted run, false otherwise
numRuns: number; // number of runs (all runs if success, up and including the first failure if failed)
numSkips: number; // number of skipped entries due to failed pre-condition (before the first failure)
numShrinks: number; // number of shrinks (depth required to get the minimal failing example)
Expand All @@ -142,6 +143,10 @@ interface RunDetails<Ts> {
// this value as to be set as path attribute in the Parameters (with the seed)
// of assert, check, sample or even statistics
error: string|null; // failure only: stack trace and error details
failures: Ts[]; // verbose>=1 only: failures that have occurred during the run
executionSummary: ExecutionTree<Ts>[]; // verbose>=1 only: traces the origin of each value
// encountered during the test and its status
runConfiguration: Parameters<Ts>; // configuration of the run, it includes local and global paramaters
}
```

Expand Down
5 changes: 3 additions & 2 deletions src/check/runner/Runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,14 @@ function check<Ts>(rawProperty: IRawProperty<Ts>, params?: Parameters<Ts>) {
const sourceValues = new SourceValuesIterator(initialValues, maxInitialIterations, maxSkips);
return property.isAsync()
? asyncRunIt(property, sourceValues, qParams.verbose, qParams.markInterruptAsFailure).then((e) =>
e.toRunDetails(qParams.seed, qParams.path, qParams.numRuns, maxSkips)
e.toRunDetails(qParams.seed, qParams.path, qParams.numRuns, maxSkips, qParams)
)
: runIt(property, sourceValues, qParams.verbose, qParams.markInterruptAsFailure).toRunDetails(
qParams.seed,
qParams.path,
qParams.numRuns,
maxSkips
maxSkips,
qParams
);
}

Expand Down
20 changes: 20 additions & 0 deletions src/check/runner/configuration/QualifiedParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ export class QualifiedParameters<T> {
this.endOnFailure = QualifiedParameters.readBoolean(p, 'endOnFailure');
}

toParameters(): Parameters<T> {
const orUndefined = <V>(value: V | null) => (value !== null ? value : undefined);
return {
seed: this.seed,
randomType: this.randomType,
numRuns: this.numRuns,
maxSkipsPerRun: this.maxSkipsPerRun,
timeout: orUndefined(this.timeout),
skipAllAfterTimeLimit: orUndefined(this.skipAllAfterTimeLimit),
interruptAfterTimeLimit: orUndefined(this.interruptAfterTimeLimit),
markInterruptAsFailure: this.markInterruptAsFailure,
path: this.path,
logger: this.logger,
unbiased: this.unbiased,
verbose: this.verbose,
examples: this.examples,
endOnFailure: this.endOnFailure,
};
}

private static readSeed = <T>(p: Parameters<T>): number => {
// No seed specified
if (p.seed == null) return Date.now() ^ (Math.random() * 0x100000000);
Expand Down
8 changes: 8 additions & 0 deletions src/check/runner/reporter/RunDetails.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { VerbosityLevel } from '../configuration/VerbosityLevel';
import { ExecutionTree } from './ExecutionTree';
import { Parameters } from '../configuration/Parameters';

/**
* Post-run details produced by {@link check}
Expand Down Expand Up @@ -129,4 +130,11 @@ interface RunDetailsWithDoc<Ts> {
* Verbosity level required by the user
*/
verbose: VerbosityLevel;
/**
* Configuration of the run
*
* It includes both local parameters set on `fc.assert` or `fc.check`
* and global ones specified using `fc.configureGlobal`
*/
runConfiguration: Parameters<Ts>;
}
11 changes: 10 additions & 1 deletion src/check/runner/reporter/RunExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { VerbosityLevel } from '../configuration/VerbosityLevel';
import { ExecutionStatus } from './ExecutionStatus';
import { ExecutionTree } from './ExecutionTree';
import { RunDetails } from './RunDetails';
import { QualifiedParameters } from '../configuration/QualifiedParameters';

/**
* @hidden
Expand Down Expand Up @@ -91,7 +92,13 @@ export class RunExecution<Ts> {
return [...offsetItems.slice(0, offsetItems.length - 1), `${middle}`, ...remainingItems.slice(1)].join(':');
};

toRunDetails(seed: number, basePath: string, numRuns: number, maxSkips: number): RunDetails<Ts> {
toRunDetails(
seed: number,
basePath: string,
numRuns: number,
maxSkips: number,
qParams: QualifiedParameters<Ts>
): RunDetails<Ts> {
if (!this.isSuccess()) {
// encountered a property failure
return {
Expand All @@ -114,6 +121,7 @@ export class RunExecution<Ts> {
failures: this.extractFailures(),
executionSummary: this.rootExecutionTrees,
verbose: this.verbosity,
runConfiguration: qParams.toParameters(),
};
}

Expand Down Expand Up @@ -144,6 +152,7 @@ export class RunExecution<Ts> {
failures: [],
executionSummary: this.rootExecutionTrees,
verbose: this.verbosity,
runConfiguration: qParams.toParameters(),
};
}
}
21 changes: 15 additions & 6 deletions test/unit/check/runner/reporter/RunExecution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as fc from '../../../../../lib/fast-check';
import { RunExecution } from '../../../../../src/check/runner/reporter/RunExecution';
import { VerbosityLevel } from '../../../../../src/check/runner/configuration/VerbosityLevel';
import { ExecutionStatus } from '../../../../../src/fast-check';
import { QualifiedParameters } from '../../../../../src/check/runner/configuration/QualifiedParameters';

describe('RunExecution', () => {
it('Should expose data coming from the last failure', () =>
Expand Down Expand Up @@ -30,7 +31,7 @@ describe('RunExecution', () => {
}
// Assert the value
const lastFailure = failuresDesc[failuresDesc.length - 1];
const details = run.toRunDetails(seed, '', 42, 10000);
const details = run.toRunDetails(seed, '', 42, 10000, QualifiedParameters.read({}));
expect(details.failed).toBe(true);
expect(details.interrupted).toBe(false);
expect(details.counterexamplePath).not.toBe(null);
Expand Down Expand Up @@ -64,7 +65,9 @@ describe('RunExecution', () => {
run.fail(42, failureId, 'Failed');
}
// Assert the value
expect(run.toRunDetails(seed, '', 42, 10000).counterexamplePath).toEqual(path.join(':'));
expect(run.toRunDetails(seed, '', 42, 10000, QualifiedParameters.read({})).counterexamplePath).toEqual(
path.join(':')
);
})
));
it('Should generate correct counterexamplePath given initial offset', () =>
Expand All @@ -86,9 +89,9 @@ describe('RunExecution', () => {
const joinedPath = [...offsetPath, ...addedPath.slice(1)];
joinedPath[offsetPath.length - 1] += addedPath[0];
// Assert the value
expect(run.toRunDetails(seed, offsetPath.join(':'), 42, 10000).counterexamplePath).toEqual(
joinedPath.join(':')
);
expect(
run.toRunDetails(seed, offsetPath.join(':'), 42, 10000, QualifiedParameters.read({})).counterexamplePath
).toEqual(joinedPath.join(':'));
}
)
));
Expand Down Expand Up @@ -119,7 +122,13 @@ describe('RunExecution', () => {
break;
}
}
const details = run.toRunDetails(0, '', executionStatuses.length + 1, executionStatuses.length + 1);
const details = run.toRunDetails(
0,
'',
executionStatuses.length + 1,
executionStatuses.length + 1,
QualifiedParameters.read({})
);
let currentExecutionTrees = details.executionSummary;
for (let idx = 0, idxInTrees = 0; idx !== executionStatuses.length; ++idx, ++idxInTrees) {
// Ordered like execution: same value and status
Expand Down

0 comments on commit 078e111

Please sign in to comment.