Mum*_*les 93 c++ unit-testing private-methods
我正在编写一些单元测试.特别是我想测试一些私有方法.
到目前为止,我已经提出了使用.
#define private public
Run Code Online (Sandbox Code Playgroud)
但我对此并不满意,因为它会从单元测试的角度破坏所有封装.
您使用什么方法对私有方法进行单元测试.
Ant*_*ams 73
而不是#define
你在问题中提到的讨厌的黑客,一个更清洁的机制是使测试成为被测试类的朋友.这允许测试代码(以及测试代码)访问私有部分,同时保护它们免受其他一切的影响.
但是,最好通过公共接口进行测试.如果你的类X在私有成员函数中有很多代码,那么可能值得提取一个由类X的实现使用的新类Y.然后可以通过它的公共接口测试这个新的类Y,而不暴露它用于X类的客户.
jls*_*ker 61
如果您使用的是Google Test,则可以使用FRIEND_TEST轻松将您的测试夹具声明为受测试类的朋友.
而且你知道,如果像其他一些答案所说的那样测试私有函数是非常糟糕的,那么它可能不会被内置到Google Test中.
您可以在此答案中阅读有关何时测试私有函数的好坏的详细信息.
Mik*_*our 58
如果方法足够复杂以保证单独进行测试,则将它们重构为自己的类并通过其公共接口进行测试.然后在原始课堂中私下使用它们.
Man*_*j R 30
使测试类成为原始类的朋友.这个朋友的声明将在#define UNIT_TEST
旗帜内.
class To_test_class {
#ifdef UNIT_TEST
friend test_class;
#endif
}
Run Code Online (Sandbox Code Playgroud)
现在进行单元测试,您将使用flag编译代码-DUNIT_TEST
.这样您就可以测试私有函数了.
现在,您的单元测试代码将不会被推送到生产环境中,因为UNIT_TEST
标志将为false.因此代码仍然是安全的.
您也不需要任何特殊的库来进行单元测试.
小智 15
我知道这是一个较老的问题,但似乎没有人分享我喜欢的相对好的方法,所以在这里:
将要测试的方法更改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);
}
}
Run Code Online (Sandbox Code Playgroud)
当然,您必须更新单元测试以在派生类而不是基类上运行测试,但在此之后,对基类所做的任何更改都将自动反映在"testing"类中.
经过许多小时,对于那些想要测试其私有功能的人来说,这就是我决定的最佳解决方案。这是Max DeLiso和Miloš的答案的组合。
如果您使用boost :: unit-test,那么有一个简单而优雅的解决方案。
在课堂上 使用protected
代替private
/* MyClass.hpp */
class MyClass {
protected:
int test() {
return 1;
}
};
Run Code Online (Sandbox Code Playgroud)创建一个灯具:
/* 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()
Run Code Online (Sandbox Code Playgroud)这样,您可以自由使用任何MyClass
功能,而无需在班级中#define private public
添加好友!
定义黑客是一个可怕的想法.在编译它时,任意用预处理器重写代码是不明智的.
现在有几个人已经提到过,你是否应该测试私有方法是有争议的.但是,这并未涵盖您故意隐藏构造函数以限制实例化到某些范围或其他一些更深奥的案例的情况.
此外,您不能成为命名空间的朋友,并且"友谊"不会在C++中继承,因此根据您的单元测试框架,您可能遇到麻烦.幸运的是,如果你正在使用Boost.Test,那么就可以通过Fixtures的形式优雅地解决这个问题.
http://www.boost.org/doc/libs/1_52_0/libs/test/doc/html/utf/user-guide/fixture/per-test-case.html
您可以对夹具进行操作,并使其实例化您在单元测试功能中使用的所有实例,将它们声明为夹具的静态实例和模块范围.如果您正在使用命名空间,请不要担心,您可以在命名空间中声明fixture,并在命名空间之外声明测试用例,然后使用范围解析运算符来获取静态成员.
该BOOST_FIXTURE_TEST_CASE
宏将采取实例化和拆除的夹具你的照顾.