2016-08-03 80 views
2

即時通訊非常好奇人們的意見在什麼方式與硬件接口的軟件側應用程序應單元測試。單元測試應用程序接口到硬件 - 模擬或不模擬

例如,軟件應用程序「連接」的主要類將構建USB設備的句柄。

我想測試「連接」類的基本功能,比如說「OpenConnection」,它會嘗試連接到USB硬件設備。

到目前爲止我已經構建了一個MOCK硬件設備,並且在我的連接類中包含了一個編譯器標誌,所以如果它內置在單元測試模式下,它將使用模擬對象,否則它會使用實際的硬件接口。

參見下面的例子

class TConnection 
{ 
public: 
    static TConnection* GetConnection(); 
    static void Shutdown(); 

    bool DidInitialise(); 

    bool Write(uint8_t* _pu8_buffer); 
    bool Read(uint8_t* _pu8_buffer); 

protected: 
    TConnection(); 
    virtual ~TConnection(); 
    bool init(); 

private: 
    static TConnection* mp_padConnection; 
    static bool mb_DidInitialise; 

#ifdef _UNIT_TEST_BUILD 
    static mock_device* mp_handle; 
#else 
    static device* mp_handle; 
#endif 
}; 

然後在源文件中包括我像

#include "connection.h" 

#ifdef _UNIT_TEST_BUILD 
    mock_device* TConnection::mp_handle = nullptr; 
#else 
    device* TConnection::mp_handle = nullptr; 
#endif // _UNIT_TEST_BUILD 

TConnection::TConnection() 
{ 
    ... 
    init(); 
    ... 
} 

bool TConnection::init() 
{ 
    mp_handle = hid_open(_VENDOR_ID, _PRODUCT_ID, nullptr); 
    if (mp_hidHandle == nullptr) { 
     return false; 
    } 
    if (hid_set_nonblocking(mp_hidHandle, _DISABLE_NB) == _ERROR_CODE) { 
     return false; 
    } 
    return true; 
} 

我真的不喜歡我的代碼的唯一的事情就是我的實際連接類包含測試代碼。我更喜歡他們分開。我也不同意擁有一個全新的模擬連接類,它僅僅是爲了單元測試的目的而編寫的,它讓我覺得我只是在寫一些按照預期工作的東西。

所以我問,什麼是預先測試的這樣一類

謝謝您的時間和建議更好的方法

回答

5

您可以避免使用依賴注入向您的類添加測試代碼。創建一個接口IDevice並使類Device實現該接口。然後,在類TConnection中,使用指向此接口的指針而不是Device類型的成員。同時創建一個輔助方法,它允許您設置一個新的設備,是這樣的:現在

void setDevice(IDevice *device); 

,爲您的生產代碼的簡單使用Device類的實例,而在你的測試代碼使用setDevice交換實現設備的與一個模擬對象。這個模擬對象將是類MockDevice的一個實例,它也將實現接口IDevice。這樣你可以在測試中改變實現並使用模擬類。由於您已經使用gtest,所以我建議您不要自己編寫模擬類,而應使用C++嘲笑框架gmock(它完全兼容gtest)。這樣,您還需要創建一個單獨的類,但幾乎所有內容都將由模擬框架處理。你所需要做的就是定義模擬方法。創建一個額外的界面和模擬類似乎起初是過度的,但從長遠來看,它肯定會帶來回報。如果你想做任何認真的代碼測試,學習使用接口,依賴注入和模擬類是非常重要的。檢查文檔瞭解更多信息:

https://github.com/google/googlemock/blob/master/googlemock/docs/CheatSheet.md

+0

您好Marko,我想您剛剛爲我提供了我的理想設計,謝謝!我非常喜歡這種界面方法。在我的課堂上嵌入了測試/模擬代碼時,它非常抽象。我現在要嘗試這種設計,但我相信它正是我所需要的。 – Spirit

3

我個人有模擬無論是作爲單獨的類,或部分的測試代碼。爲了區分模擬庫和實際庫,我將在構建腳本中進行更改,我假設這將包括鏈接到庫的測試文件(和模擬)

創建一個單獨的類不是浪費精力。它應該按照預期行事,但這可以簡化爲測試所需的最低限度。更有趣的是讓類生成錯誤事件,以確保您的代碼正確處理這些事件。另一種選擇是有時要等待發生錯誤,我不建議這樣做。強烈建議在主題

兩本書:

+0

謝謝你的意見的Eirik,我很欣賞的反饋。不過,我只是覺得當我嘲笑我的主要課程,並且這樣做時,我忽視了我的連接類的實際測試。但我感謝你的看法,我可以看到有一個單獨的ConnectionMock可能是我應該去的方式:) – Spirit

+1

我添加了一些書籍建議,我發現有幫助。基本上,如果做得對,模擬應該和記錄功能中的測試代碼一樣重要。 –

+0

非常感謝Eirik的書籍,它們看起來很有趣。 Ive既然下了他們倆的訂單:) – Spirit