嵌入式系统的Google测试

mmcblk1

我想使用Google测试为嵌入式应用程序软件编写单元测试。

这些测试将在用C ++编写的应用程序软件上执行。应用软件(例如I2CSPI),故障断言所使用的驱动程序用C编写。我的问题是:

  1. 什么是开始的好地方?我的意思是我可以阅读一些资源,以了解有关在嵌入式环境中使用Google Test的更多信息。
  2. 我该如何模拟驱动程序文件?例如,如果我void read(uint8_t address)在I2C库中有一个函数,该如何模拟该函数,以便在我的C ++类中调用此特定函数?
  3. 这些用C编写的驱动程序文件也包含在我的C ++文件中。我尝试编译仅包含我的C ++类标头的裸露的Test文件,但是由于编译器找不到驱动程序标头,因此出现了编译问题。如何避免这个问题?
  4. 使用代码管理失败的断言-驱动程序库中的失败断言要求系统重置。我如何在测试中模拟这一点?
列昂纳多

我最近用gTest为Arm Cortex-M3内核测试了FAT文件系统和引导程序实现,因此我只花了两美分。

嵌入式软件测试提出了无法通过模拟来复制硬件环境的问题。我有三组测试:

A)在PC上运行的单元测试(我在TDD中使用我使用这些测试来开发我的应用程序逻辑。这是我需要模拟/存根的地方。我的公司使用硬件抽象层(HAL),这就是我的嘲笑。如果您想编写可测试的代码,那么这最后一点至关重要。

/* this is not testable */
my_register->bit0 = 1;

/* this is also not testable */
*my_register |= BIT0;
/* this is testable */
void set_bit(uint32_t* reg, uint8_t bit)
{
    *reg |= bit;
}

set_bit(my_register , BIT0);

后者是可测试的,因为您要模拟set_bit函数,从而打破了对硬件的依赖。

B)对目标进行单元测试。这是一组比(A)小得多的测试,但是对于测试驱动程序和HAL功能尤其有用。这些测试背后的想法是,我可以正确地测试要模拟的功能。因为这是在目标上运行的,所以我需要它尽可能简单和轻巧,因此我使用MinUnit,它是单个C头文件。我已经使用MinUnit在Cortex-M3内核和专有DSP代码上进行了目标测试(未经任何修改)。我在这里也使用过TDD。

C)集成测试。我在这里使用Python和Behave来构建,下载并在目标上运行整个应用程序。

回答您的问题:

  1. 正如其他人已经说过的那样,从gTest Primer开始,不用担心模拟,只需要掌握使用gTest的技巧即可。Cpputest是提供一些内存检查(用于泄漏)的一个很好的选择对于gTest语法,我有点偏爱派生安装程序类。Cpputest可以运行用gTest编写的测试。两者都是很好的框架。

  2. 我使用Fake Function Frakework进行模拟和存根。它非常易于使用,并且提供了良好的模拟框架所期望的一切:设置不同的返回值,传递回调,检查参数调用历史记录等。我想让Ceedling受益到目前为止,FFF很棒。

  3. 我不那样做 我使用C ++编译器(在我的情况下为g ++)编译测试框架和测试,并使用C编译器(gcc)编译嵌入式代码,然后将它们链接在一起。从下面的示例中,您将看到我不在C文件中包含C ++标头。链接测试时,将链接要模拟的功能的C源文件以外的所有内容。

使用代码管理失败的断言-驱动程序库中的失败断言要求系统重置。我如何在测试中模拟这一点?

我将模拟reset函数,并根据需要添加一个回调以“重置”。

假设您要测试read_temperature使用该read功能的功能。以下是使用FFF进行模拟的gTest示例。

hal_i2c.h

/* Low-level driver function */
uint8_t read(uint8_t address);

read_temperature.h

/* Reads the temperature from the I2C sensor */
float read_temperature(void);

read_temp.c

#include <hal_i2c.h>

float read_temperature(void)
{
    unit8_t raw_value;
    float temp;

    /* Read the raw value from the I2C sensor */
    raw_value = read(0xAB);

    /* Convert the raw value */
    temp = ((float)raw_value)/0.17+273;
    return temp;
}

test_i2c.cpp

#include <gtest/gtest.h>
#include <fff.h>

extern "C"
{
#include <hal_i2c.h>
#include <read_temperature.h>
}

DEFINE_FFF_GLOBALS;
// Create a mock for the uint8_t read(uint8_t address) function
FAKE_VALUE_FUNC(uint8_t , read, uint8_t);

TEST(I2CTest, test_read) {

    // This clears the FFF counters
    RESET_FAKE(read);

    // Set the raw temperature value
    read_fake.return_val = 0xAB;

    // Make sure that we read 123.4 degree
    ASSERT_EQ((float)123.4, read_temperature());
}

希望这可以帮助!干杯!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章