Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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