Stdout redirection with dup2 + tempfile works in main.rs but fails in #[test] — why?

I'm working on a logging system in Rust where I want to capture the output of a macro that writes to stdout (via println!) and validate it in tests.

To capture output, I'm using a dup2 + tempfile + libc::STDOUT_FILENO strategy that redirects stdout to a temporary file. It works perfectly when invoked from main.rs, but fails when the exact same code is run inside a #[test] function.

  • I’m not using io::set_output_capture
  • Even with --nocapture, stdout seems not to flow to the redirected output
  • My macro prints correctly, but the capture shows ""

Has anyone else run into this? Is the test harness doing some internal redirection or buffering of stdout before my dup2 has a chance to take effect?

Here's a minimal example (with main.rs and tests/test-main.rs) to reproduce.

Rust version: rustc 1.86.0 (05f9846f8 2025-03-31)

Files Used for the topic

Appreciate any pointers. Thanks!

it sure does. see:

CORRECTION:

libtest captures the output of the print* family of macros, it does NOT capture or redirect stdout in anyway.

if you want to make sure the text is written to stdout and not captured by libtest, use the write macro instead of print macro, e.g.:

use

writeln!(stdout(), "hello world")

instead of

println!("hello world")

Thanks! That worked.
use std::io::{stdout, Write};

Seems to work for stderr() also.