テスト
さて,push
と pop
を書き終えたので,次は書いたコードを実際にテストしてみましょう!
Rust と cargo は,ファーストクラスの機能としてテストをサポートしているので,これは非常に簡単です.
関数を書いて,#[test]
というアノテーション (注釈) を付けるだけでいいんです.
一般的に,Rust コミュニティではテストはテストされるコードの隣におくのが慣習です.
しかし「本当の」コードとの衝突を避けるために,通常テスト用に新しい名前空間を作ります.
first.rs
が lib.rs
に含まれるよう指定するために mod
を使いましたが,
mod
はインラインで全く新しいファイルを作成することにも使用することができます.
// in first.rs
mod test {
#[test]
fn basics() {
// TODO
}
}
cargo test
コマンドで呼び出します.
> cargo test
Compiling lists v0.1.0 (/Users/ABeingessner/dev/temp/lists)
Finished dev [unoptimized + debuginfo] target(s) in 1.00s
Running /Users/ABeingessner/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));
// 何も破損していないことを確かめるために,さらに要素をプッシュする
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`
おっと.新しいモジュールを作ったので,リストを使うには明示的にそれを引き込む必要があります.
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/ABeingessner/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
やった!
しかし,super::List
が使用されていないという警告が出ているのは,どういうことでしょう…?
どう考えてもテストの中で使ってますよね.
…テストの時だけですけどね! コンパイラを喜ばせるために(そしてユーザに優しくするために)テストを実行する時だけ,テストモジュールをコンパイルするように指示する必要があります.
#[cfg(test)]
mod test {
use super::List;
// 他は全部同じ
}
これでテストは完璧です!