Rustのcargoでライブラリ&テスト(単体、結合)
サクッとできてしまう。
成果物
プロジェクト作成からテスト実行まで
1. プロジェクト作成
$ cargo new my_project --lib
2. ビルド
$ cargo build
じつはこの肯定は不要。次のcargo test
をやれば自動的に実行されるから。
3. 単体テスト
$ cargo test
以下のような出力を得られる。
Compiling communicator v0.1.0 (/tmp/work/communicator) Finished dev [unoptimized + debuginfo] target(s) in 3.05s Running target/debug/deps/communicator-9820f266b5f5cd1b running 3 tests test adder::tests::test_add_two ... ok test tests::it_works ... ok test tests::test_get_message ... ok test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/integration_test-1d08c00d9b209e5e running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Doc-tests communicator running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
単体テストコード
- プロジェクト/
- src/
- lib.rs
- src/
lib.rs
// 実装 fn get_message() -> String { String::from("Hello world !!") } // 単体テスト #[cfg(test)] mod tests { use super::*; #[test] fn test_get_message() { assert_eq!(get_message(), String::from("Hello world !!")); } }
Rustで単体テストするときは上記コードのように、同一ファイル内にmod tests {}
モジュールを作って書くのが慣習らしい。
上記コードの場合、pub
で公開されていない関数がテストコードで参照できている。C#など他言語ではpublicメソッドしかテストできなかったのに。書き方によってはprivateは参照できなくなる。詳細は別途pub
の項でやるためここでは省略。
use super::*;
tests
モジュール内にて、同モジュールの直上親モジュールに定義された要素すべてを展開する(接頭辞モジュール名::
なしで参照)
- 注釈(アノテーション)
#[test]
- テストコードであることを示す
#[cfg(test)]
cargo test
コマンドを実行したときだけビルドされるようになる
結合テストコード
- プロジェクト/
- src/
- lib.rs
- tests/
- integration_test.rs
- src/
integration_test.rs
extern crate クレート名; // 結合テスト #[test] fn test_get_message() { assert_eq!(クレート名::get_message(), String::from("Hello world !!")); }
クレート名
はcargo new
したときの名前を使う。
注意すべきはpub
で公開された関数しか参照できないこと。lib.rsにあるfn test_get_message()
を公開すべくpub fn test_get_message()
として定義すべき。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
$ 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のプロジェクト構造