CLI app test fails if `cargo build` is not run first

Viewed 51

I have a pure Rust CLI app that I'm unit testing, and if I run

cargo clean
cargo test --release

it fails to find the binary, but if I run

cargo clean
cargo build --release
cargo test --release

it works. Is there a way to tell cargo not to run the test until the binary app has been built?

Here's my test harness:

#[cfg(test)]
pub mod tests {
    use std::process::Command;

    use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt};
    use predicates::prelude::predicate;

    #[test]
    fn test_that_cli_app_produces_result() -> Result<(), Box<dyn std::error::Error>> {
        let mut cmd = Command::cargo_bin("fastsim-cli")?;
        let mut cyc_file = project_root::get_project_root().unwrap();
        cyc_file.push("../fastsim/resources/cycles/udds.csv");
        assert!(cyc_file.exists());
        let mut veh_file = project_root::get_project_root().unwrap();
        veh_file.push("../fastsim/resources/vehdb/2012_Ford_Fusion.yaml");
        assert!(veh_file.exists());

        cmd.args([
            "--cyc-file",
            cyc_file.to_str().unwrap(),
            "--veh-file",
            veh_file.to_str().unwrap(),
        ]);
        cmd.assert()
            .success()
            .stdout(predicate::str::contains("32.4"));

        Ok(())
    }
}
1 Answers

From the #[cfg(test)] mod tests { I am guessing that this is code that exists inside of your library or binary source files. That is not the correct location for a test which needs to run a built binary. Instead, you should write a so-called “integration test” which are located in the tests/ directory next to src/, and are separate compilation targets (so that they can be built after everything else). Cargo specifically provides for testing binaries via integration tests:

Binary targets are automatically built if there is an integration test. This allows an integration test to execute the binary to exercise and test its behavior. The CARGO_BIN_EXE_<name> environment variable is set when the integration test is built so that it can use the env macro to locate the executable.

If you're already using an integration test, then something else has gone wrong that isn't obvious from your description, because Cargo should be building the binary, as per the documentation.

Related