Rustのユニットテストは、組み込みマクロ、特殊属性、cargoのインフラストラクチャを通じて言語に組み込まれています。歴史的に、Cや他のいくつかの言語ではテストは外部の追加機能であり、これにより本番コードとテストとのインターフェースが異なることがよくあります。しかし、Rustではテストは主要なコードと同じ環境でコンパイルされ、実行されるため、「テストだけで動く」問題を解消しています。
問題: テストはビルドを遅くしたり、情報が少なかったり、悪く構成されている可能性があります。また、十分に分離されていないテストはコードのメンテナンスや可読性を妨げます。
解決策: テストは#[test]属性でマークされた特別な関数としてmod testsモジュール内に書かれます。すべてのテストコードはcargo testキーを使用してコンパイルされ、実行され、本番ビルドからは除外されます。assert_eq!、should_panicなどのマクロやセットアップメソッドは、テストの効率とクリーンさを高めるために使用されます。
コードの例:
pub fn add(a: i32, b: i32) -> i32 { a + b } #[cfg(test)] mod tests { use super::*; #[test] fn test_add() { assert_eq!(add(2, 2), 4); } }
主な特徴:
cargo testでビルドしたときのみコンパイルされ、リリースバイナリには含まれないテストを必ずmod tests内にのみ置く必要がありますか?
必ずしも必要ではありませんが、テストを隔離するためやリリース時のテストコードの漏れを防ぐために一般的に行われます。また、#[cfg(test)]を使用するのにも役立ちます。
特定のモジュール/ファイルのテストだけを実行することはできますか?
はい、cargo test テスト名を使用してテストの名前やパスを指定できます。
プライベート関数はテストされますか?
はい、テストモジュールが同じファイル内に定義され、use super::*;を使用することで、テストはそのファイル内のすべての内部関数にアクセスできます。
#[cfg(test)]なし)assert_eq!の不使用または過剰に複雑な検証テストはメインコードと混在しており、#[cfg(test)]に隠れておらず、グローバル変数によって初期化されています。
利点:
欠点:
テストは入れ子モジュールにカプセル化されており、テストの検証にはセットアップ関数とassert_eq!マクロが使用されています。
利点:
欠点: