@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 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
  });
@@ -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.0",
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",