单元测试硬件的应用程序接口 - 模拟与否

Spi*_*rit 2 c++ unit-testing googletest c++11

我非常好奇人们对于与硬件接口的软件端应用程序应该以何种方式进行单元测试的意见.

例如,软件应用程序"连接"的主类将构建USB设备的句柄.

我想测试"Connection"类基本函数,比如"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
};
Run Code Online (Sandbox Code Playgroud)

然后在源文件中包含类似的内容

#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;
}
Run Code Online (Sandbox Code Playgroud)

我真的不喜欢我的代码是我的实际连接类包含测试代码.我更希望他们分开.

说这个,我也不同意有一个全新的模拟连接类只是为了单元测试而编写,它让我觉得我只是写了一些旨在按预期工作的东西.

所以我想问一下,测试这样一个类的更好的方法是什么

提前感谢您的时间和建议

Mar*_*vic 5

您可以通过使用依赖项注入来避免向您的类添加测试代码.创建一个接口IDevice并使类Device实现该接口.然后,在类中TConnection,使用指向此接口的指针而不是类型的成员Device.还可以创建一个帮助方法,允许您设置新设备,例如:

void setDevice(IDevice *device);
Run Code Online (Sandbox Code Playgroud)

现在,为您的生产代码简单地使用类的实例Device,而在您的测试代码中使用setDevice交换设备的实现与模拟对象.这个模拟对象将是一个类的实例,MockDevice它也将实现接口IDevice.这样你就可以改变测试中的实现并使用mock类.由于你已经在使用gtest,我建议你不要自己编写mock类,而是使用C++ mocking framework gmock(它与gtest完全兼容).这样,您还需要创建一个单独的类,但几乎所有内容都将由模拟框架处理.您需要做的就是定义模拟方法.创建一个额外的界面和模拟类似乎一开始就有点过头了,但从长远来看它肯定会有所回报.如果你想对代码进行任何严格的测试驱动,学习使用接口,依赖注入和模拟类是必不可少的.查看文档以获取更多详细信息:

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