やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustのテスト体系化

 単体テスト結合テスト

成果物

参考

Rustのテスト

テスト 所在 概要
単体テスト ライブラリ内(src/lib.rs配下) 1回に1モジュールをテストする。非公開インタフェースも可。
結合テスト ライブラリ外(src/tests/配下) ライブラリ外との連携テスト。公開インタフェースのみ。1回に複数モジュール使うことも。

単体テスト

 src/lib.rsで呼び出す。

$[cfg(test)]

 cargo testコマンドを実行したときだけビルドする(cargo build時はしない)。

非公開な関数のテスト

src/lib.rs

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));
    }
}

 言語によっては公開関数しかできない。Rustはできる。

結合テスト

testsディレクト

 Rustの結合テストsrc/tests/ディレクトリ配下に書く。src/lib.rsではないため、ライブラリ外となる。

tests/integration_test.rs

#[test]
fn it_adds_two() {
    assert_eq!(4, test_sys_0::add_two(2));
}

 なお、上記はRust2018のみ可。Rust2015なら以下のように書く必要がある。(extern crate 自クレート名) ドキュメントには書いてなかった。

extern crate adder;

#[test]
fn it_adds_two() {
    assert_eq!(4, adder::add_two(2));
}

 RustのバージョンはCargo.tomlで指定する。[package]セクションのeditionキー値に2018と指定する。私の環境ではデフォルトでそうなっていた。

[package]
name = "自クレート名"
version = "0.1.0"
authors = ["GitHub_Username <GitHub_Email>"]
edition = "2018"

テスト実行

 単体テスト同様cargo testで行う。以下、単体と結合を含むコードのテスト結果。

$ cargo test
   Compiling test_sys_0 v0.1.0 (/tmp/work/Rust.Test.Systematization.20190701080709/src/1/test_sys_0)
    Finished dev [unoptimized + debuginfo] target(s) in 2.94s
     Running target/debug/deps/test_sys_0-2a725cc47b7b95e7

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-86d9649b743776b5

running 1 test
test it_adds_two ... ok

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

   Doc-tests test_sys_0

running 0 tests

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

特定の結合テスト関数のみ実行

$ cargo test it_adds_two

特定の結合テストファイルのみ実行

$ cargo test --test integration_test

結合テストでない関数をつくる

  • クレート/
    • src/
    • tests/
      • integration_test.rs
      • common/
        • mod.rs

tests/common/mod.rs

pub fn setup() {
    // ここにライブラリテスト固有のコードが来る
}

tests/integration_test.rs

mod common;
#[test]
fn it_adds_two() {
    common::setup();
    assert_eq!(4, adder::add_two(2));
}

main.rsはテスト不可

 Rustが参照できるのはlib.rs, Cargo.tomlに定義されたクレートのみ。つまりmain.rsへのテストは書けない。

 裏を返せば、必要な処理はすべてライブラリにぶち込むべき。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで