サンプルコードで身につける: #[test] と assert! — テストの書き方
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1assert! で真偽を検証する最小のテスト
#[cfg(test)] の mod tests に #[test] 関数を置き、assert! で真偽を検証する基本形です。assert! の条件が偽になると panic してそのテストは失敗扱いになります。この実行環境では main が動くため、同じ検証を main からも呼んで通ることを確かめています。
2テスト関数を分けて意図を名前にする
1つの関数に対して、観点ごとにテスト関数を分ける例です。positive_stays と negative_becomes_positive という名前自体が仕様の説明になっており、失敗したときも「どの観点が壊れたか」が一目で分かります。cargo test はテスト関数を1つずつ実行して、関数名つきで成否を報告します。
3assert! に失敗メッセージを付ける
assert!(条件, "メッセージ", 値...) の形で、失敗時に表示される説明を添えられることを示す例です。メッセージには println! と同じ {} の埋め込みが使えるため、実際の値を含めておくと原因調査が一気に楽になります。条件だけの assert! で失敗原因が分かりにくいと感じたら、この形に育てていきます。
4条件が複雑な関数こそテストで守る
うるう年判定のように条件が入り組んだ関数は、頭の中の確認だけでは漏れが出ます。「4で割り切れる」「ただし100で割り切れる年は除く」「ただし400で割り切れる年は含む」という3つのルールを、それぞれ代表的な年で assert! に固定しています。仕様の例外ケースをテストとして書き残すのは実務の基本動作です。
5ユーザー名バリデーションのテスト
「空でない・8文字以内・空白を含まない」というユーザー名の検証関数を、正常系と拒否ケースの両面からテストする実務寄りの例です。バリデーションは仕様変更が多く、テストがないと「直したら別のケースが壊れた」が起きがちな領域です。拒否すべき入力こそ assert!(!...) で明示的に固定しておきます。