从单元测试文件中伪造 "source file under test" 内的值

Faking values within "source file under test" from an unit test file

假设我有一个 c 源文件(正在测试的源文件),内容为:

uint8 reg1 = I2CRead(20)
uint8 reg2 = I2CRead(24)
uint8 reg3 = I2CRead(28)

if (reg1 != 0x10) || (reg2 != 0x11) || (reg3 != 0x12)
{
   register content wrong ...
} 

else
{
   register content is OK...
}

I2CRead()函数构造如下:

uint8 I2CRead (uint8 address)
{
   I2C_Hw_Istance()->DTR = address  //DTR = Data Transmit Register

   return I2C_Hw_Instance()-> DRR   //DRR = Data Receive Register 
}

现在我正在尝试编写一个单元测试(使用 cpputest 框架),我想 "fake" 函数读回的值 I2CRead() 以便满足 if() 中的所有相等表达式。

单元测试文件与 "source file under test" 隔离,但我可以通过特殊方式访问以下函数 在被测源文件中:I2C_Hw_Instance().

使用此函数,我可以 "fake" 我在单元测试文件中的寄存器值,如下所示:

I2C_Hw_Istance()->DTR = 20;
I2C_Hw_Istance()->DRR = 0x10;

因为我连续调用了 3 个 I2CRead() 函数,所以我需要通过每个 I2CRead() 单独调用来伪造 DTR 和 DRR . 因此,这意味着单元测试文件需要知道何时调用下一个 I2CRead() 函数,以便能够操作中的值 DTR 和 DRR。

一般如何做到这一点,知道吗?

我的想法是有一种与单元测试一起构建的假文件(只是 "conceptual"):

FakeFile.c

void fakeRegisters()
{
   if first call of I2CRead() than:
     I2C_Hw_Istance()->DTR = 20;
     I2C_Hw_Istance()->DRR = 0x10;

   if second call of I2CRead()than:
     I2C_Hw_Istance()->DTR = 24;
     I2C_Hw_Istance()->DRR = 0x11;

   if tird call of I2CRead() than:
      I2C_Hw_Istance()->DTR = 28;
      I2C_Hw_Istance()->DRR = 0x12;
}

您需要选择 I2CRead() 的实现:

uint8_t I2CRead_i2c(uint8_t address)
{
   I2C_Hw_Istance()->DTR = address  //DTR = Data Transmit Register
   return I2C_Hw_Instance()-> DRR   //DRR = Data Receive Register
}


uint8_t I2CRead_fake(uint8_t address)
{
    switch (address) {
    case 20: return 0x10;
    case 24: return 0x11;
    case 28: return 0x12;
    }
    fail_test();                /* however you do this in your xUnit */
}

现在,在您的代码中,您通常使用 "real" 实现:

uint8 (*I2CRead)(uint8) = I2CRead_i2c;

当您 运行 测试时,您需要注入模拟实现:

I2CRead = I2CRead_fake;

这是最简单的伪造实现之一;如果您需要,可以使用整个范围的伪造(您可能希望有一个包含寄存器内容的数组,以便您可以测试初学者的成功和失败路径)。