Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Add --seed=true to generate a new seed #1800

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions bin/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ program
collect,
[]
)
.option('--seed [value]',
'specify a seed to re-order your tests; '
+ 'if specified without a value, a seed will be generated'
.option('--seed <value>',
'specify a seed to enable randomized ordering of tests.\n'
+ 'set to "true" to generate a new seed.'
)
.option('-w, --watch', 'watch files for changes and re-run the test suite')
.parse(process.argv);
Expand Down
2 changes: 1 addition & 1 deletion docs/api/config/seed.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The provided string will be used as the seed in a pseudo-random number generator

Randomly ordering your tests can help identify non-atomic tests which either depend on a previous test or are leaking state to subsequent tests.

If `seed` is boolean true (or set as URL query parameter without a value), then QUnit will generate on-demand a new random value to use as seed. You can then read the seed at runtime from the configuration value, and use it to reproduce the same test sequence later.
If `seed` is boolean true (or set as URL query parameter without a value), then QUnit will generate on-demand a new random value to use as seed. You can then read the seed from `QUnit.config.seed` at runtime, and use it to reproduce the same test sequence later.

## See also

Expand Down
22 changes: 8 additions & 14 deletions src/cli/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,20 @@ async function run (args, options) {

const files = utils.getFilesFromArgs(args);

// Replace any previous instance, e.g. in watch mode
QUnit = globalThis.QUnit = requireQUnit();

if (options.filter) {
QUnit.config.filter = options.filter;
globalThis.qunit_config_filter = options.filter;
}

if (options.module) {
QUnit.config.module = options.module;
globalThis.qunit_config_module = options.module;
}
if (options.seed) {
globalThis.qunit_config_seed = options.seed;
}

const seed = options.seed;
if (seed) {
if (seed === true) {
// Length may vary from 6-14, pad to 10
QUnit.config.seed = Math.random().toString(36).slice(2).padEnd(10, '0');
} else {
QUnit.config.seed = seed;
}
// Replace any previous instance, e.g. in watch mode
QUnit = globalThis.QUnit = requireQUnit();

if (QUnit.config.seed) {
console.log(`Running tests with seed: ${QUnit.config.seed}`);
}

Expand Down
21 changes: 14 additions & 7 deletions src/core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ function readFlatPreconfigString (val, dest) {
}
}

function readFlatPreconfigStringOrBoolean (val, dest) {
if (typeof val === 'boolean' || (typeof val === 'string' && val !== '')) {
config[dest] = val;
}
}

function readFlatPreconfigStringArray (val, dest) {
if (typeof val === 'string' && val !== '') {
config[dest] = [val];
Expand All @@ -190,7 +196,7 @@ function readFlatPreconfig (obj) {
readFlatPreconfigBoolean(obj.qunit_config_reorder, 'reorder');
readFlatPreconfigBoolean(obj.qunit_config_requireexpects, 'requireExpects');
readFlatPreconfigBoolean(obj.qunit_config_scrolltop, 'scrolltop');
readFlatPreconfigString(obj.qunit_config_seed, 'seed');
readFlatPreconfigStringOrBoolean(obj.qunit_config_seed, 'seed');
readFlatPreconfigStringArray(obj.qunit_config_testid, 'testId');
readFlatPreconfigNumber(obj.qunit_config_testtimeout, 'testTimeout');

Expand Down Expand Up @@ -238,12 +244,13 @@ if (urlParams.testId) {
readFlatPreconfigBoolean(urlParams.hidepassed, 'hidepassed');
readFlatPreconfigBoolean(urlParams.noglobals, 'noglobals');
readFlatPreconfigBoolean(urlParams.notrycatch, 'notrycatch');
if (urlParams.seed === true) {
// Generate a random seed if the option is specified without a value
readFlatPreconfigStringOrBoolean(urlParams.seed, 'seed');

if (config.seed === 'true' || config.seed === true) {
// Generate a random seed
// Length of `Math.random()` fraction, in base 36, may vary from 6-14.
// Pad and take slice to a consistent 10-digit value.
// TODO: Present this in HtmlReporter
config.seed = Math.random().toString(36).slice(2);
} else {
readFlatPreconfigString(urlParams.seed, 'seed');
config.seed = (Math.random().toString(36) + '0000000000').slice(2, 12);
}

export default config;
8 changes: 4 additions & 4 deletions test/cli/cli-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ QUnit.module('CLI Main', () => {
qunit_config_notrycatch: 'false'
}
});
assert.equal(execution.snapshot, `TAP version 13
assert.equal(execution.snapshot, `Running tests with seed: dummyfirstyes
TAP version 13
ok 1 dummy
not ok 2 slow
---
Expand Down Expand Up @@ -213,9 +214,8 @@ Bail out! Error: No tests matched the filter "no matches".
# exit code: 1`);
});

QUnit.test('--seed generates new random seed', async assert => {
// https://github.com/qunitjs/qunit/issues/1691
const command = ['qunit', '--seed', '--', 'basic-one.js', 'test/'];
QUnit.test('--seed=true generates new random seed', async assert => {
const command = ['qunit', '--seed', 'true', 'basic-one.js', 'test/'];
const execution = await execute(command);

const actualHarness = execution.snapshot
Expand Down