Beyond unit tests in our library crate, we can also integration test our actual final binary.
There’s a few different ways to get the path to the cargo binary that gets built when you test, but the easiest I’ve found by far is to use the asset_cmd
crate.
❯ cargo add --dev assert_cmd
Updating crates.io index
Adding assert_cmd v2.0.12 to dev-dependencies.
Features:
- color
- color-auto
Updating crates.io index
Integration tests live in the tests
directory and only have access to the public interface of your library. Each Rust source file in the tests
directory is compiled as a separate crate.
I’ve named my file integration.rs
, but that can be whatever your want.
touch tests/integration.rs
Inside of integration.rs
we can set up two tests. Each of them is fairly straightforward and only tests functionality that is created for us by clap, but it gives us a good idea of what it looks like to run a binary.
/// make sure help runs. This indicates the binary works
#[test]
fn test_help() {
assert_cmd::Command::cargo_bin("garden")
.unwrap()
.arg("--help")
.assert()
.success()
.stderr("");
}
/// make sure we have a write command by running `garden write --help`
#[test]
fn test_write_help() {
assert_cmd::Command::cargo_bin("garden")
.unwrap()
.arg("write")
.arg("--help")
.assert()
.success()
.stderr("");
}
assert_cmd::Command::cargo_bin
is a function that will locate the cargo binary for us and create a assert_cmd::Command
from it.
assert_cmd::Command
allows us to build up the execution of our binary using builder functions and then execute that command.
For example, the first test builds garden --help
and the second builds garden write --help
.
assert
then runs the command we’ve built, and allows us to test the output.
The Assert
struct returned from the assert
function includes a series of functions for testing the output. .success
makes sure the command ran successfully, and .stderr
allows us to test the output of stderr.
There’s no output on stderr
for our binary when outputting help text, so we can test against an empty string.
For programs that don’t require interactivity this is often enough to exercise the different ways in which the binary can be used, from user input to CLI output and more.