1. 程式人生 > >C++類的完美單元測試方案——基於C++11擴充套件的friend語法

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這本書。