Ioa*_*ana 8 c++ boost unit-testing
我写了这个非常琐碎的课程,以便清楚我的问题是什么:
class A
{
public:
int x;
A(int y) {x=y;}
bool operator==(const A &other) const {return x==other.x;}
};
Run Code Online (Sandbox Code Playgroud)
现在,如果我定义A first(1)和A second(1),那么BOOST_CHECK_EQUAL(第一个,第二个)应该通过似乎很自然.然而,当我尝试这样做时,我得到了50个错误,第一个听起来像:没有数学运算符<<在ostr << t这是升级代码中的某个地方...其他测试工作正常,比较已知类型甚至指针,但是类对象似乎发生了一些不同的事情.
Joh*_*ing 22
我已经确定了三种解决问题的方法operator<<.
第一种方法是operator<<为您的类型提供.这是必需的,因为当boost_check_equal失败时,它还通过调用operator<<对象来记录失败.请参阅休息后的详细附录,了解这是如何实现的.它比看起来更难.
第二种方法是不做我刚刚提到的日志记录.你可以通过#definineing 来做到这一点BOOST_TEST_DONT_PRINT_LOG_VALUE.要仅针对一个测试禁用日志记录,您可以使用此方法围绕相关测试#define,然后立即#undef:
#define BOOST_TEST_DONT_PRINT_LOG_VALUE
BOOST_CHECK_EQUAL (first, second);
#undef BOOST_TEST_DONT_PRINT_LOG_VALUE
Run Code Online (Sandbox Code Playgroud)
第三种方法是operator<<通过不将一个项目与另一个项目进行比较来回避对您的类型起作用的需要,而只是检查一个bool:
BOOST_CHECK (first == second);
Run Code Online (Sandbox Code Playgroud)
选择您喜欢的方法.
我的偏好是第一个,但实施这一点令人惊讶地具有挑战性.如果您只是定义一个operator<<全局范围,它将无法工作.我认为这是因为名称解析问题.一种流行的建议,以解决这个问题是把operator<<在std命名空间.这至少在某些编译器的实践中是有效的,但我不喜欢它,因为标准禁止向std命名空间添加任何东西.
我发现一个更好的方法是print_log_value为您的类型实现自定义类模板特化. print_log_value是Boost.Test内部的类模板useb,实际上operator<<为指定的类型调用了正确的.它委托一个operator<<人去做繁重的工作.专业print_log_value的自定义类型由Boost [需要引证]正式支持,并且因此完成.
假设你的类型被称为Timestamp(这是在我的代码),首先定义一个全局免费operator<<为Timestamp:
static inline std::ostream& operator<< (std::ostream& os, const Mdi::Timestamp& ts)
{
os << "Timestamp";
return os;
}
Run Code Online (Sandbox Code Playgroud)
...然后print_log_value为它提供专业化,委托给operator<<你刚刚定义的:
namespace boost { namespace test_tools {
template<>
struct print_log_value<Mdi::Timestamp > {
void operator()( std::ostream& os,
Mdi::Timestamp const& ts)
{
::operator<<(os,ts);
}
};
}}
Run Code Online (Sandbox Code Playgroud)
这是对 John Dibling出色回答的补充。问题似乎是在正确的命名空间中需要有一个输出运算符。因此,如果您定义了全局输出,那么您可以通过在命名空间中定义另一个转发到全局运算符的operator<<错误来避免此错误(至少对于 Visual Studio 2015,又名 vc14 和 boost 1.60) 。boost::test_tools::tt_detail这一微小的调整使人们能够避免该类的奇怪且更冗长的专门化print_log_value。这是我所做的:
namespace boost {
namespace test_tools {
namespace tt_detail {
std::ostream& operator<<(std::ostream& os, Mdi::Timestamp const& ts)
{
return ::operator<<(os, ts);
}
} // namespace tt_detail
} // namespace test_tools
} // namespace boost
Run Code Online (Sandbox Code Playgroud)
虽然这个问题和答案已经发布三年了,但我还没有在Boost.Test 文档中看到对此进行清楚的讨论。