假設你的榜樣的第一部分是測試的源代碼,第二部分是單元測試,那麼你就需要在如何選擇你可以這樣處理:
一些像BDE和Boost這樣的開源框架擁有自己的ASSERT宏,它可以在應用程序啓動時配置爲表現出與C斷言不同的行爲。例如,您可以指定失敗的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()異常,而不是:
void loadDataFile(FILE* input) {
if (input == NULL) {
throw std::invalid_argument("input file descriptor cannot be NULL");
}
...
}
您可以測試你的代碼強制它與合同:
REQUIRE_THROWS_AS(loadDataFile(NULL), std::invalid_argument);
這是引入異常(和需要處理他們)到你的代碼中,這是一個比你的客戶感到滿意的更大的改變 - 一些公司有一個無例外規則,一些平臺(例如嵌入式)不支持異常。
最後,如果你真的想,你可以改變代碼的接口公開合同失效:
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。
我不知道趕,但谷歌測試所謂的_death tests_。 –
你可以推出自己的'assert'宏嗎?你可以給它一個可定製的「斷言處理程序」,它會在測試項目中拋出失敗,並以其他方式終止。然後在你的測試中,你可以檢查拋出的'AssertException'。 – KABoissonneault
請檢查我的答案在這裏:https://stackoverflow.com/questions/37499284/how-to-suppress-termination-in-google-test-when-assert-unexpectedly-triggers/37503591#37503591 – deniss