テスト - Rust By Example
Description: Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries.

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# テスト

知っての通り、テストはどんなソフトウェアにも不可欠です！Rustはユニットテストと統合テストを第一級にサポートしています（TRPLのこの章を参照してください）。

上のリンク先のテストの章では、ユニットテストと統合テストの書き方を紹介しています。ユニットテストはテスト対象のモジュール内に、統合テストは`tests/`ディレクトリ内に置きます。

    foo
    ├── Cargo.toml
    ├── src
    │   └── main.rs
    │   └── lib.rs
    └── tests
        ├── my_test.rs
        └── my_other_test.rs

`tests`内の各ファイルは個別の統合テストです。これはライブラリを依存クレートから呼ばれたかのようにテストできます。

テストの章は3つの異なるテストスタイルについて解説しています。単体テスト、ドキュメンテーションテスト、そして結合テストです。

`cargo`は、全てのテストを簡単に実行する方法を提供します。

    $ cargo test

出力はこのようになります。

    $ cargo test
       Compiling blah v0.1.0 (file:///nobackup/blah)
        Finished dev [unoptimized + debuginfo] target(s) in 0.89 secs
         Running target/debug/deps/blah-d3b32b97275ec472

    running 4 tests
    test test_bar ... ok
    test test_baz ... ok
    test test_foo_bar ... ok
    test test_foo ... ok

    test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

パターンにマッチする名前のテストを実行することもできます。

    $ cargo test test_foo

    $ cargo test test_foo
       Compiling blah v0.1.0 (file:///nobackup/blah)
        Finished dev [unoptimized + debuginfo] target(s) in 0.35 secs
         Running target/debug/deps/blah-d3b32b97275ec472

    running 2 tests
    test test_foo ... ok
    test test_foo_bar ... ok

    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out

注意：Cargoは複数のテストを並列で実行することがありますので、それらが互いに競合しないようにしてください。

並行性が問題を引き起こす一例として、以下のように、2つのテストが1つのファイルに出力するケースがあります。

    #![allow(unused)]
    fn main() {
    #[cfg(test)]
    mod tests {
        // 必要なモジュールをインポートします。
        use std::fs::OpenOptions;
        use std::io::Write;

        // ファイルに書き込むテスト
        #[test]
        fn test_file() {
            // ferris.txtというファイルを開くか、存在しない場合は作成します。
            let mut file = OpenOptions::new()
                .append(true)
                .create(true)
                .open("ferris.txt")
                .expect("Failed to open ferris.txt");

            // "Ferris"と5回書き込みます。
            for _ in 0..5 {
                file.write_all("Ferris\n".as_bytes())
                    .expect("Could not write to ferris.txt");
            }
        }

        // 同じファイルに書き込むテスト
        #[test]
        fn test_file_also() {
            // ferris.txtというファイルを開くか、存在しない場合は作成します。
            let mut file = OpenOptions::new()
                .append(true)
                .create(true)
                .open("ferris.txt")
                .expect("Failed to open ferris.txt");

            // "Corro"と5回書き込みます。
            for _ in 0..5 {
                file.write_all("Corro\n".as_bytes())
                    .expect("Could not write to ferris.txt");
            }
        }
    }
    }

以下のような結果を得ようと意図しています。

    $ cat ferris.txt
    Ferris
    Ferris
    Ferris
    Ferris
    Ferris
    Corro
    Corro
    Corro
    Corro
    Corro

しかし、実際に`ferris.txt`に出力されるのは、以下の通りです。

    $ cargo test test_file && cat ferris.txt
    Corro
    Ferris
    Corro
    Ferris
    Corro
    Ferris
    Corro
    Ferris
    Corro
    Ferris