-
Notifications
You must be signed in to change notification settings - Fork 30k
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: fix spec skip detection #47537
Conversation
Review requested:
|
@nodejs/test_runner even after this PR there are discrepancies when running with and without diff --git a/test/fixtures/test-runner/output/spec_reporter.js b/test/fixtures/test-runner/output/spec_reporter.js
index 6a7c2d655f..20ef4f140c 100644
--- a/test/fixtures/test-runner/output/spec_reporter.js
+++ b/test/fixtures/test-runner/output/spec_reporter.js
@@ -5,7 +5,7 @@ const fixtures = require('../../../common/fixtures');
const spawn = require('node:child_process').spawn;
const child = spawn(process.execPath,
- ['--no-warnings', '--test-reporter', 'spec', fixtures.path('test-runner/output/output.js')],
+ ['--no-warnings', '--test', '--test-reporter', 'spec', fixtures.path('test-runner/output/output.js')],
{ stdio: 'pipe' }); diff --git a/test/fixtures/test-runner/output/spec_reporter.snapshot b/test/fixtures/test-runner/output/spec_reporter.snapshot
index ad0c88c26f..8f5cf3131b 100644
--- a/test/fixtures/test-runner/output/spec_reporter.snapshot
+++ b/test/fixtures/test-runner/output/spec_reporter.snapshot
@@ -57,7 +57,7 @@
*
async assertion fail (*ms)
- AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ AssertionError: Expected values to be strictly equal:
true !== false
@@ -68,7 +68,7 @@
*
*
* {
- generatedMessage: true,
+ generatedMessage: false,
code: 'ERR_ASSERTION',
actual: true,
expected: false,
@@ -109,7 +109,8 @@
subtest sync throw fail (*ms)
sync throw non-error fail (*ms)
- Symbol(thrown symbol from sync throw non-error fail)
+ [Error: Symbol(thrown symbol from sync throw non-error fail)
+ ]
level 0a
level 1a (*ms)
@@ -120,7 +121,8 @@
top level
+long running (*ms)
- 'test did not finish before its parent and was cancelled'
+ [Error: test did not finish before its parent and was cancelled
+ ]
+short running
++short running (*ms)
@@ -149,8 +151,7 @@
<anonymous> (*ms) # SKIP
test with a name and options provided (*ms) # SKIP
functionAndOptions (*ms) # SKIP
- escaped description \ # \#\
- � � (*ms)
+ escaped description \ # \#\ \n \t \f \v \b \r (*ms)
escaped skip message (*ms) # SKIP
escaped todo message (*ms)
escaped diagnostic (*ms)
@@ -165,7 +166,8 @@
async t is this in test (*ms)
callback t is this in test (*ms)
callback also returns a Promise (*ms)
- 'passed a callback but also returned a Promise'
+ [Error: passed a callback but also returned a Promise
+ ]
callback throw (*ms)
Error: thrown from callback throw
@@ -178,16 +180,14 @@
*
callback called twice (*ms)
- 'callback invoked multiple times'
+ Error: callback invoked multiple times
+ *
+ *
callback called twice in different ticks (*ms)
callback called twice in future tick (*ms)
- Error [ERR_TEST_FAILURE]: callback invoked multiple times
- * {
- failureType: 'multipleCallbackInvocations',
- cause: 'callback invoked multiple times',
- code: 'ERR_TEST_FAILURE'
- }
+ Error: callback invoked multiple times
+ *
callback async throw (*ms)
Error: thrown from callback async throw
@@ -206,10 +206,15 @@
'only' and 'runOnly' require the --test-only command-line option.
custom inspect symbol fail (*ms)
- customized
+ [Error: customized
+ ]
custom inspect symbol that throws fail (*ms)
- { foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] }
+ [Error: {
+ foo: 1,
+ [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]]
+ }
+ ]
subtest sync throw fails
sync throw fails at first (*ms)
@@ -241,16 +246,19 @@
subtest sync throw fails (*ms)
timed out async test (*ms)
- 'test timed out after *ms'
+ [Error: test timed out after *ms
+ ]
timed out callback test (*ms)
- 'test timed out after *ms'
+ [Error: test timed out after *ms
+ ]
large timeout async test is ok (*ms)
large timeout callback test is ok (*ms)
successful thenable (*ms)
rejected thenable (*ms)
- 'custom error'
+ [Error: custom error
+ ]
unfinished test with uncaughtException (*ms)
Error: foo
@@ -265,7 +273,7 @@
*
assertion errors display actual and expected properly (*ms)
- AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal:
+ AssertionError: Expected values to be loosely deep-equal:
{
bar: 1,
@@ -279,7 +287,7 @@
c: [Circular *1]
}
* {
- generatedMessage: true,
+ generatedMessage: false,
code: 'ERR_ASSERTION',
actual: [Object],
expected: [Object],
@@ -287,7 +295,8 @@
}
invalid subtest fail (*ms)
- 'test could not be started because its parent finished'
+ Error: test could not be started because its parent finished
+ *
Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
@@ -358,7 +367,7 @@
*
async assertion fail (*ms)
- AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ AssertionError: Expected values to be strictly equal:
true !== false
@@ -369,7 +378,7 @@
*
*
* {
- generatedMessage: true,
+ generatedMessage: false,
code: 'ERR_ASSERTION',
actual: true,
expected: false,
@@ -400,16 +409,20 @@
*
subtest sync throw fail (*ms)
- '1 subtest failed'
+ [Error: 1 subtest failed
+ ]
sync throw non-error fail (*ms)
- Symbol(thrown symbol from sync throw non-error fail)
+ [Error: Symbol(thrown symbol from sync throw non-error fail)
+ ]
+long running (*ms)
- 'test did not finish before its parent and was cancelled'
+ [Error: test did not finish before its parent and was cancelled
+ ]
top level (*ms)
- '1 subtest failed'
+ [Error: 1 subtest failed
+ ]
sync skip option is false fail (*ms)
Error: this should be executed
@@ -427,7 +440,8 @@
*
callback also returns a Promise (*ms)
- 'passed a callback but also returned a Promise'
+ [Error: passed a callback but also returned a Promise
+ ]
callback throw (*ms)
Error: thrown from callback throw
@@ -440,15 +454,13 @@
*
callback called twice (*ms)
- 'callback invoked multiple times'
+ Error: callback invoked multiple times
+ *
+ *
callback called twice in future tick (*ms)
- Error [ERR_TEST_FAILURE]: callback invoked multiple times
- * {
- failureType: 'multipleCallbackInvocations',
- cause: 'callback invoked multiple times',
- code: 'ERR_TEST_FAILURE'
- }
+ Error: callback invoked multiple times
+ *
callback async throw (*ms)
Error: thrown from callback async throw
@@ -456,10 +468,15 @@
*
custom inspect symbol fail (*ms)
- customized
+ [Error: customized
+ ]
custom inspect symbol that throws fail (*ms)
- { foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] }
+ [Error: {
+ foo: 1,
+ [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]]
+ }
+ ]
sync throw fails at first (*ms)
Error: thrown from subtest sync throw fails at first
@@ -488,16 +505,20 @@
*
subtest sync throw fails (*ms)
- '2 subtests failed'
+ [Error: 2 subtests failed
+ ]
timed out async test (*ms)
- 'test timed out after *ms'
+ [Error: test timed out after *ms
+ ]
timed out callback test (*ms)
- 'test timed out after *ms'
+ [Error: test timed out after *ms
+ ]
rejected thenable (*ms)
- 'custom error'
+ [Error: custom error
+ ]
unfinished test with uncaughtException (*ms)
Error: foo
@@ -512,7 +533,7 @@
*
assertion errors display actual and expected properly (*ms)
- AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal:
+ AssertionError: Expected values to be loosely deep-equal:
{
bar: 1,
@@ -526,7 +547,7 @@
c: [Circular *1]
}
* {
- generatedMessage: true,
+ generatedMessage: false,
code: 'ERR_ASSERTION',
actual: [Object],
expected: [Object],
@@ -534,4 +555,5 @@
}
invalid subtest fail (*ms)
- 'test could not be started because its parent finished'
+ Error: test could not be started because its parent finished
+ * |
CC @ErickWendel |
@@ -100,7 +100,7 @@ class SpecReporter extends Transform { | |||
ArrayPrototypeShift(this.#reported); | |||
hasChildren = true; | |||
} | |||
const skippedSubtest = subtest && data.skip && data.skip !== undefined; | |||
const skippedSubtest = subtest && 'skip' in data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think this is right - skip
has to be truthy, otherwise skip: false
will skip a test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
skip can be an empty string or undefined, but Il fix it to support false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in every test runner i'm aware of, a falsyskip
- including undefined and an empty string - does not skip the test. The purpose is so you can dynamically skip something, and it would be incredibly surprising and confusing to users if a falsy value meant "true".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I guess you are right it seems like the TAP parser makes skip an empty string
4971d18
to
e7e9868
Compare
test.reason = reason; | ||
} | ||
|
||
if (todoOrSkipToken === 'todo' || todoOrSkipToken === 'skip') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing that needs to change in this PR, but this whole block (lines 745-761 with the changes in this PR) looks like it could be optimized a bit.
@@ -321,7 +321,7 @@ not ok 3 - test # TODO reason`, | |||
status: { fail: false, pass: true, todo: false, skip: true }, | |||
id: '2', | |||
description: 'test', | |||
reason: '', | |||
reason: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes in this file, and the first two changes in test/parallel/test-runner-tap-parser.js
don't look correct. I would think the boolean would be status.skip
, which it looks like it is on line 321. The reason should be a string.
directive = this.reporter.getSkip(node.reason || true); | ||
} else if (todo) { | ||
directive = this.reporter.getTodo(node.reason); | ||
directive = this.reporter.getTodo(node.reason || true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, always?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inside this code branch? yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then why the node.reason ||
at all, if it'll literally always be true? or is it for a skip message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a string including a description for the skip, it is not necesaraly a boolean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in lib/internal/test_runner/tests_stream.js
we are doing this. Should we change that to ||
instead of using ||
in this file and then ??
again there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, since in tests_stream
we do not want to convert falsy values to true
, but here it is ok since we are inside an if detecting we are in a skipped test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but left a small comment: #47537 (comment).
Landed in 46a3cff |
PR-URL: #47537 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
PR-URL: #47537 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
PR-URL: nodejs#47537 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
Refs: #47525 (comment)