2

CatchTEST_CASEで複数の s の実行順序を保証できますか? LLVM を使用していくつかのコードをテストしていますが、明示的に初期化する必要があるいくつかの卑劣なグローバル状態があります。

現在、次のようなテスト ケースが 1 つあります。

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(...));
}

私が望むのは、それを 3 つにリファクタリングすることですTEST_CASE

  • 1 つはコンパイルに合格する必要があるテスト用で、
  • 1 つは失敗するはずのテスト用であり、
  • 1つは解釈に合格する必要があるテスト用です(将来的には、おそらくそのような分割がさらに行われるでしょう)。

しかし、不便なグローバルを設定する前にTEST_CASEそれが呼び出された場合、それらは初期化されず、テストは誤って失敗するため、単純にテスト内容を別の内容に移動することはできません。TEST_CASE

4

2 に答える 2

4

ちょうど見たばかりなので、これには少し遅れています - 申し訳ありません(将来的には、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(...));
    }
}

各セクションは、埋め込まれたテスト ケースのように機能します (テスト ケース全体が最初から実行され、各セクションのすべての初期化が行われます)。したがって、非スローのいずれかがスローされても、他のセクションの実行が妨げられることはありません。

...初期化コードを1回だけ実行する必要がある場合を除きます-その場合、@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 のためにこれをスキップするため、最初に実行される TEST_CASE は問題ではありません。

このコードは、Catch の Test Fixture サポートを利用しています。これは、私の日常の仕事で広く使用されています: https://github.com/philsquared/Catch/blob/master/docs/test-fixtures.md

于 2015-07-09T19:33:45.950 に答える