Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_runner: added coverage support with watch mode #51288

Closed
wants to merge 1 commit into from

Conversation

pulkit-30
Copy link
Contributor

@pulkit-30 pulkit-30 commented Dec 26, 2023

fix #51253

code:

with following test files

// test1.test.mjs
import { test } from 'node:test';

test('test1', () => {})
// test2.test.mjs
import { test } from 'node:test';

test('test2', () => {})

run node --test --experimental-test-coverage --watch

output:

✔ test1 (1.952625ms)
✔ test2 (2.08075ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 228.890917
ℹ start of coverage report
ℹ ---------------------------------------------------------------
ℹ file           | line % | branch % | funcs % | uncovered lines
ℹ ---------------------------------------------------------------
ℹ test1.test.mjs | 100.00 |   100.00 |  100.00 | 
ℹ test2.test.mjs | 100.00 |   100.00 |  100.00 | 
ℹ ---------------------------------------------------------------
ℹ all files      | 100.00 |   100.00 |  100.00 |
ℹ ---------------------------------------------------------------
ℹ end of coverage report
  • when i update test2.test.mjs
✔ test1 (1.952625ms)
✔ test2 (2.08075ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 228.890917
ℹ start of coverage report
ℹ ---------------------------------------------------------------
ℹ file           | line % | branch % | funcs % | uncovered lines
ℹ ---------------------------------------------------------------
ℹ test1.test.mjs | 100.00 |   100.00 |  100.00 | 
ℹ test2.test.mjs | 100.00 |   100.00 |  100.00 | 
ℹ ---------------------------------------------------------------
ℹ all files      | 100.00 |   100.00 |  100.00 |
ℹ ---------------------------------------------------------------
ℹ end of coverage report
✔ test2 (3.161208ms)
ℹ start of coverage report
ℹ ---------------------------------------------------------------
ℹ file           | line % | branch % | funcs % | uncovered lines
ℹ ---------------------------------------------------------------
ℹ test2.test.mjs | 100.00 |   100.00 |  100.00 | 
ℹ ---------------------------------------------------------------
ℹ all files      | 100.00 |   100.00 |  100.00 |
ℹ ---------------------------------------------------------------
ℹ end of coverage report

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Dec 26, 2023
@MoLow
Copy link
Member

MoLow commented Dec 26, 2023

I propose this implementation, which is a little simpler:

diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js
index 2f18b0bcf0..29dc7ca495 100644
--- a/lib/internal/test_runner/harness.js
+++ b/lib/internal/test_runner/harness.js
@@ -177,6 +177,7 @@ function setup(root) {
   root.harness = {
     __proto__: null,
     bootstrapComplete: false,
+    watchMode: false,
     coverage: FunctionPrototypeBind(collectCoverage, null, root, coverage),
     counters: {
       __proto__: null,
diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js
index c4194923cc..810a3ee13e 100644
--- a/lib/internal/test_runner/runner.js
+++ b/lib/internal/test_runner/runner.js
@@ -78,7 +78,7 @@ const {
   exitCodes: { kGenericUserError },
 } = internalBinding('errors');
 
-const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch'];
+const kFilterArgs = new SafeSet(['--test', '--experimental-test-coverage', '--watch']);
 const kFilterArgValues = ['--test-reporter', '--test-reporter-destination'];
 const kDiagnosticsFilterArgs = ['tests', 'suites', 'pass', 'fail', 'cancelled', 'skipped', 'todo', 'duration_ms'];
 
@@ -107,7 +107,7 @@ function createTestFileList() {
 }
 
 function filterExecArgv(arg, i, arr) {
-  return !ArrayPrototypeIncludes(kFilterArgs, arg) &&
+  return !kFilterArgs.has(arg) &&
   !ArrayPrototypeSome(kFilterArgValues, (p) => arg === p || (i > 0 && arr[i - 1] === p) || StringPrototypeStartsWith(arg, `${p}=`));
 }
 
@@ -425,11 +425,10 @@ function watchFiles(testFiles, opts) {
   });
   if (opts.signal) {
     kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
-    opts.signal.addEventListener(
-      'abort',
-      () => opts.root.postRun(),
-      { __proto__: null, once: true, [kResistStopPropagation]: true },
-    );
+    opts.signal.addEventListener('abort', () => {
+      opts.root.postRun();
+      opts.root.reporter.end();
+    }, { __proto__: null, once: true, [kResistStopPropagation]: true });
   }
 
   return filesWatcher;
@@ -497,8 +496,12 @@ function run(options = kEmptyObject) {
   let filesWatcher;
   const opts = { __proto__: null, root, signal, inspectPort, testNamePatterns, only };
   if (watch) {
+    root.harness.watchMode = true;
     filesWatcher = watchFiles(testFiles, opts);
-    postRun = undefined;
+    postRun = () => {
+      kFilterArgs.delete('--experimental-test-coverage');
+      root.postRun();
+    };
   }
   const runFiles = () => {
     root.harness.bootstrapComplete = true;
diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js
index 4eb02c5d4e..b28d00dce2 100644
--- a/lib/internal/test_runner/test.js
+++ b/lib/internal/test_runner/test.js
@@ -756,7 +756,9 @@ class Test extends AsyncResource {
         reporter.coverage(nesting, loc, coverage);
       }
 
-      reporter.end();
+      if (harness.watchMode === false) {
+        reporter.end();
+      }
     }
   }

@pulkit-30
Copy link
Contributor Author

yeah looks clean 👍🏼

@MoLow MoLow added request-ci Add this label to start a Jenkins CI on a PR. author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels Jan 2, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jan 2, 2024
@nodejs-github-bot
Copy link
Collaborator

Copy link
Member

@rluvaton rluvaton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments, great job

@pulkit-30 pulkit-30 requested a review from atlowChemi January 6, 2024 13:47
@benjamingr benjamingr added the request-ci Add this label to start a Jenkins CI on a PR. label Jan 6, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jan 6, 2024
@nodejs-github-bot
Copy link
Collaborator

@atlowChemi
Copy link
Member

@pulkit-30 the failure is related to the changes:

not ok 2474 parallel/test-runner-watch-coverage
  ---
  duration_ms: 2215.81000
  severity: fail
  exitcode: 1
  stack: |-
    TAP version 13
    # Subtest: test runner must report coverage report with watch mode
        # Subtest: should report coverage report with watch mode
        not ok 1 - should report coverage report with watch mode
          ---
          duration_ms: 1797.885443
          location: 'file:///home/iojs/build/workspace/node-test-commit-linux-containered/test/parallel/test-runner-watch-coverage.mjs:80:3'
          failureType: 'testCodeFailure'
          error: |-
            The expression evaluated to a falsy value:
            
              assert(stdout.includes(getCoverageFixtureReport('tap')))
            
          code: 'ERR_ASSERTION'
          name: 'AssertionError'
          expected: true
          actual: false
          operator: '=='
          stack: |-
            TestContext.<anonymous> (file:///home/iojs/build/workspace/node-test-commit-linux-containered/test/parallel/test-runner-watch-coverage.mjs:82:5)
            process.processTicksAndRejections (node:internal/process/task_queues:95:5)
            async Test.run (node:internal/test_runner/test:632:9)
            async Promise.all (index 0)
            async Suite.run (node:internal/test_runner/test:951:7)
            async startSubtest (node:internal/test_runner/harness:219:3)
          ...
        1..1
    not ok 1 - test runner must report coverage report with watch mode
      ---
      duration_ms: 1801.223591
      type: 'suite'
      location: 'file:///home/iojs/build/workspace/node-test-commit-linux-containered/test/parallel/test-runner-watch-coverage.mjs:79:1'
      failureType: 'subtestsFailed'
      error: '1 subtest failed'
      code: 'ERR_TEST_FAILURE'
      ...
    1..1
    # tests 1
    # suites 1
    # pass 0
    # fail 1
    # cancelled 0
    # skipped 0
    # todo 0
    # duration_ms 1826.192055
  ...

@atlowChemi atlowChemi added the request-ci Add this label to start a Jenkins CI on a PR. label Jan 8, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jan 8, 2024
@nodejs-github-bot
Copy link
Collaborator

@MoLow
Copy link
Member

MoLow commented Jan 10, 2024

@MoLow MoLow added the request-ci Add this label to start a Jenkins CI on a PR. label Jan 13, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jan 13, 2024
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@cjihrig
Copy link
Contributor

cjihrig commented Mar 24, 2024

The linked issue is now closed, so I'll go ahead and close this as well. Thanks for the PR though.

@cjihrig cjihrig closed this Mar 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

test_runner: add coverage support with watch mode.
7 participants