From 953f7da774e419e4ad076681a6bf2b077adfef71 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Sun, 26 May 2024 16:28:43 +0100 Subject: [PATCH] Core: Deprecate unset timeout for tests taking longer than 3 seconds Up until now, QUnit has not defined or enforced any default timeout. This means if your test timed out or got stuck, this would be silent and could (depending on how you run/integrate your tests) be hard to find the cause of, and might take a long time to even detect as it would be subject to a higher-level timeout (e.g. some kind of maximum process time or CI limit). In QUnit 3.0, the default timeout will change from undefined (effectively Infinity) to 3 seconds. This only effects you if you * do not have `QUnit.config.testTimeout` set, * and, have one or more tests exceeding 3 seconds, * and, are not calling `assert.timeout()` inside this test. Starting in QUnit 2.21, a deprecation warning will be logged, at most once per test run, if you have no timeout defined, and a test takes longer than 3 seconds. You can prepare yourself for QUnit 3 when this happens by calling `assert.timeout()` inside those tests, or by setting `QUnit.config.testTimeout` globally with a higher timeout as-needed. --- src/assert.js | 2 +- src/core.js | 2 +- src/core/config.js | 1 + src/test.js | 12 +++++++++++ test/cli/cli-main.js | 1 + .../fixtures/config-testTimeout-deprecated.js | 20 +++++++++++++++++++ .../config-testTimeout-deprecated.tap.txt | 14 +++++++++++++ 7 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/cli/fixtures/config-testTimeout-deprecated.js create mode 100644 test/cli/fixtures/config-testTimeout-deprecated.tap.txt diff --git a/src/assert.js b/src/assert.js index 25c541eb3..94cc8e7f7 100644 --- a/src/assert.js +++ b/src/assert.js @@ -81,7 +81,7 @@ class Assert { // Alias of pushResult. push (result, actual, expected, message, negative) { Logger.warn('assert.push is deprecated and will be removed in QUnit 3.0.' + - ' Please use assert.pushResult instead (https://qunitjs.com/api/assert/pushResult).'); + ' Please use assert.pushResult instead. https://qunitjs.com/api/assert/pushResult'); const currentAssert = this instanceof Assert ? this : config.current.assert; return currentAssert.pushResult({ diff --git a/src/core.js b/src/core.js index 3c9404122..8bf783b05 100644 --- a/src/core.js +++ b/src/core.js @@ -124,7 +124,7 @@ extend(QUnit, { load: function () { Logger.warn('QUnit.load is deprecated and will be removed in QUnit 3.0.' + - ' Refer to .'); + ' https://qunitjs.com/api/QUnit/load/'); QUnit.autostart(); }, diff --git a/src/core/config.js b/src/core/config.js index 0387d69bd..4e34207a2 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -127,6 +127,7 @@ const config = { // started: 0, // Internal state + _deprecated_timeout_shown: false, blocking: true, callbacks: {}, modules: [], diff --git a/src/test.js b/src/test.js index 880cd7fde..11ca4385e 100644 --- a/src/test.js +++ b/src/test.js @@ -759,6 +759,18 @@ Test.prototype = { config.timeoutHandler(timeoutDuration), timeoutDuration ); + } else { + clearTimeout(config.timeout); + config.timeout = setTimeout( + function () { + config.timeout = null; + if (!config._deprecated_timeout_shown) { + config._deprecated_timeout_shown = true; + Logger.warn(`Test "${test.testName}" took longer 3000ms, but no timeout was set. Set QUnit.config.testTimeout or call assert.timeout() to avoid a timeout in QUnit 3. https://qunitjs.com/api/config/testTimeout/`); + } + }, + 3000 + ); } } diff --git a/test/cli/cli-main.js b/test/cli/cli-main.js index 314d58384..4e919002f 100644 --- a/test/cli/cli-main.js +++ b/test/cli/cli-main.js @@ -16,6 +16,7 @@ QUnit.module('CLI Main', () => { // and only await/assert the already-started command. concurrentMapKeys(readFixtures(FIXTURES_DIR), 0, (runFixture) => runFixture()), async (assert, fixture) => { + assert.timeout(10000); const result = await fixture; assert.equal(result.snapshot, result.expected, result.name); } diff --git a/test/cli/fixtures/config-testTimeout-deprecated.js b/test/cli/fixtures/config-testTimeout-deprecated.js new file mode 100644 index 000000000..ab200bfc3 --- /dev/null +++ b/test/cli/fixtures/config-testTimeout-deprecated.js @@ -0,0 +1,20 @@ +QUnit.test('fast async', function (assert) { + var done = assert.async(); + assert.true(true); + setTimeout(done, 7); +}); + +QUnit.test('slow async 1', function (assert) { + var done = assert.async(); + assert.true(true); + setTimeout(done, 3500); +}); + +QUnit.test('slow async 2', function (assert) { + var done = assert.async(); + assert.true(true); + setTimeout(done, 3500); +}); + + + diff --git a/test/cli/fixtures/config-testTimeout-deprecated.tap.txt b/test/cli/fixtures/config-testTimeout-deprecated.tap.txt new file mode 100644 index 000000000..76646cd82 --- /dev/null +++ b/test/cli/fixtures/config-testTimeout-deprecated.tap.txt @@ -0,0 +1,14 @@ +# command: ["qunit", "config-testTimeout-deprecated.js"] + +TAP version 13 +ok 1 fast async +ok 2 slow async 1 +ok 3 slow async 2 +1..3 +# pass 3 +# skip 0 +# todo 0 +# fail 0 + +# stderr +Test "slow async 1" took longer 3000ms, but no timeout was set. Set QUnit.config.testTimeout or call assert.timeout() to avoid a timeout in QUnit 3. https://qunitjs.com/api/config/testTimeout/