我能保证使用 Catch 执行多个TEST_CASE
的顺序吗?我正在使用LLVM测试一些代码,它们有一些卑鄙的全局状态,我需要显式初始化。
现在我有一个这样的测试用例:
TEST_CASE("", "") {
// Initialize really shitty LLVM global variables.
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeNativeTarget();
llvm::InitializeAllAsmParsers();
// Some per-test setup I can make into its own function
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile...));
CHECK_NOTHROW(Interpret(...));
CHECK_THROWS(Compile(...));
CHECK_THROWS(Compile(...));
}
我想要的是将其重构为三个TEST_CASE
,
- 一个用于应通过编译的测试,
- 一个用于应该失败的测试,以及
- 一个用于应该通过解释的测试(将来,也许会进一步进行此类划分)。
但是我不能简单地将测试内容移动到另一个TEST_CASE
因为如果在设置不方便的全局变量之前调用该TEST_CASE
,那么它们就不会被初始化,测试将虚假失败。
我有点晚了,因为我刚刚看到它 - 对不起(如果合适,将来您可以将 Catch 相关问题发布到 Catch 论坛或 GitHub 上的问题列表。
无论如何 - 我不知道你最后做了什么,但在这种情况下,听起来你只是想将每组断言分组到SECTION
s。
TEST_CASE() {
// Initialize really shitty LLVM global variables.
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeNativeTarget();
llvm::InitializeAllAsmParsers();
SECTION( "should pass compilation" ) {
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile...));
}
SECTION( "should pass interpretation" ) {
CHECK_NOTHROW(Interpret(...));
}
SECTION( "Should fail compilation" ) {
CHECK_THROWS(Compile(...));
CHECK_THROWS(Compile(...));
}
}
然后,每个部分都像一个嵌入式测试用例(整个测试用例从一开始就执行 - 通过所有初始化 - 对于每个部分)。因此,如果其中一个无投掷抛出,它不会阻止其他部分执行。
。除非初始化代码只执行一次 - 在这种情况下,您可以按照@paddy建议的那样放入静态初始化器(在其构造函数中调用初始化器的类 - 然后只需创建一个全局实例) - 或者您可以使用静态布尔值上的 if 保护初始化代码块。
如果 Phil 的解决方案由于某种原因不适合,这里有一个替代方案:
struct TestFixture {
static bool _initialised;
TestFixture() {
if (!_initialised) {
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeNativeTarget();
llvm::InitializeAllAsmParsers();
_initialised = true;
}
}
};
bool TestFixture::_initialised = false;
TEST_CASE_METHOD(TestFixture, "should pass compilation" ) {
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
CHECK_NOTHROW(Compile(...));
}
TEST_CASE_METHOD(TestFixture, "should pass interpretation" ) {
CHECK_NOTHROW(Interpret(...));
}
TEST_CASE_METHOD(TestFixture, "Should fail compilation" ) {
CHECK_THROWS(Compile(...));
CHECK_THROWS(Compile(...));
}
在此示例代码中,哪个TEST_CASE先运行并不重要,因为第一次运行将调用 llvm 初始化函数,而其他将由于布尔值而跳过此操作。
这段代码利用了 Catch 的测试夹具支持,我们在日常工作中广泛使用了它:https://github.com/philsquared/Catch/blob/master/docs/test-fixtures.md