assert_eq!
マクロや#[should_panic]
注釈など。
成果物
参考
プロジェクト作成
$ cargo new adder --lib
テスト実行
$ cd adder $ cargo test
雛形コード
#[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }
アサーション
assert!(bool)
: 真なら成功assert_eq!(T, T)
: 同一なら成功assert_ne!(T, T)
: 同一でないなら成功
エラーメッセージ
assert!
---- モジュール名::関数名 stdout ---- thread 'モジュール名::関数名' panicked at 'assertion failed: コード', ファイルパス:行:列
assert_eq!
, assert_ne!
---- モジュール名::関数名 stdout ---- thread 'モジュール名::関数名' panicked at 'assertion failed: `(left == right)` left: `4`, right: `5`', ファイルパス:行:列
追加
fn add_two(a: i32) -> i32 { a + 3 } #[cfg(test)] mod tests { use super::*; #[test] fn is_add_two_msg() { assert_eq!(4, add_two(2), "テストに失敗しましたわ。: {}", 4); } }
---- tests::is_add_two_msg stdout ---- thread 'tests::is_add_two_msg' panicked at 'assertion failed: `(left == right)` left: `4`, right: `5`: テストに失敗しましたわ。: 4', src/lib.rs:11:27
#[cfg(test)]
cargo test
コマンド実行時のみビルドする。
#[test]
テスト関数である。(cargo test
時にテストとして認識する)
#[should_panic]
pub struct Guess { value: u32, } impl Guess { pub fn new(value: u32) -> Guess { if value < 1 || value > 100 { panic!("0〜100までの整数でなければならない。: {}", value); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic] fn greater_than_100() { Guess::new(200); } }
$ cargo test ... running 1 test test tests::greater_than_100 ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
パニックしたのに強制終了されず、テスト成功としてカウントされている。これで異常系の確認もできる。
もし、panic!
をコメントアウトしたら?
// if value < 1 || value > 100 { panic!("0〜100までの整数でなければならない。: {}", value); }
テスト失敗。ログ出力をみてもよくわからない。テストコードに#[should_panic]
があるので、パニックしなかったから失敗したと予想できる。つまり、コードを見なければわからない。
running 1 test test tests::greater_than_100 ... FAILED failures: failures: tests::greater_than_100 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
#[should_panic(expected = ...)]
パニック時のメッセージを指定できる。種別が異なるパニックとは切り分けてテストできる。
pub struct Guess { value: u32, } impl Guess { pub fn new(value: u32) -> Guess { if value < 1 || value > 100 { panic!("0〜100までの整数でなければならない。: {}", value); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "0〜100までの整数でなければならない。: 199")] // #[should_panic(expected = "0〜100までの整数でなければならない。: 200")] fn greater_than_100() { Guess::new(200); } }
---- tests::greater_than_100 stdout ---- thread 'tests::greater_than_100' panicked at '0〜100までの整数でなければならない。: 200', src/lib.rs:6:39 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. note: Panic did not include expected string '0〜100までの整数でなければならない。: 199' failures: tests::greater_than_100 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
まとめ
注釈 | 意味 |
---|---|
#[cfg(test)] |
cargo test 時のみビルドする |
#[test] |
cargo test でテスト対象とする |
#[should_panic(expected = "パニック時のメッセージ")] |
パニックすべきテストである |
マクロ | 意味 |
---|---|
assert!(bool) |
引数が真ならテスト成功 |
assert_eq!(T, T) |
引数が同一ならテスト成功 |
assert_ne!(T, T) |
引数が同一でないならテスト成功 |
対象環境
- 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(ジェネリクス、トレイト境界とともに)