Cargo doesn't capture stderr in tests

I found this topic in a discussion thread in 2017. I'm running into the same problem, and I'm wondering if there anything new on the subject. (See. I'm a good boy and didn't reopen an old topic.)

1 Like

That thread suggests a complicated situation. The current one (which might be the same) is fairly simple as I understand it, though inelegant:

  • print!, println!, eprint!, eprintln! all participate in the test output capturing mechanism.
  • std::io::stdout(), std::io::stderr() don't; they are unmediated access to file descriptors (except for the lock).

In order to write to stderr but participate in capturing, use eprint! for your output.

I am using eprintln! in my tests. That's the output that's not being suppressed.

eprintln! calls std::io::_eprint, and _eprint delegates to the capturing mechanism, which uses a thread-local variable for the capture hook.

Are you perhaps calling eprintln! from a thread other than the thread your #[test] function was called on? If so, the output won't be captured, because there's no inter-thread inheritance mechanism that could do that.

3 Likes

I think you've identified my problem. The eprintln! is in another process. I guess I have to tell the process when it's running under a test so it can skip the output manually.

Or you could, for testing, capture the output of the process yourself. then eprint! it. If that suits your needs.

i didn't know that I specifically have to use the macros to get my output captured during tests. That is good to know.

Do you know the reason why it has been implemented that way? The only reason I might think of is that it could be difficult on some platforms to redirect stdout/stderr (e.g. by replacing it with socket pair on the file descriptor level, of which one end is connected with the capturing mechanism). Or is there another reason, or is this just random or deliberately done through the macros?

There are often multiple tests running at the same time. You can't set the stdout and stderr fd for a specific thread. println!() and friends can be captured on a per test basis as they use thread local storage for storing an output redirection.

I guess the only way to work around that would be to use multiple processes instead of threads? But maybe that gives other problems... And not sure if it's really important for many cases, except maybe when libraries are involved (e.g. native libraries) that write to stdout/stderr.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.