我正在为我的应用程序编写单元测试,现在我偶然发现了一个我应该在其中测试私有方法的类。这可能是特定课程设计不佳的结果,但我必须这样做。Qt 中是否有任何方法可以调用私有方法,可能使用 QMetaObject 或类似的东西?
对于单元测试,我使用的是 QTestLib 框架。
我正在为我的应用程序编写单元测试,现在我偶然发现了一个我应该在其中测试私有方法的类。这可能是特定课程设计不佳的结果,但我必须这样做。Qt 中是否有任何方法可以调用私有方法,可能使用 QMetaObject 或类似的东西?
对于单元测试,我使用的是 QTestLib 框架。
正确的(读烦人的)答案是你不应该测试私有方法,那些是实现细节;-)
。
OTOH - 您是否考虑过根据您是否正在测试然后扩展,有条件地声明它们受保护/私有?我过去曾用它来摆脱类似的困境。
#ifdef TESTING
// or maybe even public!
#define ACCESS protected
#else
#define ACCESS private
#endif
/* your class here */
class Foo {
ACCESS
int fooeyness;
}
// or better yet, place this in a different file!
#ifdef TESTING
/*
class which extends the tested class which has public accessors
*/
#endif
解决方案 1,快速简单:让测试类成为公众的朋友。
class Foo {
// ...
private:
friend class FooTest;
};
这样,您的FooTest
班级就可以访问公共班级的所有成员。但是,这种方式每次您想从不同的测试访问私有数据时都需要修改原始类,并且您会在公共 API 中泄漏有关测试的信息,并且您可能会打开类命名冲突(如果有 /另一个/ FooTest 类?),等等。
解决方案2,也就是正确完成:不要将私有方法放在公共类中,而是使用公共方法创建一个私有类。
class Foo {
//
private:
friend class FooPrivate;
FooPrivate *d;
};
FooPrivate
在它自己的标头中声明,可能未安装,或保留在 include-privates/ 子目录中,或其他任何东西 - 即它不会妨碍正常使用。公开课以这种方式保持清洁。
class FooPrivate {
public:
// only public stuff in here;
// and especially this:
static FooPrivate *get(Foo *f) { return f->d; }
};
然后,测试包括私有标头和FooPrivate::get(fooObj)
获取私有类实例的调用,然后愉快地使用它。
我找到了更方便的方法来做到这一点。首先,所有私有方法都应该是私有槽。然后创建该类的一个实例:
Foo a;
然后我们可以使用 QMetaObject::invokeMethod 调用该方法拥有的任何槽(公共或私有)。所以如果我们想调用方法Test,我们可以这样做:
QMetaObject::invokeMethod(&a, "Test", Qt::DirectConnection);
此外,我们可以有返回值和发送参数......实际上,一切都在这里回答:http: //doc.qt.nokia.com/stable/qmetaobject.html#invokeMethod
我不同意“私人成员是实现细节”的心态,在我看来,这大致翻译为“只测试你的代码的一部分”。
我可以与“单位就是单位”的论点相关,但为什么不尝试用测试尽可能多地覆盖你的代码,即使是在单位内部呢?阿卡。给你的单位做一次彻底的直肠检查。
考虑到这个图像,我经常使用的一种方法在其他答案中没有提到是执行以下操作:
protected
而不是private
在代码中。注意:您必须小心依赖复杂实例化模式的类,以确保正确构造它们(阅读:从子类 ctor 调用原始类的构造函数)。
我曾经读过单元测试应该测试类公共接口,而不是受保护/私有的东西。
你的班级应该从外面表现得恰到好处。如果实施策略发生变化,您的单元测试类仍然是相同的。