我在测试用例中使用了这个C ++代码来强制异常并增加覆盖率:
bool exceptionThrown(false);
try {
/* One or multiple lines of code */
} catch (std::runtime_error& e) {
std::cerr << " Exception caught: " << e.what() << "\n";
exceptionThrown = true;
}
if (exceptionThrown) {
std::cerr << " OK: Exception has been thrown\n";
} else {
std::cerr << " FATAL: Exception should have been thrown\n";
return(1);
}
可以想象,随着测试次数的增加,这段代码重复了很多,我根本不喜欢。我一直在考虑用这种方法包装这个代码的方法。宏,但我不确定这是不是一个好习惯。在这种情况下,您是否有任何建议避免代码重复?
答案 0 :(得分:2)
除了明显的问题,例如“为什么不使用谷歌测试?”和“为什么不使用升压测试框架?”等
这是一种做你想做的事情的方法: (编辑:更新以减少测试体中的输入 - 这个版本是单线程的,一个简单的修改可以使它线程安全)
#include <iostream>
#include <stdexcept>
namespace detail {
struct try_base {
virtual ~try_base() = default;
virtual const std::string& message() const = 0;
static std::unique_ptr<try_base>& last() {
struct empty : try_base {
const std::string& message() const override { return _message; }
std::string _message = "no exception";
};
static std::unique_ptr<try_base> _p = std::make_unique<empty>();
return _p;
}
bool threw() const { return _threw; }
operator bool() const { return !threw(); }
bool operator!() const { return threw(); }
bool _threw = false;
};
template<class F, class...Args>
struct try_exec
: try_base {
try_exec(F&& f, Args&&...args)
{
try {
f(std::forward<Args>(args)...);
}
catch(const std::exception& e) {
_threw = true;
_message = e.what();
}
}
const std::string& message() const override { return _message; }
std::string _message;
};
}
template<class F, class...Args>
const auto& try_exec(F&& f, Args&&... args)
{
auto& last = detail::try_base::last();
last = std::make_unique<detail::try_exec<F, Args...>>(std::forward<F>(f),
std::forward<Args>(args)...);
return *last;
}
bool report()
{
std::cout << detail::try_base::last()->message() << std::endl;
return true;
}
void example2(int x, int y)
{
using namespace std;
if (x < 6) {
throw std::logic_error("example 2 throws with "s + to_string(x) + " and " + to_string(y));
}
}
auto main() -> int
{
try_exec([] {
throw std::runtime_error("foo");
}) or report();
try_exec(&example2, 5, 4) or report();
try_exec([]{
example2(5, 4);
}) or report();
return 0;
}
预期产出;
test 1 threw: foo
test 2 threw: example 2 throws with 5 and 4
test 3 threw: example 2 throws with 5 and 4