@t09tanaka/test-gates 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +4 -2
- package/dist/stryker.cjs +4 -4
- package/dist/stryker.d.cts +7 -5
- package/dist/stryker.d.ts +7 -5
- package/dist/stryker.js +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.2
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `createStrykerGatesConfig` sets Stryker's `maxTestRunnerReuse` to 50 unless the project passes its own (Stryker's default is 0: one test runner process for the whole run). In a project with mutants that never end, the runner became about three times slower from the first of them on, and mutants that are killed in seconds on their own timed out. Starting a new process every 50 mutants kept the speed: a full run of 781 mutants went from 14 to 18 minutes with stray timeouts to under 7 minutes with none.
|
|
8
|
+
- `timeoutMS` is no longer set by the helper; Stryker's default (5000) applies again. The 30000 of 0.3.1 was the wrong fix. It rested on the idea that a restarted runner makes the next mutant slow, when in fact a runner that is not restarted stays slow. With 30000 the same full run took 47 minutes and still failed, and mutants that exhaust the heap crashed the runner and were reported as `RuntimeError` instead of `Timeout`.
|
|
9
|
+
|
|
10
|
+
A project that set `timeoutMS` itself to work around stray timeouts can remove it.
|
|
11
|
+
|
|
3
12
|
## 0.3.1
|
|
4
13
|
|
|
5
14
|
### Changed
|
package/README.md
CHANGED
|
@@ -280,7 +280,9 @@ How an `expectedTimeouts` entry is judged:
|
|
|
280
280
|
|
|
281
281
|
When the run fails on a timeout, first run again with less load (`npm run test:gates:mutation -- --concurrency 1`). Add an entry only for a mutant that can never finish.
|
|
282
282
|
|
|
283
|
-
`createStrykerGatesConfig` sets Stryker's `
|
|
283
|
+
`createStrykerGatesConfig` sets Stryker's `maxTestRunnerReuse` to 50 (since 0.3.2; Stryker's own default is 0, one test runner process for the whole run). A mutant that would be killed can also time out for a reason that has nothing to do with the mutant: in a Jest project with three mutants that never end, the test runner handled about a third as many mutants per minute from the first of them on, for the rest of the run. Mutants that are killed in seconds on their own then timed out, a different set on each full run, and the run took 14 to 18 minutes. With a new process every 50 mutants the speed stayed the same to the end, nothing timed out that should not, and the run took under 7 minutes. Why the runner slows down was not found; the restart only cuts it short. Pass `maxTestRunnerReuse` to the helper to change it.
|
|
284
|
+
|
|
285
|
+
0.3.1 set `timeoutMS` to 30000 instead. That was the wrong fix and 0.3.2 takes it back: the longer limit let most slow mutants finish, but the run above took 47 minutes, and in another project mutants that exhaust the heap crashed the test runner before the limit and came back as `RuntimeError`, which is only counted, not failed. `timeoutMS` is Stryker's default (5000) again unless the project sets it.
|
|
284
286
|
|
|
285
287
|
### `test-gates selfcheck [--all | --first] [-- <gate command>]`
|
|
286
288
|
|
|
@@ -462,7 +464,7 @@ Why these choices:
|
|
|
462
464
|
- Jest measures with istanbul (`babel`), because the v8 provider does not count the untaken side of an `if` without `else`.
|
|
463
465
|
- Jest fails on a `coverageThreshold` path key that matches no file, so a typo in `test-gates.json` cannot pass. Vitest does the opposite: a glob or path key in `thresholds` that matches nothing passes. The Vitest helper therefore narrows `coverage.include` to the gates and uses `perFile`.
|
|
464
466
|
- Stryker never fails on its own score (`break: null`). The verdict comes from `test-gates mutation`, which knows the allow list.
|
|
465
|
-
- The Stryker helper also sets defaults that can be overridden: `coverageAnalysis: 'perTest'`, `incremental` with its file under `reports/`, and `
|
|
467
|
+
- The Stryker helper also sets defaults that can be overridden: `coverageAnalysis: 'perTest'`, `incremental` with its file under `reports/`, and `maxTestRunnerReuse: 50` (see [Timeouts](#timeouts)).
|
|
466
468
|
|
|
467
469
|
`loadGates(dir)` returns the validated manifest: `gates` (each with its resolved `spec`), `candidates` and the resolved `settings`. It throws when the manifest has any problem.
|
|
468
470
|
|
package/dist/stryker.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/stryker.ts
|
|
31
31
|
var stryker_exports = {};
|
|
32
32
|
__export(stryker_exports, {
|
|
33
|
-
|
|
33
|
+
DEFAULT_MAX_TEST_RUNNER_REUSE: () => DEFAULT_MAX_TEST_RUNNER_REUSE,
|
|
34
34
|
createStrykerGatesConfig: () => createStrykerGatesConfig
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(stryker_exports);
|
|
@@ -602,7 +602,7 @@ function resolveRootDir(rootDir) {
|
|
|
602
602
|
|
|
603
603
|
// src/stryker.ts
|
|
604
604
|
var WEAKENING_OPTIONS = ["ignoreStatic", "ignorers"];
|
|
605
|
-
var
|
|
605
|
+
var DEFAULT_MAX_TEST_RUNNER_REUSE = 50;
|
|
606
606
|
function createStrykerGatesConfig(options = {}) {
|
|
607
607
|
const { rootDir: rootDirOption, ...overrides } = options;
|
|
608
608
|
for (const option of WEAKENING_OPTIONS) {
|
|
@@ -627,7 +627,7 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
627
627
|
incremental: true,
|
|
628
628
|
incrementalFile: "reports/stryker-incremental.json",
|
|
629
629
|
tempDirName: ".stryker-tmp",
|
|
630
|
-
|
|
630
|
+
maxTestRunnerReuse: DEFAULT_MAX_TEST_RUNNER_REUSE,
|
|
631
631
|
clearTextReporter: { logTests: false, reportTests: false },
|
|
632
632
|
...overrides,
|
|
633
633
|
mutate: manifest.gates.map((gate) => gate.path),
|
|
@@ -638,6 +638,6 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
638
638
|
}
|
|
639
639
|
// Annotate the CommonJS export names for ESM import in node:
|
|
640
640
|
0 && (module.exports = {
|
|
641
|
-
|
|
641
|
+
DEFAULT_MAX_TEST_RUNNER_REUSE,
|
|
642
642
|
createStrykerGatesConfig
|
|
643
643
|
});
|
package/dist/stryker.d.cts
CHANGED
|
@@ -5,11 +5,13 @@ interface StrykerGatesOptions {
|
|
|
5
5
|
[option: string]: unknown;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Stryker's own default is
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Stryker's own default is 0: one test runner process for the whole run. Measured on a Jest
|
|
9
|
+
* project with three mutants that never end (`Hit limit reached`): from the first of them on
|
|
10
|
+
* the runner handled about a third as many mutants per minute for the rest of the run, and
|
|
11
|
+
* mutants that are killed in seconds on their own ran out of time. With a new process every 50
|
|
12
|
+
* mutants the speed stayed the same to the end.
|
|
11
13
|
*/
|
|
12
|
-
declare const
|
|
14
|
+
declare const DEFAULT_MAX_TEST_RUNNER_REUSE = 50;
|
|
13
15
|
/**
|
|
14
16
|
* Stryker config for the gates: mutate exactly the gates, never fail on the score
|
|
15
17
|
* (`thresholds.break: null`), and write the JSON report that `test-gates mutation` judges.
|
|
@@ -19,4 +21,4 @@ declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
|
19
21
|
*/
|
|
20
22
|
declare function createStrykerGatesConfig(options?: StrykerGatesOptions): Record<string, unknown>;
|
|
21
23
|
|
|
22
|
-
export {
|
|
24
|
+
export { DEFAULT_MAX_TEST_RUNNER_REUSE, type StrykerGatesOptions, createStrykerGatesConfig };
|
package/dist/stryker.d.ts
CHANGED
|
@@ -5,11 +5,13 @@ interface StrykerGatesOptions {
|
|
|
5
5
|
[option: string]: unknown;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Stryker's own default is
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Stryker's own default is 0: one test runner process for the whole run. Measured on a Jest
|
|
9
|
+
* project with three mutants that never end (`Hit limit reached`): from the first of them on
|
|
10
|
+
* the runner handled about a third as many mutants per minute for the rest of the run, and
|
|
11
|
+
* mutants that are killed in seconds on their own ran out of time. With a new process every 50
|
|
12
|
+
* mutants the speed stayed the same to the end.
|
|
11
13
|
*/
|
|
12
|
-
declare const
|
|
14
|
+
declare const DEFAULT_MAX_TEST_RUNNER_REUSE = 50;
|
|
13
15
|
/**
|
|
14
16
|
* Stryker config for the gates: mutate exactly the gates, never fail on the score
|
|
15
17
|
* (`thresholds.break: null`), and write the JSON report that `test-gates mutation` judges.
|
|
@@ -19,4 +21,4 @@ declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
|
19
21
|
*/
|
|
20
22
|
declare function createStrykerGatesConfig(options?: StrykerGatesOptions): Record<string, unknown>;
|
|
21
23
|
|
|
22
|
-
export {
|
|
24
|
+
export { DEFAULT_MAX_TEST_RUNNER_REUSE, type StrykerGatesOptions, createStrykerGatesConfig };
|
package/dist/stryker.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
// src/stryker.ts
|
|
9
9
|
var WEAKENING_OPTIONS = ["ignoreStatic", "ignorers"];
|
|
10
|
-
var
|
|
10
|
+
var DEFAULT_MAX_TEST_RUNNER_REUSE = 50;
|
|
11
11
|
function createStrykerGatesConfig(options = {}) {
|
|
12
12
|
const { rootDir: rootDirOption, ...overrides } = options;
|
|
13
13
|
for (const option of WEAKENING_OPTIONS) {
|
|
@@ -32,7 +32,7 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
32
32
|
incremental: true,
|
|
33
33
|
incrementalFile: "reports/stryker-incremental.json",
|
|
34
34
|
tempDirName: ".stryker-tmp",
|
|
35
|
-
|
|
35
|
+
maxTestRunnerReuse: DEFAULT_MAX_TEST_RUNNER_REUSE,
|
|
36
36
|
clearTextReporter: { logTests: false, reportTests: false },
|
|
37
37
|
...overrides,
|
|
38
38
|
mutate: manifest.gates.map((gate) => gate.path),
|
|
@@ -42,6 +42,6 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
export {
|
|
45
|
-
|
|
45
|
+
DEFAULT_MAX_TEST_RUNNER_REUSE,
|
|
46
46
|
createStrykerGatesConfig
|
|
47
47
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t09tanaka/test-gates",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Test gates for the code that must not be wrong: per-file 100% coverage as the floor, mutation testing with a per-mutant allow list as the real check.",
|
|
5
5
|
"author": "t09tanaka",
|
|
6
6
|
"license": "MIT",
|