mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Fail the test when no tests match the filter (#20749)
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com> Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
This commit is contained in:
@@ -398,7 +398,7 @@ pub const JunitReporter = struct {
|
||||
\\ </testcase>
|
||||
, .{});
|
||||
},
|
||||
.skip => {
|
||||
.skipped_because_label, .skip => {
|
||||
this.testcases_metrics.skipped += 1;
|
||||
try this.contents.appendSlice(bun.default_allocator, ">\n <skipped />\n </testcase>\n");
|
||||
},
|
||||
@@ -462,7 +462,6 @@ pub const CommandLineReporter = struct {
|
||||
jest: TestRunner,
|
||||
callback: TestRunner.Callback,
|
||||
last_dot: u32 = 0,
|
||||
summary: Summary = Summary{},
|
||||
prev_file: u64 = 0,
|
||||
repeat_count: u32 = 1,
|
||||
|
||||
@@ -476,15 +475,6 @@ pub const CommandLineReporter = struct {
|
||||
junit: *JunitReporter,
|
||||
};
|
||||
|
||||
pub const Summary = struct {
|
||||
pass: u32 = 0,
|
||||
expectations: u32 = 0,
|
||||
skip: u32 = 0,
|
||||
todo: u32 = 0,
|
||||
fail: u32 = 0,
|
||||
files: u32 = 0,
|
||||
};
|
||||
|
||||
const DotColorMap = std.EnumMap(TestRunner.Test.Status, string);
|
||||
const dots: DotColorMap = brk: {
|
||||
var map: DotColorMap = DotColorMap.init(.{});
|
||||
@@ -607,6 +597,10 @@ pub const CommandLineReporter = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn summary(this: *CommandLineReporter) *TestRunner.Summary {
|
||||
return &this.jest.summary;
|
||||
}
|
||||
|
||||
pub fn handleTestPass(cb: *TestRunner.Callback, id: Test.ID, file: string, label: string, expectations: u32, elapsed_ns: u64, parent: ?*jest.DescribeScope) void {
|
||||
const writer_ = Output.errorWriter();
|
||||
var buffered_writer = std.io.bufferedWriter(writer_);
|
||||
@@ -620,8 +614,8 @@ pub const CommandLineReporter = struct {
|
||||
printTestLine(.pass, label, elapsed_ns, parent, expectations, false, writer, file, this.file_reporter);
|
||||
|
||||
this.jest.tests.items(.status)[id] = TestRunner.Test.Status.pass;
|
||||
this.summary.pass += 1;
|
||||
this.summary.expectations += expectations;
|
||||
this.summary().pass += 1;
|
||||
this.summary().expectations += expectations;
|
||||
}
|
||||
|
||||
pub fn handleTestFail(cb: *TestRunner.Callback, id: Test.ID, file: string, label: string, expectations: u32, elapsed_ns: u64, parent: ?*jest.DescribeScope) void {
|
||||
@@ -646,11 +640,11 @@ pub const CommandLineReporter = struct {
|
||||
Output.flush();
|
||||
|
||||
// this.updateDots();
|
||||
this.summary.fail += 1;
|
||||
this.summary.expectations += expectations;
|
||||
this.summary().fail += 1;
|
||||
this.summary().expectations += expectations;
|
||||
this.jest.tests.items(.status)[id] = TestRunner.Test.Status.fail;
|
||||
|
||||
if (this.jest.bail == this.summary.fail) {
|
||||
if (this.jest.bail == this.summary().fail) {
|
||||
this.printSummary();
|
||||
Output.prettyError("\nBailed out after {d} failure{s}<r>\n", .{ this.jest.bail, if (this.jest.bail == 1) "" else "s" });
|
||||
Global.exit(1);
|
||||
@@ -676,8 +670,18 @@ pub const CommandLineReporter = struct {
|
||||
}
|
||||
|
||||
// this.updateDots();
|
||||
this.summary.skip += 1;
|
||||
this.summary.expectations += expectations;
|
||||
this.summary().skip += 1;
|
||||
this.summary().expectations += expectations;
|
||||
this.jest.tests.items(.status)[id] = TestRunner.Test.Status.skip;
|
||||
}
|
||||
|
||||
pub fn handleTestFilteredOut(cb: *TestRunner.Callback, id: Test.ID, _: string, _: string, expectations: u32, _: u64, _: ?*jest.DescribeScope) void {
|
||||
var this: *CommandLineReporter = @fieldParentPtr("callback", cb);
|
||||
|
||||
// this.updateDots();
|
||||
this.summary().skipped_because_label += 1;
|
||||
this.summary().skip += 1;
|
||||
this.summary().expectations += expectations;
|
||||
this.jest.tests.items(.status)[id] = TestRunner.Test.Status.skip;
|
||||
}
|
||||
|
||||
@@ -698,16 +702,23 @@ pub const CommandLineReporter = struct {
|
||||
Output.flush();
|
||||
|
||||
// this.updateDots();
|
||||
this.summary.todo += 1;
|
||||
this.summary.expectations += expectations;
|
||||
this.summary().todo += 1;
|
||||
this.summary().expectations += expectations;
|
||||
this.jest.tests.items(.status)[id] = TestRunner.Test.Status.todo;
|
||||
}
|
||||
|
||||
pub fn printSummary(this: *CommandLineReporter) void {
|
||||
const tests = this.summary.fail + this.summary.pass + this.summary.skip + this.summary.todo;
|
||||
const files = this.summary.files;
|
||||
const summary_ = this.summary();
|
||||
const tests = summary_.fail + summary_.pass + summary_.skip + summary_.todo;
|
||||
const files = summary_.files;
|
||||
|
||||
Output.prettyError("Ran {d} test{s} across {d} file{s}. ", .{
|
||||
tests,
|
||||
if (tests == 1) "" else "s",
|
||||
files,
|
||||
if (files == 1) "" else "s",
|
||||
});
|
||||
|
||||
Output.prettyError("Ran {d} tests across {d} files. ", .{ tests, files });
|
||||
Output.printStartEnd(bun.start_time, std.time.nanoTimestamp());
|
||||
}
|
||||
|
||||
@@ -1063,6 +1074,7 @@ pub const TestCommand = struct {
|
||||
.onTestFail = CommandLineReporter.handleTestFail,
|
||||
.onTestSkip = CommandLineReporter.handleTestSkip,
|
||||
.onTestTodo = CommandLineReporter.handleTestTodo,
|
||||
.onTestFilteredOut = CommandLineReporter.handleTestFilteredOut,
|
||||
};
|
||||
reporter.repeat_count = @max(ctx.test_options.repeat_count, 1);
|
||||
reporter.jest.callback = &reporter.callback;
|
||||
@@ -1225,33 +1237,33 @@ pub const TestCommand = struct {
|
||||
const write_snapshots_success = try jest.Jest.runner.?.snapshots.writeInlineSnapshots();
|
||||
try jest.Jest.runner.?.snapshots.writeSnapshotFile();
|
||||
var coverage_options = ctx.test_options.coverage;
|
||||
if (reporter.summary.pass > 20) {
|
||||
if (reporter.summary.skip > 0) {
|
||||
Output.prettyError("\n<r><d>{d} tests skipped:<r>\n", .{reporter.summary.skip});
|
||||
if (reporter.summary().pass > 20) {
|
||||
if (reporter.summary().skip > 0) {
|
||||
Output.prettyError("\n<r><d>{d} tests skipped:<r>\n", .{reporter.summary().skip});
|
||||
Output.flush();
|
||||
|
||||
var error_writer = Output.errorWriter();
|
||||
error_writer.writeAll(reporter.skips_to_repeat_buf.items) catch unreachable;
|
||||
}
|
||||
|
||||
if (reporter.summary.todo > 0) {
|
||||
if (reporter.summary.skip > 0) {
|
||||
if (reporter.summary().todo > 0) {
|
||||
if (reporter.summary().skip > 0) {
|
||||
Output.prettyError("\n", .{});
|
||||
}
|
||||
|
||||
Output.prettyError("\n<r><d>{d} tests todo:<r>\n", .{reporter.summary.todo});
|
||||
Output.prettyError("\n<r><d>{d} tests todo:<r>\n", .{reporter.summary().todo});
|
||||
Output.flush();
|
||||
|
||||
var error_writer = Output.errorWriter();
|
||||
error_writer.writeAll(reporter.todos_to_repeat_buf.items) catch unreachable;
|
||||
}
|
||||
|
||||
if (reporter.summary.fail > 0) {
|
||||
if (reporter.summary.skip > 0 or reporter.summary.todo > 0) {
|
||||
if (reporter.summary().fail > 0) {
|
||||
if (reporter.summary().skip > 0 or reporter.summary().todo > 0) {
|
||||
Output.prettyError("\n", .{});
|
||||
}
|
||||
|
||||
Output.prettyError("\n<r><d>{d} tests failed:<r>\n", .{reporter.summary.fail});
|
||||
Output.prettyError("\n<r><d>{d} tests failed:<r>\n", .{reporter.summary().fail});
|
||||
Output.flush();
|
||||
|
||||
var error_writer = Output.errorWriter();
|
||||
@@ -1261,7 +1273,11 @@ pub const TestCommand = struct {
|
||||
|
||||
Output.flush();
|
||||
|
||||
var failed_to_find_any_tests = false;
|
||||
|
||||
if (test_files.len == 0) {
|
||||
failed_to_find_any_tests = true;
|
||||
|
||||
if (ctx.positionals.len == 0) {
|
||||
Output.prettyErrorln(
|
||||
\\<yellow>No tests found!<r>
|
||||
@@ -1321,76 +1337,92 @@ pub const TestCommand = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (reporter.summary.pass > 0) {
|
||||
Output.prettyError("<r><green>", .{});
|
||||
}
|
||||
const summary = reporter.summary();
|
||||
const did_label_filter_out_all_tests = summary.didLabelFilterOutAllTests() and reporter.jest.unhandled_errors_between_tests == 0;
|
||||
|
||||
Output.prettyError(" {d:5>} pass<r>\n", .{reporter.summary.pass});
|
||||
|
||||
if (reporter.summary.skip > 0) {
|
||||
Output.prettyError(" <r><yellow>{d:5>} skip<r>\n", .{reporter.summary.skip});
|
||||
}
|
||||
|
||||
if (reporter.summary.todo > 0) {
|
||||
Output.prettyError(" <r><magenta>{d:5>} todo<r>\n", .{reporter.summary.todo});
|
||||
}
|
||||
|
||||
if (reporter.summary.fail > 0) {
|
||||
Output.prettyError("<r><red>", .{});
|
||||
} else {
|
||||
Output.prettyError("<r><d>", .{});
|
||||
}
|
||||
|
||||
Output.prettyError(" {d:5>} fail<r>\n", .{reporter.summary.fail});
|
||||
if (reporter.jest.unhandled_errors_between_tests > 0) {
|
||||
Output.prettyError(" <r><red>{d:5>} error{s}<r>\n", .{ reporter.jest.unhandled_errors_between_tests, if (reporter.jest.unhandled_errors_between_tests > 1) "s" else "" });
|
||||
}
|
||||
|
||||
var print_expect_calls = reporter.summary.expectations > 0;
|
||||
if (reporter.jest.snapshots.total > 0) {
|
||||
const passed = reporter.jest.snapshots.passed;
|
||||
const failed = reporter.jest.snapshots.failed;
|
||||
const added = reporter.jest.snapshots.added;
|
||||
|
||||
var first = true;
|
||||
if (print_expect_calls and added == 0 and failed == 0) {
|
||||
print_expect_calls = false;
|
||||
Output.prettyError(" {d:5>} snapshots, {d:5>} expect() calls", .{ reporter.jest.snapshots.total, reporter.summary.expectations });
|
||||
} else {
|
||||
Output.prettyError(" <d>snapshots:<r> ", .{});
|
||||
|
||||
if (passed > 0) {
|
||||
Output.prettyError("<d>{d} passed<r>", .{passed});
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (added > 0) {
|
||||
if (first) {
|
||||
first = false;
|
||||
Output.prettyError("<b>+{d} added<r>", .{added});
|
||||
} else {
|
||||
Output.prettyError("<b>, {d} added<r>", .{added});
|
||||
}
|
||||
}
|
||||
|
||||
if (failed > 0) {
|
||||
if (first) {
|
||||
first = false;
|
||||
Output.prettyError("<red>{d} failed<r>", .{failed});
|
||||
} else {
|
||||
Output.prettyError(", <red>{d} failed<r>", .{failed});
|
||||
}
|
||||
}
|
||||
if (!did_label_filter_out_all_tests) {
|
||||
if (summary.pass > 0) {
|
||||
Output.prettyError("<r><green>", .{});
|
||||
}
|
||||
|
||||
Output.prettyError("\n", .{});
|
||||
}
|
||||
Output.prettyError(" {d:5>} pass<r>\n", .{summary.pass});
|
||||
|
||||
if (print_expect_calls) {
|
||||
Output.prettyError(" {d:5>} expect() calls\n", .{reporter.summary.expectations});
|
||||
}
|
||||
if (summary.skip > 0) {
|
||||
Output.prettyError(" <r><yellow>{d:5>} skip<r>\n", .{summary.skip});
|
||||
} else if (summary.skipped_because_label > 0) {
|
||||
Output.prettyError(" <r><d>{d:5>} filtered out<r>\n", .{summary.skipped_because_label});
|
||||
}
|
||||
|
||||
reporter.printSummary();
|
||||
if (summary.todo > 0) {
|
||||
Output.prettyError(" <r><magenta>{d:5>} todo<r>\n", .{summary.todo});
|
||||
}
|
||||
|
||||
if (summary.fail > 0) {
|
||||
Output.prettyError("<r><red>", .{});
|
||||
} else {
|
||||
Output.prettyError("<r><d>", .{});
|
||||
}
|
||||
|
||||
Output.prettyError(" {d:5>} fail<r>\n", .{summary.fail});
|
||||
if (reporter.jest.unhandled_errors_between_tests > 0) {
|
||||
Output.prettyError(" <r><red>{d:5>} error{s}<r>\n", .{ reporter.jest.unhandled_errors_between_tests, if (reporter.jest.unhandled_errors_between_tests > 1) "s" else "" });
|
||||
}
|
||||
|
||||
var print_expect_calls = reporter.summary().expectations > 0;
|
||||
if (reporter.jest.snapshots.total > 0) {
|
||||
const passed = reporter.jest.snapshots.passed;
|
||||
const failed = reporter.jest.snapshots.failed;
|
||||
const added = reporter.jest.snapshots.added;
|
||||
|
||||
var first = true;
|
||||
if (print_expect_calls and added == 0 and failed == 0) {
|
||||
print_expect_calls = false;
|
||||
Output.prettyError(" {d:5>} snapshots, {d:5>} expect() calls", .{ reporter.jest.snapshots.total, reporter.summary().expectations });
|
||||
} else {
|
||||
Output.prettyError(" <d>snapshots:<r> ", .{});
|
||||
|
||||
if (passed > 0) {
|
||||
Output.prettyError("<d>{d} passed<r>", .{passed});
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (added > 0) {
|
||||
if (first) {
|
||||
first = false;
|
||||
Output.prettyError("<b>+{d} added<r>", .{added});
|
||||
} else {
|
||||
Output.prettyError("<b>, {d} added<r>", .{added});
|
||||
}
|
||||
}
|
||||
|
||||
if (failed > 0) {
|
||||
if (first) {
|
||||
first = false;
|
||||
Output.prettyError("<red>{d} failed<r>", .{failed});
|
||||
} else {
|
||||
Output.prettyError(", <red>{d} failed<r>", .{failed});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Output.prettyError("\n", .{});
|
||||
}
|
||||
|
||||
if (print_expect_calls) {
|
||||
Output.prettyError(" {d:5>} expect() calls\n", .{reporter.summary().expectations});
|
||||
}
|
||||
|
||||
reporter.printSummary();
|
||||
} else {
|
||||
Output.prettyError("<red>error<r><d>:<r> regex <b>{}<r> matched 0 tests. Searched {d} file{s} (skipping {d} test{s}) ", .{
|
||||
bun.fmt.quote(ctx.test_options.test_filter_pattern.?),
|
||||
summary.files,
|
||||
if (summary.files == 1) "" else "s",
|
||||
summary.skipped_because_label,
|
||||
if (summary.skipped_because_label == 1) "" else "s",
|
||||
});
|
||||
Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
Output.prettyError("\n", .{});
|
||||
@@ -1410,8 +1442,9 @@ pub const TestCommand = struct {
|
||||
if (vm.hot_reload == .watch) {
|
||||
vm.runWithAPILock(JSC.VirtualMachine, vm, runEventLoopForWatch);
|
||||
}
|
||||
const summary = reporter.summary();
|
||||
|
||||
if (reporter.summary.fail > 0 or (coverage_options.enabled and coverage_options.fractions.failing and coverage_options.fail_on_low_coverage) or !write_snapshots_success) {
|
||||
if (failed_to_find_any_tests or summary.didLabelFilterOutAllTests() or summary.fail > 0 or (coverage_options.enabled and coverage_options.fractions.failing and coverage_options.fail_on_low_coverage) or !write_snapshots_success) {
|
||||
Global.exit(1);
|
||||
} else if (reporter.jest.unhandled_errors_between_tests > 0) {
|
||||
Global.exit(reporter.jest.unhandled_errors_between_tests);
|
||||
@@ -1523,14 +1556,14 @@ pub const TestCommand = struct {
|
||||
Output.flush();
|
||||
|
||||
var promise = try vm.loadEntryPointForTestRunner(file_path);
|
||||
reporter.summary.files += 1;
|
||||
reporter.summary().files += 1;
|
||||
|
||||
switch (promise.status(vm.global.vm())) {
|
||||
.rejected => {
|
||||
vm.unhandledRejection(vm.global, promise.result(vm.global.vm()), promise.asValue());
|
||||
reporter.summary.fail += 1;
|
||||
reporter.summary().fail += 1;
|
||||
|
||||
if (reporter.jest.bail == reporter.summary.fail) {
|
||||
if (reporter.jest.bail == reporter.summary().fail) {
|
||||
reporter.printSummary();
|
||||
Output.prettyError("\nBailed out after {d} failure{s}<r>\n", .{ reporter.jest.bail, if (reporter.jest.bail == 1) "" else "s" });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user