Charaken 技術系ブログ

技術系に関して学んだことや、気になったことを記事にしていく。

【Rust】がばがばRust独学 - 11. Tests - 3 Test Organization

f:id:charaken:20191223210559p:plain

Rustの公式ドキュメントを通して、Rustを独学していく記事になります。(がば要素あり)

doc.rust-lang.org

今回も、Testについて学びつつ、気になった点をコード確認した結果を記事にしています。

  • versions
$ rustc --version
rustc 1.40.0 (73528e339 2019-12-16)


Test Organization

Test Organization - The Rust Programming Language

両方の種類のテストを作成することが、ライブラリを期待通りに動作させるために重要とのことです。

Unit Tests

#[cfg(test)] アノテーションcargo test 時にのみ実行され、 cargo build 時には実行されないため、Integration Testsに比べてコンパイルタイムが短縮可能です。

また、private functionについてもテストすることが可能です。

pub fn add_two(a: i32) -> i32 {
    internal_adder(a, 2)
}

fn internal_adder(a: i32, b: i32) -> i32 {
    a + b
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn internal() {
        assert_eq!(4, internal_adder(2, 2));
    }
}
running 1 test
test tests::internal ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Integration Tests

tests/xxx.rs としてテストを記述することが可能です。

これにより、ライブラリのパブリックAPIのテストが可能になります。

例えば、公式ドキュメントのデモコード(Test Organization - The Rust Programming Language)を利用した場合、

use demo_test_organization;

#[test]
fn it_adds_two() {
    assert_eq!(4, demo_test_organization::add_two(2));
}
$ cargo test
    Finished test [unoptimized + debuginfo] target(s) in 0.00s
     Running target/debug/deps/demo_test_organization-ead944c9e6e8c86e

running 1 test
test tests::internal ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/integration_test-dc19df7dcdc5b51f

running 1 test
test it_adds_two ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests demo_test_organization

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

上記のようにテストすることが可能です。

また、Integration Testの単一テストファイルだけをテストしたい場合は、 --test オプションを利用することによって実行可能です。

$ cargo test --test integration_test
    Finished test [unoptimized + debuginfo] target(s) in 0.00s
     Running target/debug/deps/integration_test-dc19df7dcdc5b51f

running 1 test
test it_adds_two ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
テスト時のサブモジュール

テスト用のサブモジュールを利用する場合、サブモジュールとして tests/common.rs のように直下に配置してしまった場合は、 cargo test の中に含まれてしまいます。

そのため、 tests/common/mod.rs としてモジュール化し、

mod common;

と対象のテストファイルに記述することによって、サブモジュールとしての利用が可能になります。


まとめ

github.com

  • unit testsユニットテスト
  • integration tests (統合テスト)
    • tests 配下にファイルを格納することによってテストが可能
    • サブモジュール利用の場合は、 test/xxx/mod.rs とすることによってモジュール可能
      • mod xxx; をテストコードに記述することにより、モジュールを利用可能

最後に

Unit Testによって、srcが長くなってしまいそうだなぁというのが正直な感想です。

ただ、他言語の場合、単体テストが乱雑に配置されるパターンも往々にあるため、単体テストがしやすい状態ではあるかもしれないです。

大規模開発になった場合、ビジネスロジックが肥大化して、さらに単体テストで圧迫するなどが考えられますね・・・

次回は、I/Oになります。