Rustで失敗に関係なく全てのテストを実行する方法

記事作成のための確認事項

  • この記事は何を書くのか一言で
    • cargo test --no-fail-fastで失敗に関係なく全てのテストを実行できる
  • KeyWord
    • Rust, テスト
  • この記事を誰に提供したいのか
    • Rustを使ってる人
  • この記事を通して何を提供するのか
    • Rustでのテストのバリエーション

はじめに

この記事では、「Rustで失敗に関係なく全てのテストを実行する方法」について書いています。

Rustを色々勉強中ですが知らないこともまだたくさんあり、Rustの勉強も兼ねて記事を書きました。

自分に向けた備忘録の意味もありますが、「Rustでもっと良いテストがしたい」や「Rustでテストをする方法をまだよく知らない」な人の一助になれば嬉しいです。

要点だけ

  • 通常のテスト: cargo test <- これは途中でテストが失敗したら、全てのテストを実行してなくてもその時点で終了します
  • 失敗に関係なく全てのテストを実行する : cargo test --no-fail-fast

前提(環境)

私の環境のバージョン情報は以下の通りです。

プロジェクトの構成とコード

実験のために、以下のプロジェクトを用意しました。

sample
├ src
│  └ main.rs
├ tests
│  ├ test_add.rs
│  └ test_sub.rs
└ Carto.toml

各rsファイルの中身は以下の通りです。

main.rsはただHello Worldを出力するだけです。

fn main() {
    println!("Hello, world!");
}

test_add.rs, test_sub.rsも足し算、引き算のテストを行うだけです。

ちなみに、この段階では全てのテストは成功します。

#[cfg(test)]
mod tests {

    #[test]
    fn test_add1() {
        assert_eq!(2, 1+1);
    }
    
    #[test]
    fn test_add2() {
        assert_eq!(3, 1+2);
    }
}
#[cfg(test)]
mod tests {

    #[test]
    fn test_sub1() {
        assert_eq!(2, 3-1);
    }
    
    #[test]
    fn test_sub2() {
        assert_eq!(3, 4-1);
    }
}

このプロジェクトをベースにして実験を行っていきます。

全てのテストに成功する状態で、引数なしでテストを実行した場合

まずはcargo testを実行してみます。結果は以下の通りです。(testsフォルダの中のファイルのテストのみを載せます)

...(省略)...

     Running tests\test_add.rs (target\debug\deps\test_add-e04c9af421762cf2.exe)

running 2 tests
test tests::test_add2 ... ok
test tests::test_add1 ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests\test_sub.rs (target\debug\deps\test_sub-91afd5bb6e6fa34d.exe)

running 2 tests
test tests::test_sub1 ... ok
test tests::test_sub2 ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

当然ですが、全てのテストに合格した旨が出力されています。

テストの一部が失敗する状態で、引数なしでテストを実行した場合

続いて、テストの一部を失敗するように、test_add.rsのtest_add1()関数を以下のように書き換えます

    #[test]
    fn test_add1() {
        assert_eq!(3, 1+1);  // 2だったのを3に変更
    }

この状態でcargo testを実行するとどうなるでしょうか

...(省略)...

     Running tests\test_add.rs (target\debug\deps\test_add-e04c9af421762cf2.exe)

running 2 tests
test tests::test_add2 ... ok
test tests::test_add1 ... FAILED

failures:

---- tests::test_add1 stdout ----
thread 'tests::test_add1' panicked at 'assertion failed: `(left == right)`
  left: `3`,
 right: `2`', tests\test_add.rs:7:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::test_add1

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s

error: test failed, to rerun pass '--test test_add'

test_add1で失敗したと出力されているのはいいですが、本当はあるはずのtest_sub.rsのテストが実行されていません。

これはcargo testの仕様で、途中でテストに失敗したら、他にテストを行うファイルがあっても辞めるようです。

テストの一部が失敗する状態でも全てのテストを実行させる

では、テストの一部が失敗する状態でも全てのテストを実行させるにはどうすればいいでしょうか。

それはcargo test --no-fail-fastと、testの後ろに--no-fail-fastをつけてください

これを実行すると出力は以下のようになります。

...(省略)...

     Running tests\test_add.rs (target\debug\deps\test_add-e04c9af421762cf2.exe)

running 2 tests
test tests::test_add2 ... ok
test tests::test_add1 ... FAILED

failures:

---- tests::test_add1 stdout ----
thread 'tests::test_add1' panicked at 'assertion failed: `(left == right)`
  left: `3`,
 right: `2`', tests\test_add.rs:7:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::test_add1

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests\test_sub.rs (target\debug\deps\test_sub-91afd5bb6e6fa34d.exe)

running 2 tests
test tests::test_sub1 ... ok
test tests::test_sub2 ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass '--test test_add'

test_subファイルのテストも実行、表示されました。

おわりに

「Rustで失敗に関係なく全てのテストを実行する方法」について解説しました。

この方法を知っておくと、「全体でいくつエラーがあったか知りたい」時などに役に立つかと思います。

さいごに、記事を書く上で参考にしたサイトのリンクを以下に掲載します。合わせて読んでいただくと良いかと思います。

doc.rust-lang.org