为了测试我的C ++项目,我正在使用GoogleTest框架。 通常我可以使用以下语法轻松调试失败:
EXPECT_TRUE(*statement*) << *debugMessage*;
当我使用宏EXPECT_NO_THROW(或ASSERT_NO_THROW)时,我当然也可以这样做,但我无法访问在宏本身内抛出(和捕获)的异常对象,因此 debugMessage < / em>无法告诉我任何有关它的信息。
是否可以以任何方式显示有关此异常的信息?
修改
没有任何自定义功能/宏是不可能的。
答案 0 :(得分:3)
以这种方式:
#include <exception>
#include <stdexcept>
#include <ostream>
#include <iostream> // for the test
#include <gtest/gtest.h>
namespace detail {
struct unwrapper
{
unwrapper(std::exception_ptr pe) : pe_(pe) {}
operator bool() const {
return bool(pe_);
}
friend auto operator<<(std::ostream& os, unwrapper const& u) -> std::ostream&
{
try {
std::rethrow_exception(u.pe_);
return os << "no exception";
}
catch(std::runtime_error const& e)
{
return os << "runtime_error: " << e.what();
}
catch(std::logic_error const& e)
{
return os << "logic_error: " << e.what();
}
catch(std::exception const& e)
{
return os << "exception: " << e.what();
}
catch(...)
{
return os << "non-standard exception";
}
}
std::exception_ptr pe_;
};
}
auto unwrap(std::exception_ptr pe)
{
return detail::unwrapper(pe);
}
template<class F>
::testing::AssertionResult does_not_throw(F&& f)
{
try {
f();
return ::testing::AssertionSuccess();
}
catch(...) {
return ::testing::AssertionFailure() << unwrap(std::current_exception());
}
};
TEST(a, b)
{
ASSERT_TRUE(does_not_throw([] { throw std::runtime_error("i threw"); }));
}
示例输出:
Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from a
[ RUN ] a.b
/Users/rhodges/play/project/nod.cpp:66: Failure
Value of: does_not_throw([] { throw std::runtime_error("i threw"); })
Actual: false (runtime_error: i threw)
Expected: true
[ FAILED ] a.b (1 ms)
[----------] 1 test from a (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] a.b
1 FAILED TEST
答案 1 :(得分:2)
Richard Hodges的答案的另一种方法是在测试体内使用 try-catch结构。这个解决方案来自Jeff Langr撰写的非常好的书Modern C++ Programming with Test-Driven Development。
完整的工作示例如下所示:
#include <stdexcept>
#include "gtest/gtest.h"
struct foo
{
void bar() {
throw std::runtime_error("unexpected error");
}
};
TEST(foo_test, does_not_throw)
{
foo f;
try {
f.bar();
SUCCEED();
}
catch (std::exception const & err) {
FAIL() << err.what();
}
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
输出:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from foo_test
[ RUN ] foo_test.does_not_throw
/Users/Soeren/Documents/cmakeProject/src/applications/modelTest/main.cpp(26): error: Failed
unexpected error messages
[ FAILED ] foo_test.does_not_throw (1 ms)
[----------] 1 test from foo_test (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (3 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] foo_test.does_not_throw
1 FAILED TEST
答案 2 :(得分:0)
我参加聚会有点晚了,但这是一种有效的方法:
/**
* @brief Wrap a code block with try-catch, handle exceptions thrown, print them
* into EXCEPT_STREAM and rethrow.
*/
#define PRINT_AND_RETHROW(CODE_BLOCK, EXCEPT_STREAM) try{do{ CODE_BLOCK }while(0);}catch(const std::exception& ex){ EXCEPT_STREAM << "std::exception thrown: " << ex.what() << std::endl; throw; }catch(...){ EXCEPT_STREAM << "unknown structure thrown" << std::endl; throw;}
/**
* @brief Wrap a code block with try-catch, handle exceptions thrown, print them
* into std::cerr and rethrow.
*/
#define PRINT_STDERR_AND_RETHROW(CODE_BLOCK) PRINT_AND_RETHROW(CODE_BLOCK, std::cerr)
#define EXPECT_NO_THROW_PRINT(CODE_BLOCK) EXPECT_NO_THROW(SPECTRE_PRINT_STDERR_AND_RETHROW(CODE_BLOCK))
#define ASSERT_NO_THROW_PRINT(CODE_BLOCK) ASSERT_NO_THROW(SPECTRE_PRINT_STDERR_AND_RETHROW(CODE_BLOCK))
稍后在代码中,将*_NO_THROW
替换为*_NO_THROW_PRINT
,瞧瞧。
void f(){
throw std::runtime_error{"this should be printed"};
}
TEST(test, test){
EXPECT_NO_THROW_PRINT( f(); );
}
上述测试用例的预期输出:
Running main() from /build/googletest-qXr8Ln/googletest-1.10.0/googletest/src/gtest_main.cc
Note: Randomizing tests' orders with a seed of 60645 .
[==========] Running 2 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from test
[ RUN ] test.test
std::exception thrown: this should be printed
/workspace/libasync/test/ut_executor_factory.cpp:56: Failure
Expected: try{do{ f(); }while(0);}catch(const std::exception& ex){ std::cerr << "std::exception thrown: " << ex.what() << std::endl; throw; }catch(...){ std::cerr << "unknown structure thrown" << std::endl; throw;} doesn't throw an exception.
Actual: it throws.
[ FAILED ] test.test (0 ms)
[----------] 1 test from test (0 ms total)