テスト

知っての通り、テストはどんなソフトウェアにも不可欠です!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 3 tests test test_bar ... ok test test_baz ... ok test test_foo_bar ... ok test test_foo ... ok test result: ok. 3 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 { // Import the necessary modules // 必要なモジュールをインポートする。 use std::fs::OpenOptions; use std::io::Write; // This test writes to a file // ファイルに書き込むテスト。 #[test] fn test_file() { // Opens the file ferris.txt or creates one if it doesn't exist. // ferris.txtというファイルを開くか、存在しない場合は作成する。 let mut file = OpenOptions::new() .append(true) .create(true) .open("ferris.txt") .expect("Failed to open ferris.txt"); // Print "Ferris" 5 times. // "Ferris"と5回書き込む。 for _ in 0..5 { file.write_all("Ferris\n".as_bytes()) .expect("Could not write to ferris.txt"); } } // This test tries to write to the same file // 同じファイルに書き込むテスト。 #[test] fn test_file_also() { // Opens the file ferris.txt or creates one if it doesn't exist. // ferris.txtというファイルを開くか、存在しない場合は作成する。 let mut file = OpenOptions::new() .append(true) .create(true) .open("ferris.txt") .expect("Failed to open ferris.txt"); // Print "Corro" 5 times. // "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_foo Corro Ferris Corro Ferris Corro Ferris Corro Ferris Corro Ferris