C++テスティングフレームワーク: catch2のメモ

公式サイト
インサイドコードテストを書く
-
catch2/catch_test_macros.hpp
をインクルードする - TEST_CASE マクロ内にテストを書く
TEST_CASE("テストの概要をここに書く") {
// ここにテスト内容を書く
}

提供されているアサーション
See: https://github.com/catchorg/Catch2/blob/devel/docs/assertions.md
- REQUIRE( expression )
-
expression
がfalse
の場合に、テストケースをabort
- ハードアサーション
-
- CHECK( expression )
-
expression
がfalse
の場合に、後続のテストを続行する - ソフトアサーション
-
以下、XXXXにはREQUIRE
かCHECK
のいずれかがくる
- XXXX_FALSE( expression )
-
expression
がfalse
の場合にテスト失敗にする
-
- XXXX_NOTHROW( expression )
-
expression
で例外が送出されたらテスト失敗 -
expression
にはラムダ式の即時実行を記述できる。- 以下のTHROW系も同様
-
- XXXX_THROWS( expression )
-
expression
実行中に例外が送出されることを期待する
-
- XXXX_THROWS_AS( expression, exeption )
-
expression
実行中にexeption
が送出されることを期待する
-
- XXXX_THROWS_WITH( expression, string )
-
expression
実行中に例外が送出され、string
に変換される。どうゆうこと?
-
- XXXX_THROWS_MATCHES( expression, matcher )
-
expression
実行中に例外が送出される場合、matcher
で真偽を判定する -
hamcrest
みたいなやつか? - 例外用
matcher
は以下の2つ- Message( string )
- 例外メッセージで判定
- MessageMatchers( matcher )
- 文字列系またはventor系matcherを指定して判定
- Message( string )
-
- XXXX_THAT( lhs, matcher expression )

matcher
See: https://github.com/catchorg/Catch2/blob/devel/docs/matchers.md#top
複数のmatcher
を合成する場合は&&
でつなぐ
文字列Matcher
使用する場合は、catch2/matchers/catch_matchers_string.hpp
をインクルードする
文字列Matcherは名前空間Catch::Matchers
に属する
- StartsWith(std::string str, CaseSensitive)
- EndsWith(std::string str, CaseSensitive)
- ContainsSubstring(std::string str, CaseSensitive)
- Equals(std::string str, CaseSensitive)
- Matches(std::string str, CaseSensitive)
上4つは命名そのままの意味っぽい
Matches
は正規表現を指定する模様(ECMAScript互換)
Vector系Matcher
- Contains
- 指定した
vector
が存在するかどうか。多分サブセットっぽい - checks whether a specified vector is present in the result
- 指定した
- VectorContains
- 指定した1要素が存在するかどうか
- checks whether a specified element is present in the result
- Equals
- 指定した
vector
と順序も含め完全一致するかどうか - checks whether the result is exactly equal (order matters) to a specific vector
- 指定した
- UnorderedEquals
-
Equals
の順序不問版 - checks whether the result is equal to a specific vector under a permutation
-
その他
- IsEmpty()
- std::empty()がtrueとなるかどうかで判定
- SizeIs(size_t target_size)
- 範囲のサイズが同じかどうかで判定
- SizeIs(Matcher size_matcher)
- 同上
- Contains(T&& target_element, Comparator = std::equal_to<>{})
- 範囲内に指定した要素が存在するかどうか
- Contains(Matcher element_matcher)
- 同上
- AllMatch(Matcher element_matcher)
- コレクション内の全て要素がmatcherを満たすかどうか
- AnyMatch(Matcher element_matcher)
- コレクション内のいずれかがmatcherを満たすかどうか
- NoneMatch(Matcher element_matcher)
- AllMatchの逆
- AllTrue()
- コレクション内の全て要素が
true
かどうか
- コレクション内の全て要素が
- AnyTrue()
- AllTrueのany版
- NoneTrue()
- AllTrueの逆
- RangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})
- コレクション内の特定範囲のサブセットが順序も含め一致するかどうか・・・ってことかな?
- UnorderedRangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})
- RangeEqualsの順序不一致版

Qitaに記事書いた

#SECTION マクロ
SECTION
は当初、アサーションのラベル付けくらいに考えていた。
が実際はそうではなく、複数のテストセットを作るもの。
例えば
TEST_CASE("test case#1") {
SECTION("section#1") {
// (snip)
}
SECTION("section#2") {
// (snip)
}
}
とした場合、section#1
とsection#2
の二つのセクションのテストが構築され実行される。
また以下のように入れ子にした場合、
TEST_CASE("test case#2") {
SECTION("section group#1") {
SECTION("section#1") {
// (snip)
}
SECTION("section#2") {
// (snip)
}
}
SECTION("section group#2") {
SECTION("section#1") {
// (snip)
}
}
}
section group#1/section#1
、section group#2/section#1
、section group#2/section#1
のすべてのセクションの組み合わせのテストが構成され実行される。
ここで入れ子のセクション
+Arrange / Act
を使う場合は注意が必要。
例えば以下のようにセクションの外でテストハーネスのセットアップする場面を想定する。
TEST_CASE("test case#1") {
// ここでテストハーネスのセットアップ
SECTION("section#1") {
// (snip)
}
SECTION("section#2") {
// (snip)
}
}
一見、テストハーネスのセットアップが1回だけ行われるように見えるが、実際はセクションごとに実行される。
そのため、アサーションのラベルのつもりで扱うと実行時間がアホほど伸びる羽目になるので要注意。
ちなみに、複数アサーションをブロックで囲みラベル付けする方法は標準では提供されていない模様。