在没有HW的情况下测试此功能的简单/创造性方法

时间:2014-10-15 12:28:27

标签: 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 HW::setBits/setBit
{

readRegister()
//Modify
writeRegister()
}

在读写功能中,我做到了这一点。

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中的值之后不能正常工作,我在第二个中弹出它。任何想法如何简单地处理。如果可能的话,我不想添加太多逻辑来处理这个问题。基本上我只是在寻找创意。

1 个答案:

答案 0 :(得分:0)

您可以 使用模拟 。我建议使用模拟支持和memleak检测器base option for gulp.src - 它是 C / C ++单元测试框架 - 但其他像 GoogleMock 也是一种选择。

实施例

这里有一个小而基本的示例(使用CppUTest):
(我使用了一些C ++ 11功能 - 只是个人偏好,不是强制性的!)

HW-接口

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

HW-Interface mock

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

在这个(可改进的)示例中,有很多静态数据,例如。 unit = 1.您可以使用mock().setData(...) / mock().getData(...)轻松地将任何类型的数据传递到模拟。您还可以使用许多不同的模拟和命名模拟。查看手册以获得一些很好的例子。

文档