@t09tanaka/test-gates 0.3.0 → 0.3.1
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 +6 -0
- package/README.md +3 -0
- package/dist/stryker.cjs +4 -0
- package/dist/stryker.d.cts +7 -1
- package/dist/stryker.d.ts +7 -1
- package/dist/stryker.js +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `createStrykerGatesConfig` sets Stryker's `timeoutMS` to 30000 unless the project passes its own (Stryker's default is 5000). With `maxTimeouts` at 0 since 0.3.0, a mutant that would be killed but ran out of time fails the run. That happened on every full run in two projects with mutants that really never end: after each of them Stryker starts a new test runner, and the next mutant timed out while it was starting. A full run takes longer by up to 25 seconds for each mutant that hangs without tripping Stryker's loop counter.
|
|
8
|
+
|
|
3
9
|
## 0.3.0
|
|
4
10
|
|
|
5
11
|
Three defaults move to the strict side. A project that passed with 0.2.0 can fail with 0.3.0 without any change of its own; each case below says what to do.
|
package/README.md
CHANGED
|
@@ -280,6 +280,8 @@ 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 `timeoutMS` to 30000 (since 0.3.1; Stryker's own default is 5000). After a mutant that really never ends, Stryker starts a new test runner, and with 5000 the mutant that comes next can run out of time while that runner is still starting: in one project with 11 such mutants, 2 to 7 others timed out on every full run, a different set each time, and none in a run with 30000. A longer limit hides nothing, because a timeout that is not listed fails the run anyway. The price is the wait for each mutant that hangs without tripping Stryker's loop counter. Pass `timeoutMS` to the helper to change it.
|
|
284
|
+
|
|
283
285
|
### `test-gates selfcheck [--all | --first] [-- <gate command>]`
|
|
284
286
|
|
|
285
287
|
Negative control. For each gate, runs the gate with that gate's spec left out and requires the run to **fail on the coverage threshold of that very file**. A gate that stays green without its spec measures nothing; a run that fails for another reason (a config that does not load) proves nothing either.
|
|
@@ -460,6 +462,7 @@ Why these choices:
|
|
|
460
462
|
- Jest measures with istanbul (`babel`), because the v8 provider does not count the untaken side of an `if` without `else`.
|
|
461
463
|
- 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`.
|
|
462
464
|
- 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 `timeoutMS: 30000` (see [Timeouts](#timeouts)).
|
|
463
466
|
|
|
464
467
|
`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.
|
|
465
468
|
|
package/dist/stryker.cjs
CHANGED
|
@@ -30,6 +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
|
+
DEFAULT_TIMEOUT_MS: () => DEFAULT_TIMEOUT_MS,
|
|
33
34
|
createStrykerGatesConfig: () => createStrykerGatesConfig
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(stryker_exports);
|
|
@@ -601,6 +602,7 @@ function resolveRootDir(rootDir) {
|
|
|
601
602
|
|
|
602
603
|
// src/stryker.ts
|
|
603
604
|
var WEAKENING_OPTIONS = ["ignoreStatic", "ignorers"];
|
|
605
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
604
606
|
function createStrykerGatesConfig(options = {}) {
|
|
605
607
|
const { rootDir: rootDirOption, ...overrides } = options;
|
|
606
608
|
for (const option of WEAKENING_OPTIONS) {
|
|
@@ -625,6 +627,7 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
625
627
|
incremental: true,
|
|
626
628
|
incrementalFile: "reports/stryker-incremental.json",
|
|
627
629
|
tempDirName: ".stryker-tmp",
|
|
630
|
+
timeoutMS: DEFAULT_TIMEOUT_MS,
|
|
628
631
|
clearTextReporter: { logTests: false, reportTests: false },
|
|
629
632
|
...overrides,
|
|
630
633
|
mutate: manifest.gates.map((gate) => gate.path),
|
|
@@ -635,5 +638,6 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
635
638
|
}
|
|
636
639
|
// Annotate the CommonJS export names for ESM import in node:
|
|
637
640
|
0 && (module.exports = {
|
|
641
|
+
DEFAULT_TIMEOUT_MS,
|
|
638
642
|
createStrykerGatesConfig
|
|
639
643
|
});
|
package/dist/stryker.d.cts
CHANGED
|
@@ -4,6 +4,12 @@ interface StrykerGatesOptions {
|
|
|
4
4
|
/** Any other Stryker option: testRunner, jest / vitest, concurrency, ignorePatterns, … */
|
|
5
5
|
[option: string]: unknown;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Stryker's own default is 5000. After a mutant that really never ends, Stryker starts a new
|
|
9
|
+
* test runner, and the next mutant then pays that start-up inside its time limit: with 5000 a
|
|
10
|
+
* mutant that would be killed is reported as `Timeout`, which fails the run since 0.3.0.
|
|
11
|
+
*/
|
|
12
|
+
declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
7
13
|
/**
|
|
8
14
|
* Stryker config for the gates: mutate exactly the gates, never fail on the score
|
|
9
15
|
* (`thresholds.break: null`), and write the JSON report that `test-gates mutation` judges.
|
|
@@ -13,4 +19,4 @@ interface StrykerGatesOptions {
|
|
|
13
19
|
*/
|
|
14
20
|
declare function createStrykerGatesConfig(options?: StrykerGatesOptions): Record<string, unknown>;
|
|
15
21
|
|
|
16
|
-
export { type StrykerGatesOptions, createStrykerGatesConfig };
|
|
22
|
+
export { DEFAULT_TIMEOUT_MS, type StrykerGatesOptions, createStrykerGatesConfig };
|
package/dist/stryker.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ interface StrykerGatesOptions {
|
|
|
4
4
|
/** Any other Stryker option: testRunner, jest / vitest, concurrency, ignorePatterns, … */
|
|
5
5
|
[option: string]: unknown;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Stryker's own default is 5000. After a mutant that really never ends, Stryker starts a new
|
|
9
|
+
* test runner, and the next mutant then pays that start-up inside its time limit: with 5000 a
|
|
10
|
+
* mutant that would be killed is reported as `Timeout`, which fails the run since 0.3.0.
|
|
11
|
+
*/
|
|
12
|
+
declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
7
13
|
/**
|
|
8
14
|
* Stryker config for the gates: mutate exactly the gates, never fail on the score
|
|
9
15
|
* (`thresholds.break: null`), and write the JSON report that `test-gates mutation` judges.
|
|
@@ -13,4 +19,4 @@ interface StrykerGatesOptions {
|
|
|
13
19
|
*/
|
|
14
20
|
declare function createStrykerGatesConfig(options?: StrykerGatesOptions): Record<string, unknown>;
|
|
15
21
|
|
|
16
|
-
export { type StrykerGatesOptions, createStrykerGatesConfig };
|
|
22
|
+
export { DEFAULT_TIMEOUT_MS, type StrykerGatesOptions, createStrykerGatesConfig };
|
package/dist/stryker.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
|
|
8
8
|
// src/stryker.ts
|
|
9
9
|
var WEAKENING_OPTIONS = ["ignoreStatic", "ignorers"];
|
|
10
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
10
11
|
function createStrykerGatesConfig(options = {}) {
|
|
11
12
|
const { rootDir: rootDirOption, ...overrides } = options;
|
|
12
13
|
for (const option of WEAKENING_OPTIONS) {
|
|
@@ -31,6 +32,7 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
31
32
|
incremental: true,
|
|
32
33
|
incrementalFile: "reports/stryker-incremental.json",
|
|
33
34
|
tempDirName: ".stryker-tmp",
|
|
35
|
+
timeoutMS: DEFAULT_TIMEOUT_MS,
|
|
34
36
|
clearTextReporter: { logTests: false, reportTests: false },
|
|
35
37
|
...overrides,
|
|
36
38
|
mutate: manifest.gates.map((gate) => gate.path),
|
|
@@ -40,5 +42,6 @@ function createStrykerGatesConfig(options = {}) {
|
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
export {
|
|
45
|
+
DEFAULT_TIMEOUT_MS,
|
|
43
46
|
createStrykerGatesConfig
|
|
44
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.1",
|
|
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",
|