テスト
さて、push と pop を書けたので、これで実際にスタックをテストできます! Rust と cargo はテストを第一級の機能としてサポートしているので、これはとても簡単です。必要なのは、関数を書いて、それに #[test] を付けるだけです。
一般に、Rust コミュニティでは、テストはそのテスト対象のコードの近くに置くようにしています。ただし通常は、「本物の」コードと衝突しないように、テスト用に新しい名前空間を作ります。first.rs を lib.rs に含めることを指定するために mod を使ったのと同じように、mod を使って、基本的には新しいファイル全体をインラインで作成できます。
// first.rs 内
mod test {
#[test]
fn basics() {
// TODO
}
}
そして、cargo test で実行します。
> cargo test
Compiling lists v0.1.0 (/Users/ADesires/dev/temp/lists)
Finished dev [unoptimized + debuginfo] target(s) in 1.00s
Running /Users/ADesires/dev/lists/target/debug/deps/lists-86544f1d97438f1f
running 1 test
test first::test::basics ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
; 0 filtered out
やった、何もしないテストが通りました! では、何もしないテストではなくしましょう。それには assert_eq! マクロを使います。これは特別なテスト用の魔法ではありません。やっていることは、渡した 2 つのものを比較し、一致しなければプログラムをパニックさせるだけです。そう、テストハーネスには、パニックを起こすことで失敗を示すのです!
mod test {
#[test]
fn basics() {
let mut list = List::new();
// 空のリストが正しく振る舞うことを確認
assert_eq!(list.pop(), None);
// リストに要素を入れる
list.push(1);
list.push(2);
list.push(3);
// 通常の削除を確認
assert_eq!(list.pop(), Some(3));
assert_eq!(list.pop(), Some(2));
// 何も壊れていないことを確認するため、さらにいくつか push する
list.push(4);
list.push(5);
// 通常の削除を確認
assert_eq!(list.pop(), Some(5));
assert_eq!(list.pop(), Some(4));
// 使い切った状態を確認
assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), None);
}
}
> cargo test
error[E0433]: failed to resolve: use of undeclared type or module `List`
--> src/first.rs:43:24
|
43 | let mut list = List::new();
| ^^^^ use of undeclared type or module `List`
おっと! 新しいモジュールを作ったので、List を使うには明示的に取り込む必要があります。
mod test {
use super::List;
// それ以外はすべて同じ
}
> cargo test
warning: unused import: `super::List`
--> src/first.rs:45:9
|
45 | use super::List;
| ^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
Finished dev [unoptimized + debuginfo] target(s) in 0.43s
Running /Users/ADesires/dev/lists/target/debug/deps/lists-86544f1d97438f1f
running 1 test
test first::test::basics ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
; 0 filtered out
やった!
でも、あの警告はどういうことでしょう……? テストの中で明らかに List を使っています!
……ただしテスト時だけです! コンパイラを納得させるために(そして利用者に親切にするために)、test モジュール全体はテストを実行している場合にのみコンパイルされるべきだと示す必要があります。
#[cfg(test)]
mod test {
use super::List;
// それ以外はすべて同じ
}
テストについてはこれで全部です!