我正在尝试在Boost Unit Testing Framework中设置依赖项。 我发现this thread tbat有一个如何使用test_unit :: depends_on()方法的例子。到目前为止这么好,我可以写一些魔法来解决它。 但是,UTF并不尊重执行期间的测试依赖性。
场景:BOOST_AUTO_TEST_CASE A在另一个(B)之前声明,并且A depends_on()B 期望的(期望的)结果:框架检测依赖性并首先运行B,然后运行A,如果B成功。 实际结果:跳过A,因为尚未运行的B已经"失败" (即没有/错误的结果)。
现在,我的想法是对测试用例/套件进行拓扑排序,然后按排序顺序运行它们。 为此,我创建了一个test_tree_visitor来遍历套件并确定m_members test_suite成员的顺序。
但是,m_members受到保护,无法通过方法访问。 因为我无法更改标题,(会使升级到更新的版本更加困难等等),以及BOOST_ *宏"硬编码"作为test_suite的类,我正在考虑以下hackery:
class member_accessible_test_suite : public test_suite
{
public:
const std::vector<test_unit_id> *get_members() const { return &m_members; }
};
class dependency_order_visitor : public test_tree_visitor
{
public:
virtual void visit( test_case const& tu)
{}
virtual bool test_suite_start( test_suite const& tu)
{
const member_accessible_test_suite *psuite(reinterpret_cast<const member_accessible_test_suite*>(&tu));
const std::vector<test_unit_id> *pmembers(psuite->get_members());
/* do something with pmembers */
return true;
}
virtual void test_suite_finish( test_suite const& tu)
{}
};
在Coliru上查看watered down version
现在问我的问题:
升级库通常设计得很好 - 由于要求使用此功能对单元测试设计存在误解,我是否犯了一个根本性的错误?
由于member_accessible_test_suite没有数据并且只添加了函数,因此reinterpret_cast()安全还是进入UB域的快速通道? 无论哪种方式,我都担心在制作中使用这样一个可怕的黑客。
是否有更好的方法,如果有,那么这会变成XY问题?
答案 0 :(得分:-1)
在处理未通过任何机制公开的基类成员时,以下方式似乎最合适(但必须访问某些关闭功能,并且不能修改基类):
链接:Access to private member variables
这个想法背后的原因可以在标准的 14.7.2p8 中找到:
通常的访问检查规则不适用于用于指定显式实例化的名称。 特别是,函数声明符中使用的模板参数和名称 (包括参数类型,返回类型和异常规范)可以是私有类型 或者通常不可访问的对象,模板可以是成员模板 或通常无法访问的成员函数。]
我冒昧地把它外包成两个宏,这些宏可能会在某一天再次派上用场。
与所有这些变通办法一样 - 明智地使用!
/* The ROB_PRIVATE_MEMBER_INST() macro should be used for explicit instantiation of the template at the appropriate source/compilation unit
The ROB_PRIVATE_MEMBER_ACCESS() macro should be used for access to the variable where required
*/
#define ROB_PRIVATE_MEMBER_INST(CLASS, TYPE, MEMBER) \
template<typename T> \
struct CLASS##_##MEMBER##_rob_tag { \
typedef T CLASS::*type; \
friend type get(CLASS##_##MEMBER##_rob_tag); \
}; \
template<typename Tag, typename Tag::type M> \
struct CLASS##_##MEMBER##_rob_private \
{ \
friend typename Tag::type get(Tag) { return M; } \
}; \
template struct CLASS##_##MEMBER##_rob_private< \
CLASS##_##MEMBER##_rob_tag<TYPE> , &CLASS::MEMBER>; \
/**/
#define ROB_PRIVATE_MEMBER_ACCESS(CLASS, INSTANCE, TYPE, MEMBER) \
(INSTANCE.*get(CLASS##_##MEMBER##_rob_tag<TYPE>())) \
/**/