c++ - 单元测试应用程序到硬件的接口(interface)——模拟与否

标签 c++ unit-testing c++11 googletest

我很好奇人们对与硬件接口(interface)的软件端应用程序应该以何种方式进行单元测试的意见。

例如,软件应用程序“Connection”的主类将构造 USB 设备的句柄。

我想测试“Connection”类基函数,例如“OpenConnection”,它会尝试连接到 USB 硬件设备。

到目前为止,我已经构建了一个 MOCK 硬件设备,并在我的连接类中包含了一个编译器标志,因此如果它内置于单元测试模式,它将使用模拟对象,否则它将使用实际的硬件接口(interface)。

看下面的例子

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;
}

我唯一真正不喜欢我的代码的地方是我的实际连接类包含测试代码。我更希望它们是分开的。

话虽如此,我也不同意完全为了单元测试的目的而编写一个全新的模拟连接类,这让我觉得我只是在编写一些旨在按预期工作的东西。

所以我问,什么是测试此类的更好方法

提前感谢您的时间和建议

最佳答案

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

void setDevice(IDevice *device);

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

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

关于c++ - 单元测试应用程序到硬件的接口(interface)——模拟与否,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38745542/

相关文章:

c++ - 调用堆栈和堆栈有什么区别?

java - 如何确保单元测试在这种情况下保持正确?

c++ - g++ : should --std option change which STL/stdlib my code uses?

c++ - 为什么这个函数在给定右值参数的情况下返回一个左值引用?

c++ - C++ 中的 MSD 基数排序(字典顺序)

c++ - 在 C++ 中从 XML 模式生成 XML 文档

c++ - 为什么 istream 对象可以用作 bool 表达式?

c++ - 将静态 C 库与 C++ 代码链接时出现 "undefined reference to"错误

c# - 如果发生对静态记录器的调用,如何进行单元测试

android - 使用 Gradle 任务运行单元测试时出现 NoClassDefFoundError