Rustでcargo testを行った時、何のテストが実行されるか
- Rustのテストに関して調べていた時に気になったので実験してみました。
例1_main.rsとlib.raがある状態
ディレクトリ構成とコード
calc_test ├ src │ ├ main.rs │ └ lib.rs ├ tests │ └ i_test.rs └ Cargo.toml
上のような構成です。続いてはコードです。(関数名が雑なのは実験ということでご容赦ください)
src/main.rs
mod lib; fn main() { let num = 5; println!("{} * 2 = {}", num, lib::mul_two(num)); } #[cfg(test)] mod tests { use super::*; #[test] fn mul_works() { assert_eq!(4, lib::mul_two(2)); } }
src/lib.rs
/// ``` /// use calc_test::mul_two; /// /// assert_eq!(2, mul_two(1)); /// ``` pub fn mul_two(num: u32) -> u32 { add(num, num) } fn add(a: u32, b: u32) -> u32 { a + b } #[cfg(test)] mod tests { use super::*; #[test] fn three_times_two() { assert_eq!(6, mul_two(3)); } #[test] fn add_two_and_two() { assert_eq!(4, add(2, 2)); } }
tests/i_test.rs
#[test] fn test_mul() { assert_eq!(4, calc_test::mul_two(2)); }
結果
cargo test
を実行すると以下のような出力が得られます。
running 2 tests test tests::add_two_and_two ... ok test tests::three_times_two ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running unittests src\main.rs (target\debug\deps\calc_test-194625f6c7806948.exe) running 3 tests test lib::tests::add_two_and_two ... ok test lib::tests::three_times_two ... ok test tests::mul_works ... ok test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running tests\i_test.rs (target\debug\deps\i_test-879837980f56faa5.exe) running 1 test test test_mul ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests calc_test running 1 test test src\lib.rs - mul_two (line 1) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.52s
- 下記4つのテストが実行されました。
例2_lib.rsがない状態
ディレクトリ構成とコード
calc_test ├ src │ ├ main.rs │ └ calc.rs ├ tests │ └ i_test.rs └ Cargo.toml
lib.rsの名前をcalc.rsに変えました。それに伴い、main.rs内を以下のように変えてます。
mod lib;
->mod calc;
lib::~;
->calc::~
結果
cargo test
を実行するとエラーになります。
error[E0433]: failed to resolve: use of undeclared crate or module `calc_test` --> tests\i_test.rs:3:19 | 3 | assert_eq!(4, calc_test::mul_two(2)); | ^^^^^^^^^ use of undeclared crate or module `calc_test`
ライブラリ(つまり`lib.rs)を外側からテストするための機能
としてあるからだと思われます。そのためlib.rs
がないと、いくらmain.rs
があってもmul_two
関数を見つけられずにエラーが出るのだと思われます。
これはThe Rust Programming Language 日本語版
にも言及があります。
これは、バイナリを提供するRustのプロジェクトに、 src/lib.rsファイルに存在するロジックを呼び出す単純なsrc/main.rsファイルがある一因になっています。 この構造を使用して結合テストは、extern crateを使用して重要な機能を用いることで ライブラリクレートをテストすることができます。 この重要な機能が動作すれば、src/main.rsファイルの少量のコードも動作し、 その少量のコードはテストする必要がないわけです。
(まぁ、これが本当かどうかを見たかったのが今回の記事のきっかけなんですけどね、笑)
追実験_i_test.rsを通るようにしてみた場合
さて、では今度はi_test.rsを以下のようにエラーにならないようにしてみます。
#[test] fn test_mul() { assert_eq!(4, 2 + 2); //assert_eq!(4, calc_test::mul_two(2)); }
この状態でcargo test
を実行した結果は以下の通りです。
running 3 tests test calc::tests::three_times_two ... ok test calc::tests::add_two_and_two ... ok test tests::mul_works ... ok test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Running tests\i_test.rs (target\debug\deps\i_test-6157c0f04bfd7328.exe) running 1 test test test_mul ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
例1で書いた4つのテストのうち、2.の「main.rs
から辿れるファイルのunittest」と4.の「(tests
ディレクトリがある場合)testディレクトリ内のファイルのtest」が実行されています。
1.の「lib.rs
から辿れるファイルのunittest」は当然として、3.の「ドキュメントテスト」が実施されないのは少し意外でした。
ちなみに、なんでlib.rs
がなくても結合テストは実施されるようになっているんだろうか、、、
lib.rsがあることが前提なら、lib.rsが無い時は結合テストは無視してくれても良さそうな気がするけど、、、