No_run outside of documentation tests (doctests)

This is quite hard to search for because "rust compile only test" or "rust no run test" is very ambiguous in English, so instead I'm opening this.

Is there a way to make a normal #[test] but that is not ran, only compiled? Similar to doctests with no_run:

/// I want this, but not in a doctest:
/// ```no_run
/// let _foo = bar();
/// ```
fn bar() -> i32 { 3 }

The reason is I can't have a doctest on a private item:

if you need to test private items, you need to write a unit test.

And I also don't want it to run because it would be trying to connect to some random IP address when network access may not be available, but it still should compile.

I couldn't find anything for "no_run", "compile-only", "compile only" in the Writing Automated Tests section of The Book, or Rust by Example's Unit testing.

You can write normal function for it. Compiler never let the non-compilable function lives within the source code.

#[cfg(test)] // prevents this compile-only test function never be shipped within executable binary
#[allow(dead_code)] // prevents to emit dead code warning
fn bar() -> i32 {
    3
}
2 Likes

That's a clever way to write a #[test] that's not actually one. Thanks! Will wait a bit more to see if there are better options, else I'll mark it as solution.

#[test]
#[ignore]
fn test() {}

this will compile the function and show that it was ignored in the test runner

The problem with that is that it will be ran by cargo test -- --ignored, and I may have other tests under #[ignore] that I want to run sometimes but not always, as described in Ignoring Some Tests Unless Specifically Requested. This one should always be compile-only, and not run then.

Then @Hyeonu's solution is the best one. You could also stuff all those compile only tests into a module marked #[cfg(test)] to reduce the boilerplate.

or use a #[test] with body wrapped in if false {}

1 Like

Doesn't the Rust compiler ignore dead code for at least some checks? At least I remember seeing something like that in the issues of the Rust repository, but maybe compilation is always done, just not those certain checks. Not sure if only for dead branches or entire functions, or then the other approach wouldn't work either now that I think about it.

If it compiles with the if false {, it will also compile without it.

Not sure if this is the issue I was thinking of, but Dead code is not checked is somewhat relevant. It compiles with a (contrived) if false but doesn't without it.

Yeah, but there's a reason you need a contrived if false, and that just using if false doesn't trigger it: In that case simply looking at the control graph of the code illuminates the problem, but if false does not produce such a control graph, and does not cause the never type to crop up, which is the source of unreachable_code warnings.

An actual if false is not removed until you reach optimization, which is after any type or borrow checking.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.