2010-10-08 31 views
4

假设我们有这样一个类:白盒测试 - 朋友还是预处理器?

class Testee 
{ 
public: 
    void Func() 
private: 
    void auxFunc() 
}; 

,我们希望做就可以了白盒单元测试。 你认为哪种方法更好?要将测试者类声明为被测试者类的朋友?或使用这样的预处理:

class Testee 
    { 
    public: 
     void Func() 
#ifndef UNITTEST_SYMBOL 
    private: 
#elif 
    public: 
#endif 
     void auxFunc() 
    }; 

后来在测试文件

#define UNITTEST_SYMBOL 
#include "Testee.h" 
#undef UNITTEST_SYMBOL 

所以,再一次,你认为这是一个更好的办法?或者,也许你可以提出另一种方法。

+1

或者使auxFunc一个单独上课之前我所有的其他的头文件,包括该类型的测试对象中 – 2010-10-08 12:15:37

+0

@jk私有对象:,并在auxFunc类公共所有的功能? – 2010-10-08 12:16:36

+1

如果你想测试它们,是的。可以说你不应该测试私有方法,如果你是因为复杂性,它可能是你需要拆分类http://stackoverflow.com/questions/105007/do-you-test-private-method – 2010-10-08 12:25:36

回答

4

如何:

#ifndef UNITTEST_SYMBOL 
#define semiprivate private 
#else 
#define semiprivate public 
#endif 

,并声明你的类,如:

  class Testee 
    { 
    public: 
       void Func() 
    semiprivate: 
       void auxFunc() 
    }; 

甚至,如果你足够大胆,测试时做#define private public

+0

因此,我想你赞成预处理器。你能否为此提供一些论据? – 2010-10-08 11:45:42

+2

基本上,测试代码不应该混淆正则代码。 IOW,你应该能够编写代码,就好像你不打算测试它一样。使用friend类,或者在类中添加#ifdef宏,会使与类实际代码没有直接关系的类定义混乱。 '#define private public'然后成为最理想的解决方案;然而显然这样的宏观建设在技术上是非法的,因此是“半私人的”。 – 2010-10-08 11:53:07

+0

谢谢。你清楚地表达了你的观点。 – 2010-10-08 11:59:01

1

使用friend方法,声明将取决于测试类的名称,所以如果您更改过它的名称,声明也必须更改。此外,我使用Unittest ++,因此实际的测试名称由宏形成。

然后使用define的方法就不那么麻烦了。另外,我只是把定义为一个全球性的编译器选项,而不是你带路,例如

gcc -DUNIT_TESTING_ON 

#ifdef UNIT_TESTING_ON 
    public: //or protected maybe 
#else 
    private: 
#endif 

任何阅读,这也将看到目的是什么,这比查找更清晰朋友的定义,看你为什么把它做成朋友。

2

在单元测试文件中。你可以试试

#define private public 
#include "Testee.h" 

这就是我所做的,这意味着头文件中没有任何与单元测试有关的东西。 我觉得这非常有用,因为当我的代码中有很多#ifdef时,我发现它很难遵循。

我那么有#定义

+0

是不是禁止'#define'保留关键字? – ereOn 2010-10-08 12:15:31

+3

某些编译器在修改成员函数名称时会包含访问说明符,如果您打破这样的一个定义规则,将导致链接错误。 – 2010-10-08 12:26:50

+1

它在技术上是非法的,它可能会违反规则17.4.3.1.1 C++ 03的P 2。但是在gcc和MS编译器上它可以工作。我没有找到一个编译器,这导致了任何问题。 – Mumbles 2010-10-08 12:45:26