嵌入式系统的 Google 测试

2023-12-30

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

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

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

我最近使用 gTest 测试了 FAT 文件系统和引导加载程序实现(谷歌测试 http://google.github.io/googletest/)对于 Arm Cortex-M3 核心,所以我会留下我的两分钱。

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

A)单元测试(我在TDD https://wingman-sw.com/)运行on my PC。我使用这些测试来开发我的应用程序逻辑。这就是我需要嘲笑/存根的地方。我的公司使用硬件抽象层(HAL),这就是我嘲笑的。如果您想编写可测试的代码,最后一点是基础。

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

/* this is also not testable */
*my_register |= BIT0;

不要直接访问寄存器,使用可以模拟的简单 HAL 包装函数:

/* 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 https://github.com/siu/minunit,这是一个单一的 C 头文件。我已经使用 MinUnit 在 Cortex-M3 内核和专有 DSP 代码上运行了目标测试(未经任何修改)。我在这里也使用了 TDD。

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

回答您的问题:

  1. 正如其他人已经说过的,从g测试引物 http://google.github.io/googletest/primer.html,并且不用担心嘲笑,只需掌握使用 gTest 的窍门即可。提供一些内存检查(泄漏)的一个很好的替代方案是Cpputest http://cpputest.github.io/。我对派生安装类的 gTest 语法有一点偏好。 Cpputest 可以运行用 gTest 编写的测试。两者都是很棒的框架。

  2. I used 假函数框架 https://github.com/meekrosoft/fff用于嘲笑和存根。它使用起来非常简单,并且提供了一个好的模拟框架所期望的一切:设置不同的返回值、传递回调、检查参数调用历史记录等。我想给出Ceedling http://www.throwtheswitch.org/ceedling走吧。到目前为止,FFF 一直很棒。

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

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

我会模拟重置功能,添加回调以“重置”您需要的任何内容。

假设您想测试read_temperature使用的函数read功能。下面是一个使用 FFF 进行模拟的 gTest 示例。

hal_i2c.h

/* HAL Low-level driver function */

/**
 * @brief Read a byte from the I2C bus.
 * 
 * @param address The I2C slave address.
 * @return uint8_t The data read from the I2C bus.
 */
uint8_t read(uint8_t address);

read_temperature.h

/**
 * @brief Read the temperature from the sensor in the board
 * 
 * @return float The temperature in degrees Celsius.
 */
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 at address 0xAB */
    raw_value = read(0xAB);

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

test_i2c.cpp

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

DEFINE_FFF_GLOBALS;

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

// Declare the fake C functions using FFF. This needs be inside the extern "C"
// block because we're mocking a C function and the C++ name-mangling would
// break linking otherwise.


// 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 for the fake read() function
    RESET_FAKE(read);

    // Set the raw temperature value the fake for read should return
    read_fake.return_val = 0xAB;

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

对于带有测试类的更复杂的测试场景,您可以调用RESET_FAKE in the SetUp() method.

希望这可以帮助!干杯!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式系统的 Google 测试 的相关文章

  • 无法继承形状

    为什么我不能使用继承 a 的类Shapes class http msdn microsoft com en us library ms604615 28v vs 90 29 我需要延长Rectangle具有一些方法的类 但我想以与使用相同
  • strlen() 编译时优化

    前几天我发现你可以找到编译时strlen使用这样的东西 template
  • C# 中一次性对象克隆会导致内存泄漏吗?

    检查这个代码 class someclass IDisposable private Bitmap imageObject public void ImageCrop int X int Y int W int H imageObject
  • Selenium - C# - Webdriver - 无法找到元素

    在 C 中使用 selenium 我试图打开浏览器 导航到 Google 并找到文本搜索字段 我尝试下面的 IWebDriver driver new InternetExplorerDriver C driver Navigate GoT
  • 在复杂的文件夹结构中进行测试

    我正在 golang 中构建一个设计模式存储库 为了运行所有测试 我使用这个 bash 脚本 有用 bin bash go test creational abstract factory go go test creational bui
  • 防止控制台应用程序中的内存工作集最小化?

    我想防止控制台应用程序中的内存工作集最小化 在Windows应用程序中 我可以这样做覆盖 SC MINIMIZE 消息 http support microsoft com kb 293215 en us fr 1 但是 如何在控制台应用程
  • if constexpr 中的 not-constexpr 变量 – clang 与 GCC

    struct A constexpr operator bool const return true int main auto f auto v if constexpr v A a f a clang 6 接受该代码 GCC 8 拒绝它
  • 我们如何测试包私有类?

    我正在看书Effective Java in Item 13 Minimize the accessibility of classes and members 它提到 为了方便测试 您可能想让类 接口或成员更易于访问 这在某种程度上是好的
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • Libev,如何将参数传递给相关回调

    我陷入了 libev 中争论的境地 通常 libev 在类似的函数中接收包 接收回调 没关系 但是实际操作中 我们需要派遣一个亲戚 写回调 根据收到的包裹处理具体工作 例如 S RECV MSG pstRecvMsg S RECV MSG
  • 测量进程消耗的 CPU 时钟

    我用 C 语言编写了一个程序 它是作为研究结果创建的程序 我想计算程序消耗的确切 CPU 周期 精确的循环次数 知道我怎样才能找到它吗 The valgrind tool cachegrind valgrind tool cachegrin
  • 如何对使用 Controller.User 变量的控制器操作进行单元测试?

    我有一个控制器操作 如果用户已经登录 它会自动重定向到新页面 User Identity IsAuthenticated 针对这种情况编写单元测试以确保重定向发生的最佳方法是什么 我一直在使用以下 Mocks 和 Moq 来允许在我的单元测
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • 读取依赖步行者输出

    I am having some problems using one of the Dlls in my application and I ran dependency walker on it i am not sure how to
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 在 C# 的 WebAPI 中的 ApiController 上使用“传输编码:分块”提供数据

    我需要服务分块传输使用编码数据API控制器 因为我无权访问HttpContext or the Http请求 我有点不知道在哪里写入响应以及在哪里刷新它 设置如下 public class MyController ApiControlle
  • 如何高效计算连续数的数字积?

    我正在尝试计算数字序列中每个数字的数字乘积 例如 21 22 23 98 99 将会 2 4 6 72 81 为了降低复杂性 我只会考虑 连续的数字 http simple wikipedia org wiki Consecutive in
  • 如何从 Windows Phone 7 模拟器获取数据

    我有一个 WP7 的单元测试框架 它在手机上运行 结果相当难以阅读 因此我将它们写入 XDocument 我的问题是 如何才能将这个 XML 文件从手机上移到我的桌面上 以便我可以实际分析结果 到目前为止 我所做的是将 Debugger B
  • 从后面的代码添加外部 css 文件

    我有一个 CSS 文件 例如 SomeStyle css 我是否可以将此样式表文档从其代码隐藏应用到 aspx 页面 您可以将文字控件添加到标头控件中 Page Header Controls Add new System Web UI L
  • 如何为有时异步的操作创建和实现接口

    假设我有数百个类 它们使用 计算 方法实现公共接口 一些类将执行异步 例如读取文件 而实现相同接口的其他类将执行同步代码 例如将两个数字相加 为了维护和性能 对此进行编码的好方法是什么 到目前为止我读到的帖子总是建议将异步 等待方法冒泡给调

随机推荐

  • ios9 无法加载资源

    当我在 ios9 中调用我的 api 时遇到此错误 但在 ios8 中工作正常 无法加载资源 因为应用程序传输安全策略需要使用安全连接 ios9 您需要在 plist 中添加一个标志 更多信息请访问https forums develope
  • 使用 MSBuild 进行 ClickOnce 部署 -> 如何传递应用程序版本/或自动增量的当前内部版本号

    我们有一个使用 ClickOnce 部署的 Outlook 加载项 一旦开发人员签入构建 PC 就会对构建进行排队 并将应用程序发布到共享驱动器上的某个位置 问题在于 构建不会将发布版本更改为当前程序集版本 因此它会在先前版本的文件夹中发布
  • Android Google+ 集成 - 重复 UserRecoverableAuthException

    我们已就此事联系了 Google 并且我们正在聊天 https chat stackoverflow com rooms 33772 discussion between lee and arkaaito 该问题似乎已针对设备修复excep
  • DeleteD 会自动取消选择对象吗?

    我是否总是需要调用 SelectObject 将原始对象恢复到 DC 并使我的对象可供删除 即使我无论如何都要删除 DC e g Create DC HBITMAP hBitmap CreateCompatibleBitmap hDC re
  • 安装 R3.3 的 udunits2 软件包

    我只是浪费了一整天的时间试图弄清楚如何安装 udunits2 软件包以便能够安装units 软件包以便能够安装ggforce 和ggraph 软件包 我尝试在 Ubuntu 16 04 和 R gt 3 3 上安装它 因为 ggforce
  • .NET 上 C# 的模拟工具 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我是 C NET 新手 但我从事 TDD 已经有一段时间了 我想知道在 C 中编写测试时可用于模拟对象
  • 可执行文件中的函数地址(由 objdump 检查)与 printf 打印的同一函数的地址不匹配。幕后发生了什么?

    我使用的是 Ubuntu 22 04 3 x86 64 系统 我知道虚拟内存和页面一般是如何工作的 我也知道系统可以使用 ASLR 不过我想知道在这个特定场景下 Ubuntu 系统到底会发生什么 我在名为 test c 的文件中有这个小程序
  • 根据缩放级别渲染 QGraphicsScene

    有没有一种 快速 方法可以根据视图缩放级别仅渲染 GraphicsScene 项目的子集 我有一个包含许多网格线的大场景 当缩放更改以避免 网格完全填充场景 效果时 我想隐藏 显示其中一些网格线 网格线是使用QGraphicsScene的a
  • 使用 C++ REST SDK 从文件读取 JSON (卡萨布兰卡)

    我有以下代码 它应该读取文本文件的内容并将其解析为 JSON try string t importFile argv iArgCounter extract filename ifstream t f importFile filestr
  • AD用户认证

    我正在尝试创建一个 ASP NET NET 3 5 网站以通过 Exchange Web 服务连接到我们的 Exchange 2010 服务器 当我定义要进行身份验证的用户名 密码和域时 我能够连接到 EWS 但我想 如果可能的话 不要在我
  • Google 电子表格中单元格文本的 sha3-256

    我知道你可以在谷歌表格上做 sha1 和其他 但是有没有办法做 sha3 256 secret test123 hash 3054762b0a8b31adfe79efb3bc7718624627cc99c7c8f39bfa591ce6854
  • 访问 iCloud 通知中已删除的对象

    我有一个应用程序设置非常类似于 iCloudCoreDataRecipes 示例 即 将 Core Data 与 iCloud 结合使用 在应用程序委托中 我观察到 NSPersistentStoreDidImportUbiquitousC
  • 图像配准(非刚性\非线性)

    我正在寻找一些算法 最好是如果源代码可用 用于图像配准 图像变形不能用单应矩阵来描述 因为我认为变形不是对称的 不是 均匀 更具体地说 变形就像桶形 扭曲和梯形扭曲 可能是图像的一些旋转 我想获得两个图像的像素对 这样我就可以获得 变形场
  • 在 C 编程中避免为串联分配大量内存

    提供的代码从文本文件中读取行并将它们存储在称为lines的动态分配的二维数组中 该模式始终在第32767行之后重复 然后它连接特定的行 lines j lines k lines m 并将结果打印在输出文件中 问题是我的 input txt
  • Backbone.js 和 PushState

    如果我在主干路由器中启用pushState 我是否需要在所有链路上使用return false 或者主干路由器是否会自动处理此问题 是否有任何示例 包括 html 部分和脚本部分 这是蒂姆 布兰延 Tim Branyen 在他的作品中使用的
  • 下划线的 PyCharm 代码完成设置 - 受保护和损坏的名称优先级较低?

    我正在使用 PyCharm 但我不喜欢显示的默认代码完成 protected and mangled名字高于public 我怎样才能强制显示以下划线在代码完成列表的底部 在顶部公开 像 PyDev 这样的一些编辑器在没有配置的情况下做得更好
  • Django 模板中的动态块

    这是一个关于 django 的问题 我完全找不到答案 假设我有一个网站 在侧边栏中显示两个块 最后登录的用户的列表 最近发表的博客文章的列表 假设这些块将显示在 80 的网站 URL 上并使用模板文件呈现 这些块的数据是由代码生成的 显然
  • jQuery $(窗口).resize();等效的事件侦听器,仅在指定的轴更改时触发?

    我正在寻找一个事件监听器 它的工作原理类似于 jQuery resize 但仅当调整大小的对象 谈论窗口 在 x 轴或两者上调整大小时触发 但不仅仅在 y 轴上调整大小 所以基本上它只会监听宽度的调整大小事件 您可以将窗口加载时浏览器的宽度
  • JqueryUI Autocomplete: autoFocus = true 不会做任何事情

    我有这个带有自动完成功能的输入 autocomplete source jsonR php minLength 2 select function event ui this val ui item value llamar include
  • 嵌入式系统的 Google 测试

    我想使用 Google Tests 为我的嵌入式应用程序软件编写单元测试 这些测试将在用 C 编写的应用软件上执行 应用程序软件使用的驱动程序 例如I2C SPI 故障断言是用 C 编写的 我的问题是 什么是一个好的起点 我的意思是我可以阅