2016-07-22 17 views
2

assertステートメントが無効な前提条件を正しく識別していることをC++ CATCHフレームワークで確認できますか?C++キャッチフレームワークを使用してアサート文を確認する

// Source code 
void loadDataFile(FILE* input) { 
    assert(input != NULL); 
    ... 
} 

// Test code 
TEST_CASE("loadDataFile asserts out when passed NULL", "[loadDataFile]") { 
    loadDataFile(NULL) 
    // Now what do I look for? 
} 
+1

キャッチはわかりませんが、Googleテストでは_death tests_と呼ばれています。 –

+1

あなた自身の 'assert'マクロを動かすことができますか?テストプロジェクトの失敗をスローし、それ以外の場合は終了する、カスタマイズ可能な "アサートハンドラ"を与えることができます。あなたのテストでは、スローされた 'AssertException'がチェックされます。 – KABoissonneault

+0

ここで私の答えを確認してください:https://stackoverflow.com/questions/37499284/how-to-suppress-termination-in-google-test-when-assert-nexpectedly-triggers/37503591#37503591 – deniss

答えて

1

BDEBoostのようないくつかのオープンソースフレームワークは、アプリケーションの起動時にC assertとは異なる動作をするように設定できる独自のASSERTマクロを持っています。たとえば、失敗したASSERTが例外をスローするように指定することができます。次に、CatchのREQUIRE_THROWS()アサーションを使用して、コードがNULLでないFILE記述子の契約を強制していることを確認できます。

BDE例

#include <bsls_assert.h> 

void loadDataFile(FILE* input) { 
    BSLS_ASSERT_OPT(input != NULL); 
    ... 
} 

TEST_CASE("loadDataFile asserts out when passed NULL", "[loadDataFile]") { 
    // Opt-in to the 'throw exception on assert failure' handler 
    // just for this test case. 
    bsls::AssertFailureHandlerGuard guard(&bsls::Assert::failThrow); 
    REQUIRE_THROWS_AS(loadDataFile(NULL), bsls::AssertFailedException); 
} 

ブースト例

#include <boost/assert.hpp> 

void loadDataFile(FILE* input) { 
    BOOST_ASSERT(input != NULL); 
    ... 
} 

namespace boost { 
void assertion_failed(char const * expr, char const * function, char const * file, long line) { 
    throw std::runtime_error("Assertion Failed"); // TODO: use expr, function, file, line 
} 
} 

TEST_CASE("loadDataFile asserts out when passed NULL", "[loadDataFile]") { 
    REQUIRE_THROWS(loadDataFile(NULL)); 
    // Now what do I look for? 
} 

独自のassert()マクロを転がしことができます。これは車輪を再発明しています - 上記の例を参照してください。あなたが代わりにstd::invalid_argument()例外をスローするようにコードを変更することができ

REQUIRE_THROWS_AS(loadDataFile(NULL), std::invalid_argument); 

これは例外(および処理する必要性を導入している:

void loadDataFile(FILE* input) { 
    if (input == NULL) { 
     throw std::invalid_argument("input file descriptor cannot be NULL"); 
    } 
    ... 
    } 

あなたはあなたのコードは、それが契約だ強制することをテストすることができますクライアントに満足するかもしれないより大きな変化です - いくつかの企業は例外なしのルールを持っています、いくつかのプラットフォーム(例えば埋め込み)は例外をサポートしていません。

最後に、あなたは本当に、あなたが契約の失敗公開するためにあなたのコードのインターフェイスを変更する可能性がしたい場合:

enum LoadDataFile_Result { 
    LDF_Success, 
    LDF_InputIsNull, 
    ... 
}; 

LoadDataFile_Result loadDataFile(FILE* input) { 
    if (input == NULL) { 
    // bail out early for contract failure 
    return LDF_InputIsNull; 
    } 
    // input is non-NULL 
    ... 
    return LDF_Success; 
} 

を...しかし、これは、クライアントが戻り値をチェックしない固有のリスクを持っています、多くのバグの原因となり、Cのようなものが何度も繰り返されています。

2

Googleテストフレームワークに興味があるかもしれません。これは、とプログラムの異常終了をキャッチする能力があります:stderr predicate

ASSERT_DEATH(statement, regex); 
ASSERT_DEATH_IF_SUPPORTED(statement, regex); 
ASSERT_EXIT(statement, predicate, regex); 

EXPECT_DEATH(statement, regex); 
EXPECT_DEATH_IF_SUPPORTED(statement, regex); 
EXPECT_EXIT(statement, predicate, regex); 

regex一致テキストは、プログラムの終了コードと一致しました。

私はこれがアサーションの前にテストプログラムをフォークすることによって動作すると思われます。ここ

ドキュメント:あなたの例の最初のセクションでは、テスト対象のソースコードであり、第二部は、ユニットテストで、あなたはどのように選択をする必要がありますと仮定すると、

https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md

+0

@chris私の間違い。私は質問とコメントをまとめた。修正されます。 –

関連する問題