14

Some projects include multiple crates, which makes it a hassle to run all tests manually in each.

Is there a convenient way to recursively run cargo test ?

Shepmaster
  • 274,917
  • 47
  • 731
  • 969
ideasman42
  • 30,245
  • 24
  • 136
  • 249
  • Glad to see I'm not the only one wishing to bundle multiple crates in the same repository. I am surprised cargo doesn't seem to have better support for this. – Matthieu M. Feb 01 '17 at 08:52

4 Answers4

8

Update: since adding this answer 1.15 was released, adding cargo test --all, will compare this with a custom script.


This shell-script runs tests recursively on a git repository for all directories containing a Cargo.toml file (easy enough to edit for other VCS).

  • Exits on the first error.
  • Uses nocapture so stdout is shown
    (depends on personal preference, easy to adjust).
  • Runs tests with RUST_BACKTRACE set, for more useful output.
  • Builds and runs in two separate steps
    (workaround for this bug in 1.14 stable).
  • Optional CARGO_BIN environment variable to override the cargo command
    (handy if you want to use a cargo-wrapper such as cargo-out-of-source builder).

Script:

#!/bin/bash

# exit on first error, see: http://stackoverflow.com/a/185900/432509
error() {
    local parent_lineno="$1"
    local message="$2"
    local code="${3:-1}"
    if [[ -n "$message" ]] ; then
        echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
    else
        echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
    fi
    exit "${code}"
}
trap 'error ${LINENO}' ERR
# done with trap

# support cargo command override
if [[ -z $CARGO_BIN ]]; then
    CARGO_BIN=cargo
fi

# toplevel git repo
ROOT=$(git rev-parse --show-toplevel)

for cargo_dir in $(find "$ROOT" -name Cargo.toml -printf '%h\n'); do
    echo "Running tests in: $cargo_dir"
    pushd "$cargo_dir"
    RUST_BACKTRACE=0 $CARGO_BIN test --no-run
    RUST_BACKTRACE=1 $CARGO_BIN test -- --nocapture
    popd
done

Thanks to @набиячлэвэли's answer, this is an expanded version.

ideasman42
  • 30,245
  • 24
  • 136
  • 249
6

You could use a shell script. According to this answer, this

find . -name Cargo.toml -printf '%h\n'

Will print out the directories containing Cargo.toml, so, composing this with the rest of the standard shell utils yields us

for f in $(find . -name Cargo.toml -printf '%h\n' | sort -u); do
  pushd $f > /dev/null;
  cargo test;
  popd > /dev/null;
done

Which will iterate over all directories containing Cargo.toml (a good bet for crates) and run cargo test in them.

Community
  • 1
  • 1
набиячлэвэли
  • 3,049
  • 3
  • 28
  • 39
4

I cannot test it right now, but I believe you can use cargo test --all to do that.

barjak
  • 9,744
  • 3
  • 30
  • 46
2

You could use the cargo workspace feature. This crate collection uses it in combination with a Makefile, which can be used to compile each crate on its own.

(The workspace feature helps to not compile common dependencies multiple times)

musicmatze
  • 3,603
  • 6
  • 26
  • 43