到達点は、型チェックでは分からない業務ルールをテストすることです。前提は第07・11回です。
コンパイル成功は仕様の正しさではない
Rustは多くのメモリ上の誤りをコンパイル時に防ぎますが、送料無料の境界を5001円にしても型としては正しいままです。具体的な入力と期待結果をテストへ記録します。
cargo new test-practice --lib --edition 2024 で作り、src/lib.rsを次にします。
pub fn shipping(amount: i32) -> Result<u32, &'static str> {
if amount < 0 { return Err("negative amount"); }
Ok(if amount >= 5000 { 0 } else { 500 })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn boundary() {
assert_eq!(shipping(4999), Ok(500));
assert_eq!(shipping(5000), Ok(0));
}
#[test]
fn negative_is_rejected() {
assert_eq!(shipping(-1), Err("negative amount"));
}
}
cargo testで二つのテストが成功します。cfg(test)のモジュールはテスト時に使われます。テストは並行に実行される場合があるため、共有ファイル名やグローバルな環境変更に依存しないようにします。
テストの層を選ぶ
同じファイル内の単体テストは小さな関数や内部ロジックに向きます。testsディレクトリの統合テストは、外部利用者と同じように公開APIを使います。ドキュメント中のコードを試すdoctestも利用できます。
エラーの診断では、まず最初のコンパイルエラーを読みます。rustc --explain E0382 のように番号から説明を調べられます。実行時のpanicを調べる際はバックトレースも使えますが、ユーザー入力をpanicにする設計を正当化するものではありません。
cargo fmtとcargo clippyは一貫性や誤りの発見に役立ちます。ただし警告を消すために所有権や仕様を変えず、提案の理由を理解してから適用します。
練習と解答
練習:比較を amount > 5000 に変え、どのテストが失敗するか確認します。
解答:5000の期待値が0から500へずれるためboundaryが失敗します。型チェックだけでは見つからない境界の誤りを、仕様由来のテストが捕まえています。元へ戻して成功を確認します。
公式資料
Rust全20回の目次 | 前の回 | 次の回