在Qt中是否可以对单元测试(访问)私有方法进行单元测试?

时间:2011-09-12 21:23:32

标签: unit-testing qt class private-members metaobject

我正在为我的应用程序编写单元测试,现在我偶然发现了一个我应该测试私有方法的类。这可能是特定班级设计不佳的结果,但我必须这样做。有没有办法在Qt中调用私有方法,可能使用QMetaObject或类似的东西?

对于单元测试,我使用的是QTestLib框架。

5 个答案:

答案 0 :(得分:5)

正确(阅读烦人)的答案是你不应该测试私有方法,这些是实现细节;-)

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 :(得分:2)

解决方案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)来获取私有类实例,然后愉快地使用它。

答案 2 :(得分:1)

我不同意“私人成员是实施细节”的心态,在我看来,大致翻译为“只测试部分代码”。

我可以说“单位是单位”这个论点,但是为什么不尝试用尽可能多的代码覆盖你的代码,即使是在单位内?阿卡。 为您的单位提供彻底的直肠检查

考虑到这一点,我经常使用的一种方法是在其他答案中没有提及的是:

  1. 始终在代码中声明要作为protected而不是private进行测试的成员。
  2. 在测试代码中对您的类进行子类化,只需创建您需要的选择器,或者直接将测试代码直接写为该子类实现中的成员。
  3. 注意:您必须小心依赖复杂实例化模式的类,以确保正确构造它们(读取:从子类ctor调用原始类的构造函数)。

答案 3 :(得分:0)

我找到了更方便的方法来做到这一点。首先,所有私有方法都应该是私有槽。 然后创建类的实例:

Foo a;

然后我们可以使用QMetaObject :: invokeMethod来调用方法具有的任何插槽(公共或私有)。因此,如果我们想调用方法Test,我们可以这样做:

QMetaObject::invokeMethod(&a, "Test", Qt::DirectConnection);

此外,我们可以有返回值并发送参数......实际上,所有内容都在这里得到解答:http://doc.qt.nokia.com/stable/qmetaobject.html#invokeMethod

答案 4 :(得分:0)

我曾经读过Unit Test应该测试类的公共接口,而不是受保护/私有的东西。

你的班级应该从外面表现得很好。如果实施策略发生变化,您的单元测试类仍然是相同的。