Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/guides/test/coverage-threshold.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ bun test --coverage

```txt
test.test.ts:
✓ math > add [0.71ms]
✓ math > multiply [0.03ms]
math
✓ add [0.71ms]
✓ multiply [0.03ms]
✓ random [0.13ms]
-------------|---------|---------|-------------------
File | % Funcs | % Lines | Uncovered Line #s
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/test/coverage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ bun test --coverage
```txt

test.test.ts:
✓ math > add [0.71ms]
✓ math > multiply [0.03ms]
math
✓ add [0.71ms]
✓ multiply [0.03ms]
✓ random [0.13ms]
-------------|---------|---------|-------------------
File | % Funcs | % Lines | Uncovered Line #s
Expand Down
16 changes: 16 additions & 0 deletions docs/test/reporters.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ test/package-json-lint.test.ts:
Ran 4 tests across 1 files. [0.66ms]
```

Tests inside a `describe` block are nested beneath their scope, which is printed once:

```sh terminal icon="terminal"
test/math.test.ts:
math
arithmetic
✓ add [0.12ms]
✓ subtract [0.04ms]
✓ is a module [0.03ms]
✓ top-level test [0.02ms]

4 pass
0 fail
Ran 4 tests across 1 files. [0.31ms]
```

### Dots Reporter

The dots reporter shows `.` for passing tests and prints full error details for failures, useful for large test suites.
Expand Down
10 changes: 10 additions & 0 deletions src/runtime/cli/test/parallel/Coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ pub struct Coordinator<'a> {
/// from concurrent workers interleave; whenever the source file changes the
/// header is re-emitted so every line has visible context. None at start.
pub last_header_idx: Option<u32>,
/// Describe-scope path whose headers have already been printed under the
/// current `last_header_idx`. Cleared whenever the file header is re-emitted.
pub printed_scope_path: Vec<u8>,
pub frame: Frame,
pub parallel_limit: u32,
pub scale_up_after_ms: i64,
Expand Down Expand Up @@ -307,6 +310,7 @@ impl<'a> Coordinator<'a> {
return;
}
self.last_header_idx = Some(file_idx);
self.printed_scope_path.clear();
let _ = write!(
Output::error_writer(),
"\n{}:\n",
Expand Down Expand Up @@ -344,6 +348,7 @@ impl<'a> Coordinator<'a> {
}
frame::Kind::TestDone => {
let idx = rd.u32_();
let scope_path = rd.str();
let formatted = rd.str();
if w.inflight != Some(idx) {
return;
Expand All @@ -358,6 +363,11 @@ impl<'a> Coordinator<'a> {
if !is_dot {
self.break_dots();
self.ensure_header(idx);
CommandLineReporter::emit_scope_headers(
&mut self.printed_scope_path,
scope_path,
Output::error_writer(),
);
}
let _ = Output::error_writer().write_all(formatted);
self.last_printed_dot = is_dot;
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/cli/test/parallel/Frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ pub enum Kind {
Ready,
/// u32 file_idx
FileStart,
/// u32 file_idx, str formatted_line (ANSI included; printed verbatim)
/// u32 file_idx, str scope_path (`\x1f`-separated describe names, outermost
/// first), str formatted_line (ANSI included; printed verbatim)
TestDone,
/// 9 × u32: file_idx, pass, fail, skip, todo, expectations, skipped_label, files, unhandled
FileDone,
Expand Down
9 changes: 6 additions & 3 deletions src/runtime/cli/test/parallel/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ pub fn run_as_coordinator(
junit_fragments: Vec::new(),
coverage_fragments: Vec::new(),
last_header_idx: None,
printed_scope_path: Vec::new(),
frame: Frame::default(),
files_done: 0,
spawned_count: 0,
Expand Down Expand Up @@ -803,9 +804,10 @@ static WORKER_CMDS: bun_core::RacyCell<Option<*mut WorkerCommands>> = bun_core::
// pointee outlives all callers (process exits before it's dropped).

/// Called from `CommandLineReporter.handleTestCompleted` in the worker with the
/// fully-formatted status line (✓/✗ + scopes + name + duration, including ANSI
/// codes). The coordinator prints these bytes verbatim so output matches serial.
pub fn worker_emit_test_done(file_idx: u32, formatted_line: &[u8]) {
/// describe-scope path plus the fully-formatted status line (✓/✗ + indent + name
/// + duration, including ANSI codes). The coordinator prints the scope headers it
/// hasn't printed yet, then these bytes verbatim, so output matches serial.
pub fn worker_emit_test_done(file_idx: u32, scope_path: &[u8], formatted_line: &[u8]) {
// SAFETY: single-threaded worker; WORKER_CMDS only written/read on this thread.
let Some(cmds_ptr) = (unsafe { WORKER_CMDS.read() }) else {
return;
Expand All @@ -817,6 +819,7 @@ pub fn worker_emit_test_done(file_idx: u32, formatted_line: &[u8]) {
let wf = unsafe { &mut *WORKER_FRAME.get() };
wf.begin(frame::Kind::TestDone);
wf.u32_(file_idx);
wf.str(scope_path);
wf.str(formatted_line);
cmds.send(wf.finish());
}
Loading