ここでの問題は、Catch がテストのツリーのような組織をたどるように設計されており、構造のすべてのリーフノードを自動的に検出し、すべてのテストが完了するまで、テストされていないコード パスを使用してテスト ケースにコールバックすることです。リーフ ノード (テスト、セクション) は独立していることを意味します。
リポジトリをテストしたいようです-データを永続化してからロードできるもの。
2 つの異なるシナリオ (シリアル化前、シリアル化後) でまったく同じテストを繰り返すには、同じテストを共通の場所に配置し、その場所を呼び出す必要があります。テスト ケースから呼び出す限り、テスト ケース以外の関数でも同じ Catch マクロを使用できます。
これを行う 1 つの可能な方法は次のとおりです。
struct TestFixture {
Data data;
Repository repository;
TestFixture() : data(), instance() { }
};
void fillUpData(Data& data) {
// ...
}
void isDataAsExpected(Data& data) {
// Verify that 'data' is what we expect it to be, whether we
// loaded it or filled it up manually
SECTION("Data has ...) {
REQUIRE(data...);
}
}
TEST_CASE_METHOD(TestFixture, "Test with raw data") {
fillUpData(data);
isDataAsExpected(data);
REQUIRE(repository.save(data));
}
TEST_CASE_METHOD(TestFixture, "Operate on serialised data") {
REQUIRE(repository.load(data));
isDataAsExpected(_data);
}
考えられる代替手段の 1 つは、独自のメインを提供し、コマンドライン引数を使用して、データを最初にシリアル化するかどうかを制御することです。
Catch - Generators のまだ準備ができていない機能を使用する、私が考えることができる 3 番目の方法があります。
TEST_CASE("...") {
using Catch::Generators;
int iteration(GENERATE(values(0, 1)));
const bool doSave(iteration == 0);
const bool doLoad(iteration == 1);
Repository repository;
Data data;
if (doLoad) {
REQUIRE(repository.load(data));
} else {
// fill up data
}
REQUIRE(..data..test..);
if (doSave) {
REQUIRE(repository.save(data));
}
}
この方法の利点は、フローとテストが 2 回 (2 つの値に対して) 実行されることを確認できることですが、主な欠点は、ジェネレーターが SECTION および BDD スタイルの機能と互換性がないことです。