Rustのテスト方法のメモ。
|
Rustでは、テストコードを記述・実行することが出来る。
(JavaのJUnit相当)
Rustでテストコードを書く場所は、テスト対象のソースファイルの末尾にするのが一般的なようだ。
ソースファイルの末尾にテスト用のモジュールを作る。
テスト用のモジュール名は何でもいいようだが、慣例としてtestやtestsとする。
テスト用モジュールには#[cfg(test)]属性を付ける。
それぞれのテスト関数には#[test]属性を付ける。
〜 #[cfg(test)] mod test { use super::*; #[test] fn テスト関数1() { 〜 } #[test] fn テスト関数2() { 〜 } … }
テストのみで使用したい構造体や関数等は、(テスト対象コードのuse文とは別に、)テスト用モジュールのブロックの中でuse文を記述してインポートする必要がある。
大抵はテスト対象の構造体や関数を呼び出すだろうから、「use super::*
」でインポートしておくと便利。
(テストコードはテスト用モジュールにあり、テスト対象とは異なるモジュールとなるので、テスト対象をインポートする必要がある)
テスト関数の戻り型を指定することは出来ない。(Resultに出来ると便利なのだが…)
テスト関数の中身は、処理を実行して、結果をassert_eq!マクロ等で確認することになるだろう。
テストが実行される順序は不定。(しかも、cargo testのデフォルトでは、複数スレッドで並列実行される)
テスト全体の前処理や後処理を記述することは出来ないので、各テストで完結する必要がある。
非同期処理(asyncのついた関数)を呼び出してテストしたい場合は、tokio::testを使う。
#[tokio::test] async fn 非同期テスト() { 〜awaitを使った非同期処理呼び出し〜 }
use tokio::test; #[test] async fn 非同期テスト() { 〜awaitを使った非同期処理呼び出し〜 }
テストはCargoを使って実行する。
cargo test 〔オプション〕〔テスト名〕〔-- 引数…〕
テスト名を指定すると、その名前を含むテストが実行される。(テスト名は、テスト関数が属しているモジュール名も含む)
テスト名を省略すると、全テストが実行される。
WindowsのコマンドプロンプトやLinux(bash)では、テスト名に「""
」を指定すると全テストが実行される。
(WindowsのPowerShellでは「""
」は引数として認識してくれない模様)
ヘルプによると、「--」の後ろに引数が書けることになっている(テスト名は「--」の前に指定するように見える)が、実際はハイフン「-」で始まらない一番最初の引数がテスト名として扱われるようだ。
テスト関数の中でprintln!やeprintln!マクロによって出力されたメッセージは、 デフォルトではテスト実行時に表示されない。
「--」の後ろに「--nocapture」を付けると、メッセージがコンソールに出力されるようになる。
cargo test 〔オプション〕〔テスト名〕 -- --nocapture
cargo testのデフォルトでは、テストは複数スレッドで実行される。[2025-02-01]
「--」の後ろに「--test-threads=スレッド数」を付けると、スレッド数が指定できる。
1にすれば1スレッドで実行される。
cargo test 〔オプション〕〔テスト名〕 -- --test-threads=1
テスト関数の中でstd::env::args()を使って、cargo
testの引数を受け取ることが出来る。
cargo testコマンド関連以外の引数が全部取得できるので、自前のキーワードを定義してそれを探すようにすれば、独自のパラメーターを受け渡すことが出来る。
#[test] fn arg_test() { let args: Vec<String> = std::env::args().collect(); let my_arg /*Option<String>*/ = args .iter() .find(|arg| arg.starts_with("my_arg=")) .and_then(|arg| arg.split_once('=').map(|(_, value)| value.to_string())); println!("my_arg={:?}", my_arg); }
cargo test "" -- --nocapture my_arg=abc