C++類的完美單元測試方案——基於C++11擴充套件的friend語法
版權相關宣告:本文所述方案來自於《深入理解C++11—C++11新特性解析與應用》(Michael Wong著,機械工業出版社,2016.4重印)一書的學習。
專案管理中,C語言工程做單元測試用例直接寫就可以了,對於C++語言工程,曾經聽到過“C++類的私有成員在外部無法訪問沒法寫啊,就測測介面吧?”,對於專案管理人員與開發人員,作為C/C++語言使用者的你是否也有過這種煩惱?
提案“單元測試用例以私有成員函式的形式寫在被測類的裡面,通過預處理巨集開關,使得釋出時不讓單元測試編譯連結進去”,方案在語法上可以,而且也沒有破壞封裝性,但是測試用例的量很龐大跟生產程式碼搞在一起好不爽有麼有,不優雅,沒有人會這麼做會讓自己的程式碼變成那樣。
提案“通過預處理巨集開關,使得單元測試時將private替換為public”,看上去這個提案簡單,但是也不完美,使用預設的private成員限制(如class FooTest : Foo { int x;}),這個方案處理不了這個情形,另外這個方案要求你的程式中變數名和函式名中不能含有private子字串。
下面將介紹書中的類單元測試的完美解決方案:
1.語法知識準備:“可以為類模板宣告友元”(C++11新特性)
template<typename T>
class Foo {
friend T;
}
如果FooTest是類,那麼Foo<FooTest>會被例項化為一個定義了類FooTest為其友元的Foo<FooTest>類。
而若T為內建型別時,如Foo<int>會被例項化為一個普通的沒有友元定義的型別。
2.生產程式碼中的類模板例項化
template<typename T>
class FooT {
public:
friend T;
void DoSomthing(){}
private:
int m_data;
}
using Foo = FooT<int>;
後續的生產程式碼可以直接使用Foo,生產程式碼很優雅。
3.測試程式碼中的設計(與原書稍有出入,根據自身需求調整)
class FooTester; //測試類
using FooTestee = FooT<FooTester>; //被測試類
class FooTester{
public:
void Testcase1() {}
}
在FooTester類裡面,我們可以測試FooTestee的私有或公有成員函式,可以訪問FooTestee的私有成員變數進行驗證。總之單元測試很優雅。
學習了上面的完美方案,為C++11的新特性感到歡欣鼓舞,做一名重視單元測試的對自己有要求的C/C++工作者。感謝深入理解C++11這本書。