単体テストを作成する
Rust の単体テストは、テスト以外のコードが期待どおりに機能していることを検証する #[test]
属性でマークされた単純な関数です。 これらの関数は、コードをテストするときにのみコンパイルされます。
テスト関数によって、テストするコードが実行されます。 次に、結果がチェックされます。これには多くの場合、assert!
または assert_eq!
のいずれかのマクロが使用されます。
次のコード例では、単純な add
関数と、#[test]
属性でマークされた別の add_works
関数を定義します。
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[test]
fn add_works() {
assert_eq!(add(1, 2), 3);
assert_eq!(add(10, 12), 22);
assert_eq!(add(5, -2), 3);
}
コマンド $ cargo test
を実行すると、出力は次の例のようになります。
running 1 test
test add_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
テスト不合格
単に cargo tests
の動作を確認するために、失敗するテストを含めてみましょう。
#[test]
fn add_fails() {
assert_eq!(add(2, 2), 7);
}
$ cargo test
コマンドを使用してテストを再度実行すると、出力に add_works
テストに合格したことが示されます。 また、add_fails
が失敗したことが示され、assert_eq
への呼び出しに失敗したことに関する情報が含まれます。
running 2 tests
test add_works ... ok
test add_fails ... FAILED
failures:
---- add_fails stdout ----
thread 'add_fails' panicked at 'assertion failed: `(left == right)`
left: `4`,
right: `7`', src/main.rs:14:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
add_fails
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
予想される失敗
多くのシナリオでは、条件によって panic!
が発生するかどうかをテストすることが重要です。
属性 should_panic
を使用すると、panic!
を確認できます。 この属性をテスト関数に追加すると、関数内のコードがパニックになったときにテストが成功します。 コードがパニックにならないと、テストは失敗します。
ここで、add_fails
テスト関数により、予想されるパニックがキャプチャされ、それが成功テストとして扱われます。
#[test]
#[should_panic]
fn add_fails() {
assert_eq!(add(2, 2), 7);
}
テスト結果は次のようになります。
running 2 tests
test add_works ... ok
test add_fails ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
テストを無視する
[test]
属性の注釈が付けられた関数には、[ignore]
属性の注釈を付けることもできます。 この属性により、テスト中にテスト関数がスキップされます。
[ignore]
属性は、必要に応じて、テストが無視される理由と共に書き込むことができます。
#[test]
#[ignore = "not yet reviewed by the Q.A. team"]
fn add_negatives() {
assert_eq!(add(-2, -2), -4)
}
無視されたテスト関数は引き続き型チェックされ、コンパイルされますが、テストで実行されることはありません。
running 3 tests
test add_negatives ... ignored
test add_works ... ok
test add_fails ... ok
test result: ok. 2 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
テスト モジュール
ほとんどの単体テストは、#[cfg(test)]
属性によってサブモジュールに挿入されます。
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod add_function_tests {
use super::*;
#[test]
fn add_works() {
assert_eq!(add(1, 2), 3);
assert_eq!(add(10, 12), 22);
assert_eq!(add(5, -2), 3);
}
#[test]
#[should_panic]
fn add_fails() {
assert_eq!(add(2, 2), 7);
}
#[test]
#[ignore]
fn add_negatives() {
assert_eq!(add(-2, -2), -4)
}
}
cfg
属性により、条件付きコンパイルが制御され、述語が true
の場合にのみ、それがアタッチされている内容がコンパイルされます。 test
コンパイル フラグは、コマンド $ cargo test
を実行するたびに Cargo によって自動的に発行されるため、テストの実行時に常に true になります。
add_function_tests
モジュール内のコードが外部モジュール内の add
にアクセスするには、use super::*;
宣言が必要です。
このユニットで使用されているコードは、この Rust Playground リンクで確認できます。