Integration testing Cargo binaries with assert_cmd

InstructorChris Biscardi

Share this video with your friends

Send Tweet

Cargo allows us to execute a few different kinds of tests, including integration and unit. For now we'll talk about integration tests for our CLI. Integration tests live in /tests and only have access to the public interface of a crate.

In this case, we'll run the garden binary using assert_cmd and assert various things about the execution and output. For example, that the binary exits successfully and that stderr has no output.

cargo test allows us to run all tests.

To restrict the number of tests that run to only the two that work, we can use cargo test help to restrict cargo to only running tests that match the keyword "help", or use #[ignore] on a test we want to ignore.

The third test will be ignored because we have yet to build out our functionality.

Tommy Williams
~ 3 years ago

The parameter annotations in gray in your editor are confusing if you don't know Rust. I had to go find the code on Github to figure out how to get my test of help to work.

Chris Biscardiinstructor
~ 3 years ago

Hey Tommy! :)

I totally understand that the annotations can be confusing. The extension that is adding them is called rust-analyzer, which is a major part of the Rust project and represents the future for Rust IDE tooling. While I try to remove anything that might be extraneous information in my courses I made the decision to keep rust-analyzer in this series because it shows information that is otherwise hard to come by for beginners, such as inferred types of local variables and chained expressions and the names of function arguments. The inferred types are shown in the same place you would write them in the source code in this lesson, so you can choose to also type them out or not.

This does mean that there is a difference between what is shown on screen during the video and what is in the source files. I believe that this difference is beneficial since rust-analyzer is the suggested editor integration for Rust and the information it provides is hard to glean without more familiarity with Rust and both sources are made available. This is also the reason I take the time to create and link to individual commits for each lesson, so that if there is any confusion it can be resolved by checking the source code.

Tommy Williams
~ 3 years ago

Thanks, Chris, for both the quick reply and the clear explanation.

I went into this thinking it was for beginners and only realized after my comment that it was probably assumed that I knew more about Rust.

I figured out pretty quickly that those were annotations, but where I got stuck was realizing that in:

let mut cmd: Command = Comand::...

That it was ": Command" that I needed to ignore rather than "Command =".

And that just comes down to me not knowing enough about Rust.

So I have bounced over to running through the rustlings exercises for now and will come back once I have finished those and have a better handle on more of the basics of the language.

Robert Pearce
~ 3 years ago

Looks like the API has changed:

use assert_cmd::assert::Assert;
use assert_cmd::Command;
use color_eyre::eyre::Result;

#[test]
fn test_help() -> Result<()> {
    let mut cmd: Command = Command::cargo_bin("garden")?;
    let assert: Assert = cmd.arg("help").assert();
    assert.success().stderr("");
    Ok(())
}