5

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

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

4

5 回答 5

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
于 2011-09-12T21:31:34.677 回答
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)获取私有类实例的调用,然后愉快地使用它。

于 2014-04-04T13:22:59.440 回答
1

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

Foo a;

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

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

此外,我们可以有返回值和发送参数......实际上,一切都在这里回答:http: //doc.qt.nokia.com/stable/qmetaobject.html#invokeMethod

于 2011-09-13T11:57:30.773 回答
1

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

我可以与“单位就是单位”的论点相关,但为什么不尝试用测试尽可能多地覆盖你的代码,即使是在单位内部呢?阿卡。给你的单位做一次彻底的直肠检查

考虑到这个图像,我经常使用的一种方法在其他答案中没有提到是执行以下操作:

  1. 始终声明要测试的成员,protected而不是private在代码中。
  2. 在测试代​​码中对您的类进行子类化,并简单地制作您需要的选择器,或者直接将测试代码编写为该子类实现中的成员。

注意:您必须小心依赖复杂实例化模式的类,以确保正确构造它们(阅读:从子类 ctor 调用原始类的构造函数)。

于 2016-07-17T13:18:33.837 回答
0

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

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

于 2014-04-04T13:11:03.793 回答