我喜欢Catch嵌套测试层次结构的方式,并且它通过组合工作。感觉比xUnit框架的设置/拆卸更自然。
我现在有一套测试。我想要做的是,大约一半是插入加载/保存序列化测试,然后重复该点下面的所有测试,首先没有加载/保存,然后再次使用从序列化过程加载的数据。即证明加载/保存是正确的。
如果Catch有任何可以帮助解决这个问题的话,我无法理解?如果它是phpUnit,我会考虑一串@depends
测试,并使用带有布尔输入的@dataProvider
。有点难看。
(如果这没有意义,请告诉我,我会尝试找出一个最小的例子)
答案 0 :(得分:1)
这里的问题是Catch旨在下降一个类似树的测试组织,它会自动发现结构的所有叶节点,并使用未经测试的代码路径回调测试用例,直到它们全部经过测试。叶节点(测试,部分)是独立的。
听起来你想要测试存储库 - 可以保留一些数据然后重新加载的东西。
要在两种不同的场景中重复完全相同的测试(在序列化之前,序列化之后),您需要将相同的测试放入某个常见位置并调用该位置。只要从测试用例中调用它,您仍然可以在非测试用例函数中使用相同的Catch宏。
一种可能的方法是:
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);
}
一种可能的替代方法是提供自己的main,然后使用命令行参数来控制数据是否首先被序列化。
我能想到的第三种方法是使用Catch - Generators的非常准备的功能:
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));
}
}
此方法的优点是您可以看到流程和测试运行两次(对于这两个值),但主要缺点是生成器与SECTION和BDD样式的功能不兼容。