Unity(单元测试)在STM32上的移植与应用

概述

Unity Test是一个为C构建的单元测试框架。本文基于STM32F407为基础,完全使用STM32CubeIDE进行开发,移植和简单使用Unity。

单片机型号:STM32F407VET6

软件:STM32CubeIDE  Version: 1.14.1    Unity Version:2.6.0

一、配置stm32工程

新建工程,选择407芯片,生成工程后开始配置硬件,这里我们只使用了串口1,作为打印输出串口,按照图片设置,波特率等根据需要设置,这里我使用的默认值。

我习惯单独生成c和h文件。

保存生成代码。

在main.c文件中添加串口重定向函数

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int __io_putchar(int ch)
{/* Implementation of __io_putchar *//* e.g. write a character to the UART1 and Loop until the end of transmission */HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFFFFFF);return ch;
}
int __io_getchar(void)
{/* Implementation of __io_getchar */char rxChar;// This loops in case of HAL timeout, but if an ok or error occurs, we continuewhile (HAL_UART_Receive(&huart1, (uint8_t *)&rxChar, 1, 0xFFFFFFFF) == HAL_TIMEOUT);return rxChar;
}
/* USER CODE END 0 */

此时理论上可以编译通过,并且printf好用。

二、下载unity源码

GitHub - ThrowTheSwitch/Unity: Simple Unit Testing for C

源码地址如上。

在工程根路径下创建Unity文件夹,并将unity源码中的src文件夹中的文件放到这个目录中。并将example文件夹中的unity_config.h也放到目录中。

在工程中右键并刷新

这时就会看到我们添加的文件夹了。

在工程上右键Properties,如下图步骤添加unity到includes目录中。

如上图,添加源文件到工程中参与编译。

此时就可以编译了,可以正常编译通过。

这里说一下配置文件,unity_config.h,如果使用的是stm32的cube,那么这个文件什么都不用写,如果使用的是其他mcu或者编译器,需要详细阅读并进行相关的宏定义。

三、测试程序

下面我先简单翻译一下github上的readme。

基本有效性测试

TEST_ASSERT_TRUE(condition)
如果条件结果为 false,则失败
TEST_ASSERT_FALSE(condition)
如果条件结果为 true,则失败
TEST_ASSERT(condition)
另一种方式TEST_ASSERT_TRUE
TEST_ASSERT_UNLESS(condition)
另一种方式TEST_ASSERT_FALSE
TEST_FAIL()
TEST_FAIL_MESSAGE(message)
此测试会自动标记为失败。 输出消息,说明原因。

数值断言:整数

TEST_ASSERT_EQUAL_INT(expected, actual)
TEST_ASSERT_EQUAL_INT8(expected, actual)
TEST_ASSERT_EQUAL_INT16(expected, actual)
TEST_ASSERT_EQUAL_INT32(expected, actual)
TEST_ASSERT_EQUAL_INT64(expected, actual)
比较两个整数是否相等,并将错误显示为有符号整数。 将根据您的自然整数大小执行强制转换, 当您需要指定确切的大小时,您可以使用特定版本。
TEST_ASSERT_EQUAL_UINT(expected, actual)
TEST_ASSERT_EQUAL_UINT8(expected, actual)
TEST_ASSERT_EQUAL_UINT16(expected, actual)
TEST_ASSERT_EQUAL_UINT32(expected, actual)
TEST_ASSERT_EQUAL_UINT64(expected, actual)
比较两个整数是否相等,并将错误显示为无符号整数。 与 INT 一样,也有不同大小的变体。
TEST_ASSERT_EQUAL_HEX(expected, actual)
TEST_ASSERT_EQUAL_HEX8(expected, actual)
TEST_ASSERT_EQUAL_HEX16(expected, actual)
TEST_ASSERT_EQUAL_HEX32(expected, actual)
TEST_ASSERT_EQUAL_HEX64(expected, actual)
比较两个整数是否相等,并将错误显示为十六进制。与其他整数比较一样,您可以指定大小。。。这里的大小也将影响所示出的半字节的数量(例如,将示出4个半字节)。
TEST_ASSERT_EQUAL(expected, actual)
另一种TEST_ASSERT_EQUAL_INT的方式
TEST_ASSERT_INT_WITHIN(delta, expected, actual)
断言实际值在预期值的正负增量范围内。 这也具有特定尺寸的变体。
TEST_ASSERT_GREATER_THAN(threshold, actual)
断言实际值大于阈值。 这也具有特定尺寸的变体。
TEST_ASSERT_LESS_THAN(threshold, actual)
断言实际值小于阈值。 这也具有特定尺寸的变体。

数 组

_ARRAY
您可以附加到这些宏中的任何一个,以进行该类型的数组比较。在这里,您需要更加关心被检查值的实际大小。您还将指定一个额外的参数,即要比较的元素数。例如:_ARRAY
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements)
_EACH_EQUAL
另一个数组比较选项是检查数组的每个元素是否等于单个期望值。 为此,请指定 EACH_EQUAL 宏。 例如:
TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, elements)

数值断言:按位

TEST_ASSERT_BITS(mask, expected, actual)
使用整数掩码指定应在另外两个整数之间比较哪些位。 比较掩码中的高位,忽略低位。

TEST_ASSERT_BITS_HIGH(mask, actual)
使用整数掩码指定应检查哪些位以确定它们是否全部设置为高电平。 比较掩码中的高位,忽略低位。

TEST_ASSERT_BITS_LOW(mask, actual)
使用整数掩码指定应检查哪些位以确定它们是否全部设置为低电平。 比较掩码中的高位,忽略低位。

TEST_ASSERT_BIT_HIGH(bit, actual)
测试单个位并验证它是否为高电平。 对于 32 位整数,该位指定为 0-31。

TEST_ASSERT_BIT_LOW(bit, actual)
测试单个位并验证它是否为低电平。 对于 32 位整数,该位指定为 0-31。

数值断言:浮点数

TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)
TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual)
断言实际值在预期值的正负增量范围内。

TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual)
TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual)
断言实际值不在预期值的正负增量范围内。

TEST_ASSERT_EQUAL_FLOAT(expected, actual)
TEST_ASSERT_EQUAL_DOUBLE(expected, actual)
断言两个浮点值在预期值的一小部分 % 增量内“相等”。

TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual)
TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual)
断言两个浮点值在期望值的一小部分 % 增量内不“相等”。

TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual)
TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual)
TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual)
TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual)
断言实际值小于或大于阈值。

也有和变化。 它们遵循与以下相同的平等规则: 如果这两个值在预期值的一小部分 % 增量范围内,则断言将通过。LESS_OR_EQUALGREATER_OR_EQUALTEST_ASSERT_EQUAL_FLOATTEST_ASSERT_EQUAL_DOUBLE

字符串断言

TEST_ASSERT_EQUAL_STRING(expected, actual)
比较两个以 null 结尾的字符串。 如果任何字符不同或长度不同,则失败。

TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)
比较两个字符串。 如果任何字符不同,则失败,在 len 字符之后停止比较。

TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message)
比较两个以 null 结尾的字符串。 如果任何字符不同或长度不同,则失败。 失败时输出自定义消息。

TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)
比较两个字符串。 如果任何字符不同,则失败,在 len 字符之后停止比较。 失败时输出自定义消息。

指针断言

大多数指针操作只需使用上面的整数比较即可执行。 但是,为了清楚起见,添加了几个特殊情况。

TEST_ASSERT_NULL(pointer)
如果指针不等于 NULL 则失败

TEST_ASSERT_NOT_NULL(pointer)
如果指针等于 NULL 则失败

内存断言

TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)
比较两个内存块。 对于不能被强制执行为标准类型的类型来说,这是一个很好的通用断言...... 但是,由于它是内存比较,因此您必须小心数据类型被封装。

我们在工程Unity文件夹中创建test_unity.c文件,用于填写unity测试程序,我们先定义测试函数

/** test_unity.c**  Created on: Feb 14, 2024*      Author: Administrator*/#include "unity.h"void test_unity(void)
{}

并且将void test_unity(void)函数添加到main.h中

/* USER CODE BEGIN EFP */
void test_unity(void);
/* USER CODE END EFP */

然后在main.c中调用 test_unity函数。

  /* USER CODE BEGIN 2 */test_unity();/* USER CODE END 2 */

这时候编译是可以通过的。

我们接下来开始编写测试函数。

/** test_unity.c**  Created on: Feb 14, 2024*      Author: Administrator*/#include "unity.h"
#include <stdio.h>
#include <stdbool.h>bool IsTrue(bool in)
{return in;
}void testFunc(void)
{TEST_ASSERT_TRUE(IsTrue(true));TEST_ASSERT_TRUE(IsTrue(false));
}void test_unity(void)
{printf("\r\n*****hello unity*******\r\n");RUN_TEST(testFunc);UNITY_END();
}

这个时候再编译就会报错

因为我们有两个函数未实现,

/** test_unity.c**  Created on: Feb 14, 2024*      Author: Administrator*/#include "unity.h"
#include <stdio.h>
#include <stdbool.h>void setUp(void)
{
}void tearDown(void)
{
}bool IsTrue(bool in)
{return in;
}void testFunc(void)
{TEST_ASSERT_TRUE(IsTrue(true));TEST_ASSERT_TRUE(IsTrue(false));
}void test_unity(void)
{printf("\r\n*****hello unity*******\r\n");RUN_TEST(testFunc);UNITY_END();
}

这时候我们就可以编译过了。

用例的初始化:setUp()
用例的释放:tearDown()
这俩分别是在每个case之前和之后都会运行一次。
setUp() 方法用于用例的初始化,比如在执行测试用例之前进行的变量定义、初始化等。
tearDown() 方法则用于用例的释放,比如测试后的清理工作,比如数据还原、资源释放等。

运行输出如下:

符合预期,我们再写几个,完善一下测试程序。

/** test_unity.c**  Created on: Feb 14, 2024*      Author: Administrator*/#include "unity.h"
#include <stdio.h>
#include <stdbool.h>void setUp(void)
{
}void tearDown(void)
{
}bool IsTrue(bool in)
{return in;
}void testBoolPassFunc(void)
{TEST_ASSERT_TRUE(IsTrue(true));
}void testBoolFailFunc(void)
{TEST_ASSERT_TRUE(IsTrue(false));
}void testIntFunc(void)
{TEST_ASSERT_EQUAL_INT(1,1);uint8_t v = 10;TEST_ASSERT_EQUAL_INT(10, v);
}void testArrayPassFunc(void)
{uint8_t a[3] = {1,2,3};uint8_t b[3] = {1,2,3};TEST_ASSERT_EQUAL_HEX8_ARRAY(a, b, 3);
}void testArrayFailFunc(void)
{uint8_t a[3] = {1,2,3};uint8_t b[3] = {1,2,4};TEST_ASSERT_EQUAL_HEX8_ARRAY(a, b, 3);
}void testBitsFunc(void)
{TEST_ASSERT_BITS(0xF0, 0x35, 0x34);
}void testFloatPassFunc(void)
{// 这些断言验证actual参数处于expected参数的+/-delta之间。TEST_ASSERT_FLOAT_WITHIN(0.4, 1.2, 1.5);
}void testFloatFailFunc(void)
{// 这些断言验证actual参数处于expected参数的+/-delta之间。TEST_ASSERT_FLOAT_WITHIN(0.2, 1.2, 1.5);
}void testStringFunc(void)
{char *s = "hello unity";TEST_ASSERT_EQUAL_STRING(s, "hello unity");
}void testStringMessageFunc(void)
{char *s = "hello unity";TEST_ASSERT_EQUAL_STRING_MESSAGE(s, "hello unity!", "I'm a message!");
}void test_unity(void)
{printf("\r\n*****hello unity*******\r\n");RUN_TEST(testBoolPassFunc);RUN_TEST(testBoolFailFunc);RUN_TEST(testIntFunc);RUN_TEST(testArrayPassFunc);RUN_TEST(testArrayFailFunc);RUN_TEST(testBitsFunc);RUN_TEST(testFloatPassFunc);RUN_TEST(testFloatFailFunc);RUN_TEST(testStringFunc);RUN_TEST(testStringMessageFunc);UNITY_END();
}

当我们把失败的case都去掉后。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/258255.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

相机图像质量研究(22)常见问题总结:CMOS期间对成像的影响--光学串扰

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

LeetCode、338. 比特位计数【简单,位运算】

文章目录 前言LeetCode、338. 比特位计数【中等&#xff0c;位运算】题目链接与分类思路位运算移位处理前缀思想实现 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java…

快速学习Spring

Spring 简介 Spring 是一个开源的轻量级、非侵入式的 JavaEE 框架&#xff0c;它为企业级 Java 应用提供了全面的基础设施支持。Spring 的设计目标是简化企业应用的开发&#xff0c;并解决 Java 开发中常见的复杂性和低效率问题。 Spring常用依赖 <dependencies><!-…

OpenCV入门:图像处理的基石

在数字图像处理领域&#xff0c;OpenCV&#xff08;开源计算机视觉库&#xff09;是一个不可或缺的工具。它包含了一系列强大的算法和函数&#xff0c;使得开发者可以轻松地处理图像和视频数据。本文将带你走进OpenCV的世界&#xff0c;了解其基本概念和常见应用。 1. OpenCV简…

【51单片机】DS18B20(江科大)

一、DS18B20温度传感器 1.DS18B20介绍 DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点 测温范围 :- 55℃到125℃ 通信接口:1-Wire(单总线) 其它特征:可形成…

Crypto--RSA

题目&#xff1a;RSA&#xff08;BUUCTF-CRYPTO-RSABUUCTF在线评测&#xff09; 解题过程&#xff1a;直接利用RSAtool工具&#xff08;RSA-Tool 2(RSA算法辅助工具)V1.7绿色版下载 - 下载吧 (xiazaiba.com)&#xff09;解题。

数据结构(4) 链表(链式存储)

链表&#xff08;链式存储&#xff09; 单链表定义基本操作的实现单链表的插入按位序插入指定节点的前插指定节点的后插 单链表的删除 小结 单链表 定义 顺序表优点:可随机存取&#xff0c;存储密度高&#xff0c;缺点:要求大片连续空间&#xff0c;改变容量不方便。 单链表优…

云计算基础-虚拟化概述

虚拟化概述 虚拟化是一种资源管理技术&#xff0c;能够将计算机的各种实体资源&#xff08;如CPU、内存、磁盘空间、网络适配器等&#xff09;予以抽象、转换后呈现出来并可供分割、组合为一个或多个逻辑上的资源。这种技术通过在计算机硬件上创建一个抽象层&#xff0c;将单台…

人工智能学习与实训笔记(七):神经网络之推荐系统处理

九、模型压缩与知识蒸馏 出于对响应速度&#xff0c;存储大小和能耗的考虑&#xff0c;往往需要对大模型进行压缩。 模型压缩方法主要可以分为以下四类&#xff1a; 参数修剪和量化&#xff08;Parameter pruning and quantization&#xff09;&#xff1a;用于消除对模型表…

蓝桥省赛真题|简单:分数

题目链接&#xff1a;https://www.lanqiao.cn/problems/610/learning/?page1&first_category_id1&second_category_id3&tags2018&name%E5%88%86%E6%95%B0 题不难&#xff0c;但是可以帮助编程时好的习惯的养成&#xff0c;更加注意一些细节。 注意几个地方︰…

机器人专题:我国机器人产业园区发展现状、问题、经验及建议

今天分享的是机器人系列深度研究报告&#xff1a;《机器人专题&#xff1a;我国机器人产业园区发展现状、问题、经验及建议》。 &#xff08;报告出品方&#xff1a;赛迪研究院&#xff09; 报告共计&#xff1a;26页 机器人作为推动工业化发展和数字中国建设的重要工具&…

【RT-DETR有效改进】利用EMAttention加深网络深度提高模型特征提取能力(特征选择模块)

一、本文介绍 本文给大家带来的改进机制是EMAttention注意力机制&#xff0c;它的核心思想是&#xff0c;重塑部分通道到批次维度&#xff0c;并将通道维度分组为多个子特征&#xff0c;以保留每个通道的信息并减少计算开销。EMA模块通过编码全局信息来重新校准每个并行分支中…

【Qt】环境安装与初识

目录 一、Qt背景介绍 二、搭建Qt开发环境 三、新建工程 四、Qt中的命名规范 五、Qt Creator中的快捷键 六、QWidget基础项目文件详解 6.1 .pro文件解析 6.2 widget.h文件解析 6.3 widget.cpp文件解析 6.4 widget.ui文件解析 6.5 main.cpp文件解析 七、对象树 八、…

MySQL 基础知识(一)之数据库和 SQL 概述

目录 1 数据库相关概念 2 数据库的结构 ​3 SQL 概要 4 SQL 的基本书写规则 1 数据库相关概念 数据库是将大量的数据保存起来&#xff0c;通过计算机加工而成的可以进行高效访问的数据集合数据库管理系统&#xff08;DBMS&#xff09;是用来管理数据库的计算机系统&#xf…

指针的经典笔试题

经典的指针试题&#xff0c;让你彻底理解指针 前言 之前对于指针做了一个详解&#xff0c;现在来看一些关于指针的经典面试题。 再次说一下数组名 数组名通常表示的都是首元素的地址&#xff0c;但是有两个意外&#xff0c;1.sizeof&#xff08;数组名&#xff09;这里数组名…

stm32:pwm output模块,记录一下我是用smt32,输出pwm波的记录--(实现--重要)

我是实现了输出pwm波&#xff0c;频率固定&#xff0c;占空比可以不断调整的方法&#xff0c;将PA0接到示波器上&#xff0c;可以看到是一个标准的PWM波&#xff0c;如图下面示波器图。 1&#xff0c;首先是ioc的配置 我刚开始设置的分频的倍数是7199&#xff0c;使得分频的太…

Mac M2芯片配置PHP环境

Mac M2芯片配置PHP环境 1. XAMPP2. PHPBrew(PHP版本管理)安装php7.4.33版本 参考 1. XAMPP 官网地址 https://www.apachefriends.org/ 安装 安装完成 web server打开后&#xff0c;在打开localhost 成功&#xff01; 2. PHPBrew(PHP版本管理) 官方文档 https://github.co…

【教程】C++语言基础学习笔记(五)——Vector向量

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【C语言基础学习】系列文章 第一章 《项目与程序结构》 第二章 《数据类型》 第三章 《运算符》 第四章 《流程控制》 第五章…

【OpenAI Sora】开启未来:视频生成模型作为终极世界模拟器的突破之旅

这份技术报告主要关注两个方面&#xff1a;&#xff08;1&#xff09;我们的方法将各种类型的视觉数据转化为统一的表示形式&#xff0c;从而实现了大规模生成模型的训练&#xff1b;&#xff08;2&#xff09;对Sora的能力和局限性进行了定性评估。报告中不包含模型和实现细节…

jenkins 发布远程服务器并部署项目

安装参考另一个文章 配置maven 和 jdk 和 git 注意jdk的安装目录&#xff0c;是jenkins 安装所在服务器的jdk目录 注意maven的目录 是jenkins 安装所在服务器的maven目录 注意git的目录 是jenkins 安装所在服务器的 git 目录 安装 Publish Over SSH 插件 配置远程服务器 创…