C++ 无硬件测试此功能的简单/创新方法

C++ 无硬件测试此功能的简单/创新方法,c++,unit-testing,tdd,C++,Unit Testing,Tdd,我想知道是否有人知道一种简单的方法来测试这个功能,而不需要实际的硬件。问题是,我设置了两个寄存器,我想读回它们,以便验证代码是否正确 void Class::setSomeRegister( uint8_t unit, uint8_t input ) { if (input<=15) iHW.setBits( OFFSET, unit*4, 4, input ); iHW.setBit( OFFSET_TWO, unit, input==16 ); } 在读写函数中,我已经完成了

我想知道是否有人知道一种简单的方法来测试这个功能,而不需要实际的硬件。问题是,我设置了两个寄存器,我想读回它们,以便验证代码是否正确

void Class::setSomeRegister( uint8_t unit, uint8_t input )
{
if (input<=15)
    iHW.setBits( OFFSET, unit*4, 4, input );
iHW.setBit( OFFSET_TWO, unit, input==16 );
}
在读写函数中,我已经完成了这项工作

readRegister
{
#ifdef EMULATION
    return iTestRegister;
#else
     //Real Code
#endif
}

writeRegister( offset, const uint32_t value )
{
#ifdef EMULATION
    iTestRegister = value;
#else
    //Real Code
#endif
}

static uint32_t iTestRegister;
我也尝试过使用std::stack,但在第一个setregister中按下该值后,我在第二个setregister中弹出该值,这不起作用。任何关于如何简单处理的想法。如果可能的话,我不想添加太多的逻辑来处理这个问题。基本上,我只是在寻找创造性的想法。

你可以使用mock。我推荐-这是一个C/C++单元测试框架,具有模拟支持和memleak detector-但是像GoogleMock这样的其他框架也是一个选项


例子 下面是一个小而基本的示例(使用CppUTest):
(我正在使用一些C++11功能-只是个人喜好,不是强制性的!)

硬件接口 硬件接口模拟 一些示例实现 单元测试(带模拟) 在这个(可改进的)示例中,有很多静态数据,例如unit=1。您可以使用
mock().setData(…)
/
mock().getData(…)
轻松地将任何类型的数据传递给您的mock。您还可以使用许多不同的模拟和命名模拟。查看手册中的一些好例子

文档

您肯定只需要一个数组来处理最大数量的寄存器(两个?)?我有1000多个寄存器,我可以这样做,但有简单的方法吗?可能是std::map?名称应为寄存器名称或地址,值应为uint32\t类型。或者只使用文件作为内存,在文件中使用偏移量作为偏移量。@user1876942:数字并不重要-您只需要某种数组,这样您就可以用一块内存模拟寄存器-我真的看不出有什么问题吗?
readRegister
{
#ifdef EMULATION
    return iTestRegister;
#else
     //Real Code
#endif
}

writeRegister( offset, const uint32_t value )
{
#ifdef EMULATION
    iTestRegister = value;
#else
    //Real Code
#endif
}

static uint32_t iTestRegister;
class HW
{
public:
    virtual void setBit(uint32_t offset, uint8_t unit, uint8_t bits) = 0;
    virtual void setBits(uint32_t offset, uint8_t whatever, uint8_t unit, uint8_t bits) =0;
};
class HWMock : public HW
{
public:
    void setBit(uint32_t offset, uint8_t unit, uint8_t bits) override
    {
        mock().actualCall("setBit")
                .withParameter("offset", offset)
                .withParameter("unit", unit)
                .withParameter("bits", bits);
    }

    void setBits(uint32_t offset, uint8_t whatever, uint8_t unit, uint8_t bits) override
    {
        mock().actualCall("setBits")
                .withParameter("offset", offset)
                .withParameter("whatever", whatever)
                .withParameter("unit", unit)
                .withParameter("bits", bits);
    }

};
class ExampleImpl
{
public:
    static const uint32_t OFFSET = 10;

    ~ExampleImpl()
    {
        delete hw;
    }

    // This method is under test
    void setSomeRegister(uint8_t unit, uint8_t input)
    {
        if( input >= 15 )
        {
            hw->setBits(OFFSET, unit * 4, unit, input);
        }
        else
        {
            hw->setBit(OFFSET, unit, input);
        }
    }

private:
    HW* hw = new HWMock;
};
TEST_GROUP(So26382638)
{
    void setup() override
    { 
        hw = new HWMock;
    }

    void teardown() override
    {
        mock().clear();
        delete hw;
    }

    HW* hw;
    ExampleImpl impl;
};


TEST(So26382638, setRegisterSetsBit)
{
    const uint8_t unit = 1;
    const uint8_t bits = 3;
    mock().expectOneCall("setBit")
            .withParameter("offset", ExampleImpl::OFFSET)
            .withParameter("unit", unit)
            .withParameter("bits", bits);
    impl.setSomeRegister(unit, bits);
    mock().checkExpectations();
}

TEST(So26382638, setRegisterSetsBitsIf15OrMore)
{
    const uint8_t unit = 1;
    const uint8_t bits = 17;
    mock().expectOneCall("setBits")
            .withParameter("offset", ExampleImpl::OFFSET)
            .withParameter("whatever", 4 * unit)
            .withParameter("unit", unit)
            .withParameter("bits", bits);
    impl.setSomeRegister(unit, bits);
    mock().checkExpectations();
}