2

我可以用CatchTEST_CASE保证多个s的执行顺序吗?我正在使用 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在设置不方便的全局变量之前调用它,那么它们将不会被初始化并且测试将虚假地失败。

4

2 回答 2

4

我对此有点晚了,因为我才看到它 - 抱歉(如果合适的话,将来您可以将 Catch 相关问题发布到Catch 论坛或GitHub 上的问题列表。

无论如何 - 我不知道你最后做了什么,但在这种情况下,听起来你只是想将每组断言分组到SECTIONs.

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 来保护初始化代码块。

于 2014-05-26T15:35:05.100 回答
2

如果 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 初始化函数,而其他的将由于 bool.

此代码利用了 Catch 的测试夹具支持,我们在日常工作中广泛使用:https ://github.com/philsquared/Catch/blob/master/docs/test-fixtures.md

于 2015-07-09T19:33:45.950 回答