test_runner: support expecting a test-case to fail · nodejs/node@d77f98c · GitHub
Skip to content

Commit d77f98c

Browse files
JakobJingleheimervespa7
authored andcommitted
test_runner: support expecting a test-case to fail
Co-Authored-By: Alejandro Espa <98526766+vespa7@users.noreply.github.com> PR-URL: #60669 Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Jordan Harband <ljharb@gmail.com>
1 parent 8e48e72 commit d77f98c

22 files changed

Lines changed: 806 additions & 493 deletions

doc/api/test.md

Lines changed: 51 additions & 0 deletions

lib/internal/test_runner/harness.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ function runInParentContext(Factory) {
377377

378378
return run(name, options, fn, overrides);
379379
};
380-
ArrayPrototypeForEach(['skip', 'todo', 'only'], (keyword) => {
380+
ArrayPrototypeForEach(['expectFailure', 'skip', 'todo', 'only'], (keyword) => {
381381
test[keyword] = (name, options, fn) => {
382382
const overrides = {
383383
__proto__: null,

lib/internal/test_runner/reporter/tap.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ async function * tapReporter(source) {
3333
for await (const { type, data } of source) {
3434
switch (type) {
3535
case 'test:fail': {
36-
yield reportTest(data.nesting, data.testNumber, 'not ok', data.name, data.skip, data.todo);
36+
yield reportTest(data.nesting, data.testNumber, 'not ok', data.name, data.skip, data.todo, data.expectFailure);
3737
const location = data.file ? `${data.file}:${data.line}:${data.column}` : null;
3838
yield reportDetails(data.nesting, data.details, location);
3939
break;
4040
} case 'test:pass':
41-
yield reportTest(data.nesting, data.testNumber, 'ok', data.name, data.skip, data.todo);
41+
yield reportTest(data.nesting, data.testNumber, 'ok', data.name, data.skip, data.todo, data.expectFailure);
4242
yield reportDetails(data.nesting, data.details, null);
4343
break;
4444
case 'test:plan':
@@ -65,7 +65,7 @@ async function * tapReporter(source) {
6565
}
6666
}
6767

68-
function reportTest(nesting, testNumber, status, name, skip, todo) {
68+
function reportTest(nesting, testNumber, status, name, skip, todo, expectFailure) {
6969
let line = `${indent(nesting)}${status} ${testNumber}`;
7070

7171
if (name) {
@@ -76,6 +76,8 @@ function reportTest(nesting, testNumber, status, name, skip, todo) {
7676
line += ` # SKIP${typeof skip === 'string' && skip.length ? ` ${tapEscape(skip)}` : ''}`;
7777
} else if (todo !== undefined) {
7878
line += ` # TODO${typeof todo === 'string' && todo.length ? ` ${tapEscape(todo)}` : ''}`;
79+
} else if (expectFailure !== undefined) {
80+
line += ' # EXPECTED FAILURE';
7981
}
8082

8183
line += '\n';

lib/internal/test_runner/reporter/utils.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,16 @@ function formatError(error, indent) {
7070
function formatTestReport(type, data, showErrorDetails = true, prefix = '', indent = '') {
7171
let color = reporterColorMap[type] ?? colors.white;
7272
let symbol = reporterUnicodeSymbolMap[type] ?? ' ';
73-
const { skip, todo } = data;
73+
const { skip, todo, expectFailure } = data;
7474
const duration_ms = data.details?.duration_ms ? ` ${colors.gray}(${data.details.duration_ms}ms)${colors.white}` : '';
7575
let title = `${data.name}${duration_ms}`;
7676

7777
if (skip !== undefined) {
7878
title += ` # ${typeof skip === 'string' && skip.length ? skip : 'SKIP'}`;
7979
} else if (todo !== undefined) {
8080
title += ` # ${typeof todo === 'string' && todo.length ? todo : 'TODO'}`;
81+
} else if (expectFailure !== undefined) {
82+
title += ` # EXPECTED FAILURE`;
8183
}
8284

8385
const err = showErrorDetails && data.details?.error ? formatError(data.details.error, indent) : '';

lib/internal/test_runner/test.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ class Test extends AsyncResource {
496496
super('Test');
497497

498498
let { fn, name, parent } = options;
499-
const { concurrency, entryFile, loc, only, timeout, todo, skip, signal, plan } = options;
499+
const { concurrency, entryFile, expectFailure, loc, only, timeout, todo, skip, signal, plan } = options;
500500

501501
if (typeof fn !== 'function') {
502502
fn = noop;
@@ -635,6 +635,7 @@ class Test extends AsyncResource {
635635
this.plan = null;
636636
this.expectedAssertions = plan;
637637
this.cancelled = false;
638+
this.expectFailure = expectFailure !== undefined && expectFailure !== false;
638639
this.skipped = skip !== undefined && skip !== false;
639640
this.isTodo = (todo !== undefined && todo !== false) || this.parent?.isTodo;
640641
this.startTime = null;
@@ -946,7 +947,12 @@ class Test extends AsyncResource {
946947
return;
947948
}
948949

949-
this.passed = false;
950+
if (this.expectFailure === true) {
951+
this.passed = true;
952+
} else {
953+
this.passed = false;
954+
}
955+
950956
this.error = err;
951957
}
952958

@@ -1343,6 +1349,8 @@ class Test extends AsyncResource {
13431349
directive = this.reporter.getSkip(this.message);
13441350
} else if (this.isTodo) {
13451351
directive = this.reporter.getTodo(this.message);
1352+
} else if (this.expectFailure) {
1353+
directive = this.reporter.getXFail(this.expectFailure); // TODO(@JakobJingleheimer): support specifying failure
13461354
}
13471355

13481356
if (this.reportedType) {
@@ -1357,6 +1365,7 @@ class Test extends AsyncResource {
13571365
if (this.passedAttempt !== undefined) {
13581366
details.passed_on_attempt = this.passedAttempt;
13591367
}
1368+
13601369
return { __proto__: null, details, directive };
13611370
}
13621371

lib/internal/test_runner/tests_stream.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class TestsStream extends Readable {
8787
return { __proto__: null, todo: reason ?? true };
8888
}
8989

90+
getXFail(expectation = undefined) {
91+
return { __proto__: null, expectFailure: expectation ?? true };
92+
}
93+
9094
enqueue(nesting, loc, name, type) {
9195
this[kEmitMessage]('test:enqueue', {
9296
__proto__: null,

test/fixtures/test-runner/output/describe_it.js

Lines changed: 24 additions & 1 deletion

0 commit comments

Comments
 (0)