单元测试私有方法,使它们成为自由函数

时间:2018-03-28 01:22:25

标签: c++ unit-testing private-methods non-member-functions

在2017年的cppcon视频中,我遇到了Klaus Iglberger的题为“Free Your Functions!”的演讲。 在这次演讲中,演讲者谈到了如何切换到免费功能 轻松测试私有方法的过程(见19:00)。这个想法是你拉动的 类中的私有方法(你使它成为一个自由函数),它变得可以测试。

起初,我觉得这个想法很有意思,但后来却有了 我想的更多,我越不了解这实际上应该如何工作。例如, 假设我有以下(虚拟)类:

class SomeClass
{
public:
    SomeClass();
    ~SomeClass();

    void someTask();

private:

    void someComplexTask();
    void someOtherComplexTask();

};

void SomeClass::someTask()
{
    someComplexTask();
    someOtherComplexTask();
}

// private tasks implementations...

然后someComplexTask()someOtherComplexTask()是私有方法。这意味着他们 是实现细节,即它们只能在SomeClass(或朋友)内部调用。它 在我看来,如果你让它们成为自由函数,是的,它们会变得可测试,但它们不再存在 私有,也不仅仅是SomeClass特有的实施细节。实际上,可以从代码中的任何地方调用它们......

所以我的问题是:为什么Iglberger先生的观点有效?

2 个答案:

答案 0 :(得分:6)

  

这清楚地表明您存在设计缺陷。如果你有   您需要测试的私人功能,您必须向后弯曲   为了使它工作然后出了点问题。你错过了什么。   你的设计不起作用。

他的观点不仅仅是让私人职能免费。他并没有说:"获取所有私人功能并使其成为免费功能"。他说,需要测试的功能不应该是一个实现细节,因为如果你需要测试它,这表明功能是有用的。

请密切注意他对代码所做的转换:

初始代码:

class X
{
public:
 void doSomething( ... ) {
    ...
    resetValues();
    ...
 }
 ...
private:
 void resetValues() {
     for( int& value : values_ )
        value = 0;
 }
 std::vector<int> values_;
};

他从resetValues 中提取X使其在std::vector<T>上运行,而不在X上运行:

void resetValues( std::vector<int>& vec )
{
 for( int& value : vec )
   value = 0;
}

现在resetValues是一种可以重复使用和测试的功能。因为它确实与X无关,但是通过重置向量的所有值,使其成为自由函数而不是私有X方法是有效的设计。

我喜欢Rann Lifshitz在评论中所说的话:

  

我认为更好的方法是去了解一些私人   事实上,函数是常用的函数函数

答案 1 :(得分:0)

我也观看了视频。但是,我有一些分歧。

1-您的方法是否需要访问字段?如果没有,它不属于该类。但如果确实如此,他们就需要这些领域。除非将它们作为函数参数传递,否则free函数无权访问这些字段。请考虑免费功能不应被视为公共功能。

2-并非一切都应该是自由功能。但是,如果没有必要,可以避免将所有内容都放在课堂上。

3-通常不应测试私人功能。但是如果你坚持,你可能会执行诸如无效的黑客攻击(这并不总是像评论中提到的那样工作):

#define class struct
#define private public
#define protected public

#include "library.h"

#undef class
#undef private
#undef protected

释放你的功能更整洁但不太可行。