Skip to content

Commit 86a9b27

Browse files
kltanKean Tan
authored and
Kean Tan
committed
Core: Create config.testIds to expose all available test ids
What this does Currently each testId is calculated as each test is executed. Config.testIds pre-hashes all the loaded tests on demand and returns all testIds. How is this helpful Currently test runners can get access to test modules via config.modules and partition the modules based on some distribution strategy for running the tests in parallel. This is fine but it can lead to unbalanced distribution as some modules have a lot of tests and some modules are testing integration (longer running) test instead of unit test. Partitioning the tests by modules caused some instance of test runners to run way longer than others as some heavier running modules might be clumped together in the same instance. To mitigate and minimize the unbalanced test runs, the proposed solution is to partition based on each individual test with testId. The test runners can now access testIds beforehand and can distribute those ids with the testId url param. This will minimize the test execution time descrepencies between each individual instance of the test runners.
1 parent e678729 commit 86a9b27

9 files changed

+74
-12
lines changed

Gruntfile.js

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ module.exports = function( grunt ) {
165165
"test/reporter-html/xhtml-single-testid.xhtml",
166166
"test/reporter-urlparams.html",
167167
"test/moduleId.html",
168+
"test/testIds.html",
168169
"test/onerror/inside-test.html",
169170
"test/onerror/outside-test.html",
170171
"test/only.html",

docs/config/QUnit.config.md

+4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ Enabling this option will cause tests to fail, if they don't call `expect()` at
101101

102102
This property allows QUnit to run specific tests identified by the hashed version of their module name and test name. You can specify one or multiple tests to run.
103103

104+
### `QUnit.config.testIds` (array) | default: `array`
105+
106+
This property allows QUnit to return all hashed testIds of all loaded tests.
107+
104108
### `QUnit.config.testTimeout` (number) | default: `undefined`
105109

106110
Specify a global timeout in milliseconds after which all tests will fail with an appropriate message. Useful when async tests aren't finishing, to prevent the testrunner getting stuck. Set to something high, e.g. 30000 (30 seconds) to avoid slow tests to time out by accident.

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "qunit",
33
"title": "QUnit",
44
"description": "An easy-to-use JavaScript Unit Testing framework.",
5-
"version": "2.9.4-pre",
5+
"version": "2.9.3-pre",
66
"homepage": "https://qunitjs.com",
77
"author": {
88
"name": "jQuery Foundation and other contributors",

src/core/config.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { window, localSessionStorage } from "../globals";
2-
import { extend } from "./utilities";
2+
import { extend, generateHash, uniqueTestName } from "./utilities";
33

44
/**
55
* Config object: Maintain internal state
@@ -58,7 +58,27 @@ const config = {
5858
callbacks: {},
5959

6060
// The storage module to use for reordering tests
61-
storage: localSessionStorage
61+
storage: localSessionStorage,
62+
63+
// Get the testIds for all tests
64+
// Simulates how test.js generates testIds by iteratively
65+
// pushing testNames to get uniqueTestName
66+
get testIds() {
67+
var i, j, ml, tl, testIds = [], testNames, testName;
68+
69+
// Loop through all modules and tests and generate testIds
70+
for ( i = 0, ml = config.modules.length; i < ml; i++ ) {
71+
testNames = [];
72+
for ( j = 0, tl = config.modules[ i ].tests.length; j < tl; j++ ) {
73+
testName = uniqueTestName( testNames,
74+
config.modules[ i ].tests[ j ].name );
75+
testIds.push( generateHash( config.modules[ i ].name, testName ) );
76+
testNames.push( testName );
77+
}
78+
}
79+
return testIds;
80+
}
81+
6282
};
6383

6484
// take a predefined QUnit.config and extend the defaults

src/core/utilities.js

+11
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,14 @@ export function generateHash( module, testName ) {
157157

158158
return hex.slice( -8 );
159159
}
160+
161+
// Append whitespace to duplicated seen test name
162+
export function uniqueTestName( testNames, testName ) {
163+
var i, l;
164+
for ( i = 0, l = testNames; i < l.length; i++ ) {
165+
if ( testNames[ i ] === testName ) {
166+
testName += " ";
167+
}
168+
}
169+
return testName;
170+
}

src/test.js

+11-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
hasOwn,
1616
inArray,
1717
now,
18-
objectType
18+
objectType,
19+
uniqueTestName
1920
} from "./core/utilities";
2021
import { runLoggingCallbacks } from "./core/logging";
2122
import { extractStacktrace, sourceFromStacktrace } from "./core/stacktrace";
@@ -26,7 +27,7 @@ import TestReport from "./reports/test";
2627
let focused = false;
2728

2829
export default function Test( settings ) {
29-
var i, l;
30+
var testNames;
3031

3132
++Test.count;
3233

@@ -62,12 +63,14 @@ export default function Test( settings ) {
6263
valid: this.valid()
6364
} );
6465

65-
// Register unique strings
66-
for ( i = 0, l = this.module.tests; i < l.length; i++ ) {
67-
if ( this.module.tests[ i ].name === this.testName ) {
68-
this.testName += " ";
69-
}
70-
}
66+
// Register unique string for each test inside a module
67+
//
68+
// Note: this is the authorative way of generating testId
69+
// testIds are generated one at a time when individual test is being run
70+
// config.testIds also simulates the process here by pushing the tests
71+
// one at a time to match the uniqueTestName generation here
72+
testNames = this.module.tests.map( test => test.name );
73+
this.testName = uniqueTestName( testNames, this.testName );
7174

7275
this.testId = generateHash( this.module.name, this.testName );
7376

test/testIds.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>QUnit ModuleId Test Suite</title>
6+
<link rel="stylesheet" href="../dist/qunit.css">
7+
<script src="../dist/qunit.js"></script>
8+
<script src="testIds.js"></script>
9+
</head>
10+
<body>
11+
<div id="qunit"></div>
12+
</body>
13+
</html>

test/testIds.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
QUnit.module( "QUnit.config.testIds" );
2+
3+
QUnit.test( "testIds should return all testIds", function( assert ) {
4+
assert.deepEqual( QUnit.config.testIds, [ "01e80961", "3b1922df" ], "this is the test with id 01e80961" );
5+
} );
6+
7+
// This test is to prove identical test name is being hashed differently
8+
QUnit.test( "testIds should return all testIds", function( assert ) {
9+
assert.deepEqual( QUnit.config.testIds, [ "01e80961", "3b1922df" ], "this is the test with id 3b1922df" );
10+
} );

0 commit comments

Comments
 (0)