Skip to content

Commit b773f42

Browse files
committed
Revert "Chore: remove doc for test filter"
This reverts commit 1e84710.
1 parent 1e84710 commit b773f42

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

docs/api/config/testFilter.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
---
2+
layout: page-api
3+
title: QUnit.config.testFilter
4+
excerpt: Programmatically filter which tests to run.
5+
groups:
6+
- config
7+
version_added: "3.0.0"
8+
---
9+
10+
Programmatically filter which tests to run.
11+
12+
<table>
13+
<tr>
14+
<th>type</th>
15+
<td markdown="span">`function` or `null`</td>
16+
</tr>
17+
<tr>
18+
<th>default</th>
19+
<td markdown="span">`null`</td>
20+
</tr>
21+
</table>
22+
23+
The `testFilter` property allows you to implement custom logic for filtering which tests to run at runtime. This is useful for advanced scenarios such as:
24+
25+
* Quarantining flaky tests in CI environments
26+
* Distributing tests across parallel workers
27+
* Dynamically skipping tests based on runtime capabilities
28+
* Loading filter criteria from external sources (APIs, files, etc.)
29+
30+
The callback receives a `testInfo` object and must return a boolean:
31+
* Return `true` to run the test
32+
* Return `false` to skip the test
33+
34+
If the callback throws an error, the error is logged as a warning and the test is skipped.
35+
36+
## Filter hierarchy
37+
38+
The `testFilter` callback runs as part of a layered filtering system:
39+
40+
1. **Test-level filters** run first: [`test.only()`](../QUnit/test.only.md), [`test.skip()`](../QUnit/test.skip.md), [`test.if()`](../QUnit/test.if.md)
41+
2. **Programmatic filter** runs next: `QUnit.config.testFilter`
42+
3. **CLI/URL filters** run last: [`--filter`](./filter.md), [`--module`](./module.md), [`--moduleId`](./moduleId.md), [`--testId`](./testId.md)
43+
44+
This layering enables:
45+
* Test authors to control test execution via `test.only()`, `test.skip()`, `test.if()`
46+
* Project maintainers to implement dynamic filtering via `testFilter`
47+
* Developers to manually filter tests via CLI or browser URL parameters
48+
49+
## Parameters
50+
51+
### `testInfo` (object)
52+
53+
| Property | Type | Description |
54+
|----------|------|-------------|
55+
| `testId` | string | Internal hash identifier (used by "Rerun" links)
56+
| `testName` | string | Name of the test
57+
| `module` | string | Name of the parent module
58+
| `skip` | boolean | Whether test was already marked to skip
59+
60+
## See also
61+
62+
* [QUnit.config.filter](./filter.md)
63+
* [QUnit.config.module](./module.md)
64+
* [test.if()](../QUnit/test.if.md)
65+
66+
## Examples
67+
68+
### Quarantine flaky tests
69+
70+
Use an external quarantine list to skip unstable tests in CI without modifying test code.
71+
72+
```js
73+
const quarantineList = ['flaky network test', 'timing-dependent test'];
74+
75+
QUnit.config.testFilter = function (testInfo) {
76+
if (process.env.CI === 'true') {
77+
const isQuarantined = quarantineList.some(function (pattern) {
78+
return testInfo.testName.indexOf(pattern) !== -1;
79+
});
80+
if (isQuarantined) {
81+
console.log('[QUARANTINE] Skipping: ' + testInfo.testName);
82+
return false;
83+
}
84+
}
85+
return true;
86+
};
87+
```
88+
89+
### Parallel test sharding
90+
91+
Distribute tests across multiple workers using deterministic hash-based assignment.
92+
93+
```js
94+
const WORKER_ID = parseInt(process.env.WORKER_ID, 10);
95+
const TOTAL_WORKERS = parseInt(process.env.TOTAL_WORKERS, 10);
96+
97+
QUnit.config.testFilter = function (testInfo) {
98+
let hash = 0;
99+
for (let i = 0; i < testInfo.testId.length; i++) {
100+
const char = testInfo.testId.charCodeAt(i);
101+
hash = ((hash << 5) - hash) + char;
102+
hash = hash & hash;
103+
}
104+
hash = Math.abs(hash);
105+
106+
// Assign test to worker
107+
const assignedWorker = hash % TOTAL_WORKERS;
108+
return assignedWorker === WORKER_ID;
109+
};
110+
```
111+
112+
### Runtime capability detection
113+
114+
Skip tests for features not available in the current environment.
115+
116+
```js
117+
const features = {
118+
webgl: typeof WebGLRenderingContext !== 'undefined',
119+
indexedDB: typeof indexedDB !== 'undefined'
120+
};
121+
122+
QUnit.config.testFilter = function (testInfo) {
123+
// Tests tagged with [feature] in their name
124+
for (const feature in features) {
125+
const tag = '[' + feature + ']';
126+
if (testInfo.testName.indexOf(tag) !== -1 && !features[feature]) {
127+
console.log('[FEATURE] Skipping ' + feature + ' test');
128+
return false;
129+
}
130+
}
131+
return true;
132+
};
133+
134+
QUnit.test('[webgl] 3D rendering', function (assert) {
135+
// Only runs if WebGL is available
136+
assert.ok(true);
137+
});
138+
```
139+
140+
### Combine multiple conditions
141+
142+
```js
143+
const quarantined = ['flaky test'];
144+
145+
QUnit.config.testFilter = function (testInfo) {
146+
// Skip quarantined tests
147+
if (quarantined.some(function (p) { return testInfo.testName.indexOf(p) !== -1; })) {
148+
return false;
149+
}
150+
151+
// Skip slow tests in quick mode
152+
if (process.env.QUICK_RUN && testInfo.testName.indexOf('slow') !== -1) {
153+
return false;
154+
}
155+
156+
// Filter by module if specified
157+
if (process.env.TEST_MODULE && testInfo.module.indexOf(process.env.TEST_MODULE) === -1) {
158+
return false;
159+
}
160+
161+
return true;
162+
};
163+
```

0 commit comments

Comments
 (0)