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
へのテストは書けない。
裏を返せば、必要な処理はすべてライブラリにぶち込むべき。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- rustc 1.34.2 (6c2484dc3 2019-05-13)
- cargo 1.34.0 (6789d8a0a 2019-04-01)
$ uname -a Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux
前回まで
- Rustを学んでみたい(プログラミング言語)
- Rustの環境構築
- RustでHelloWorld
- Rustの和訳ドキュメント
- Cargoでプロジェクト作成・ビルド・実行
- クレートとは?
- Rustで関数を使ってみる
- Rustでモジュールを使ってみる
- Rustで乱数を生成する(rand)
- Rustで標準入力する(std::io::stdin().read_line())
- RustでMatch判定する(match)
- Rustでprintとread_lineを1行にする方法
- Rustで数当てゲーム
- クレート名にドット.が使えない
- Rustの変数と可変性(let, mut) error[E0384]: cannot assign twice to immutable variable
x
- Rustのimmutable束縛とconst定数の違い
- RustのREPL、evcxrのインストールに失敗した
- Rustでコンパイルするときの変数未使用warningを消す
- Rustの変数(再代入、再宣言(シャドーイング))
- Rustのシャドーイングについて
- イミュータブルについて(副作用)
- Rustの定数(const)
- Rustのデータ型(数値)
- Rustのデータ型(論理)
- Rustのデータ型(文字)
- Rustのデータ型(タプル)
- Rustのデータ型(配列)
- Rustの関数
- Rustのif式
- Rustのくりかえし文(loop)
- Rustのくりかえし文(while)
- Rustのくりかえし文(for)
- Rustの所有権(ムーブ)
- Rustの所有権(関数)
- Rustの所有権(スライス)
- Rustの構造体(定義とインスタンス化)
- Rustの構造体(プログラム例)
- Rustの構造体(メソッド)
- Rustの列挙型(enum)
- Rustの列挙型(enum)
- Rustの列挙型(enum)
- Rustのmatch(制御フロー演算子)
- RustでNULLを扱う(Option, Some, None)
- NULL参照は10億ドルの失敗だった
- Rustの列挙型に独自表示を実装する(E0277 対策 std::fmt::Display 実装)
- RustのIfLet(matchの糖衣構文)
- Rustのプロジェクト構造
- Rustのcargoでライブラリ&テスト(単体、結合)
- Rustのモジュール(mod)
- Rustのモジュール(pub)
- Rustのmod参照方法(
mod 子モジュール名;
,use 要素名;
,extern crate クレート名;
,super
) - Rustのインポートまとめ(Rust2018)
- RustのコレクションVec型
- RustのコレクションString型
- RustのコレクションHashMap型
- Rustのコレクション(練習問題)
- Rustのエラー処理
- Rustのジェネリクス
- Rustのトレイト
- Rustのライフタイム1
- Rustのライフタイム2(構造体の定義)
- Rustのライフタイム3(ライフタイム省略)
- Rustのライフタイム4(impl定義)
- Rustの静的ライフタイム5('static)
- Rustのライフタイム6(ジェネリクス、トレイト境界とともに)
- Rustのテストコードを書く
- Rustのテスト実行