Unit testing of private methods

我正在编写一些单元测试。 我特别想测试一些私有方法。

到目前为止,我已经想出了使用。

#define private public

但是我对此并不满意,因为从单元测试的角度来看,它会破坏所有的封装。

您使用哪些方法对私有方法进行单元测试。

94318 次浏览

如果这些方法足够复杂以至于需要单独进行测试,那么就将它们重构到它们自己的类中,并通过它们的公共接口进行测试。然后在原来的课堂上私下使用它们。

与您在问题中提到的令人讨厌的 #define黑客行为不同,一种更清晰的机制是使测试成为被测类的朋友。这允许测试代码(以及仅测试代码)访问这些私有文件,同时保护它们不受其他内容的影响。

但是,最好通过公共接口进行测试。如果您的类 X 在私有成员函数中有很多代码,那么可能值得提取一个新的类 Y,该类被类 X 的实现所使用。然后可以通过其公共接口测试这个新的类 Y,而不需要将其使用暴露给类 X 的客户端。

我不认为私有方法需要单元测试用例。

If a method is private it can used only within that class. If you have tested all the public methods using this private method then there is no need to test this separately since it was used only in those many ways.

将测试类作为原始类的朋友。这个朋友声明将在 #define UNIT_TEST标志中。

class To_test_class {
#ifdef UNIT_TEST
friend test_class;
#endif
}

现在对于您的单元测试,您将编译带有 -DUNIT_TEST标志的代码。通过这种方式,您将能够测试私有函数。

现在您的单元测试代码将不会被推送到生产环境中,因为 UNIT_TEST标志将是 false。因此,代码仍然是安全的。

您也不需要任何特殊的单元测试库。

如果您正在使用 GoogleTest,那么您可以使用 FRIEND_TEST轻松地将您的测试 fixture 声明为被测类的朋友。

And you know, if testing private functions were unequivocally bad like some of the other answers were saying, then it probably wouldn't be built into Google Test.

您可以了解更多关于测试私有函数 在这个答案中的好坏的信息。

定义黑客是一个可怕的想法。在编译代码时,使用预处理器任意地重写代码是不明智的。

现在,正如一些人已经提到的,是否应该测试私有方法是有争议的。但是这并不包括有意隐藏构造函数以将实例化限制在某些范围内的情况,或者其他一些更深奥的情况。

另外,你不能加一个名称空间为好友,“友谊”在 C + + 中没有继承,所以取决于你的单元测试框架,你可能会遇到麻烦。幸运的是,如果你使用 Boost。测试中,这个问题的优雅解决方案是 Fixture。

http://www.boost.org/doc/libs/1_52_0/libs/test/doc/html/utf/user-guide/fixture/per-test-case.html

您可以将 fixture 加为好友,并让它实例化您在单元测试函数中使用的所有实例,将它们声明为静态的 fixture 和模块作用域。如果使用名称空间,不用担心,只需在名称空间内声明 fixture,在名称空间外声明测试用例,然后使用范围解析运算符获取静态成员。

BOOST_FIXTURE_TEST_CASE宏将负责为您实例化和拆分您的夹具。

我知道这是一个老问题了,但似乎没有人分享过我喜欢的相对较好的方法,所以就这样吧:

将要测试的方法从 private更改为 protected。对于其他类,该方法仍然是 private,但是现在您可以从您的基类派生一个“测试”类,该类公开您想要测试的私有功能。

这里有一个简单的例子:

class BASE_CLASS {
protected:
int your_method(int a, int b);
};


class TEST_CLASS : public BASE_CLASS {
public:
int your_method(int a, int b) {
return BASE_CLASS::your_method(a, b);
}
}

当然,您必须更新您的单元测试,以便在派生类而不是基类上运行测试,但是在此之后,对基类所做的任何更改都将自动反映在“测试”类中。

经过几个小时后,我决定对于那些想要测试其私有函数的用户来说,这是最好的解决方案。这是 Max DeLisoMilo答案的组合。

如果您正在使用 单元测试,那么有一个简单和优雅的解决方案。

  1. 在你的课堂上使用 protected而不是 private

    /* MyClass.hpp */
    
    
    class MyClass {
    
    
    protected:
    int test() {
    return 1;
    }
    };
    
  2. Create a fixture:

    /* TestMyClass.cpp */
    
    
    class F : public MyClass {};
    
    
    
    
    BOOST_FIXTURE_TEST_SUITE(SomeTests, F)
    
    
    // use any protected methods inside your tests
    BOOST_AUTO_TEST_CASE(init_test)
    {
    BOOST_CHECK_EQUAL( test(), 1 );
    }
    BOOST_AUTO_TEST_SUITE_END()
    

This way you can freely use any of the MyClass functions without #define private public or adding friends to you class!