说明

主流语言都有测试框架,在嵌入式领域特别是资源紧缺的单片机工程中没有合适的测试框架。本文发布一种简单的C语言测试框架SCUNIT,可以应用于嵌入式领域。

测试环境

本框架是基于标准C语言编写,对平台无要求,测试环境如下:

单片机:STM32F407

RTOS:RT-THREAD

测试用例测试的是基于链表的一个路由表结构。

API

void scunit_load(PrintFunc func);

void scunit_add_suite(char *name);

void scunit_add_test(char *name, SCUnitFunc func);

void SCUNIT_ASSERT(bool condition, char *tag);

void SCUNIT_ASSERT_MESSAGE(bool condition, char *tag, char *message);

void SCUNIT_PRINT(char *format, ...);

scuit_load函数是scuit模块载入函数,需要提供打印接口。比如在标准c语言环境,可以将printf作为参数传入。在单片机应用里,可以将串口打印函数传入。本文的测试用例,是将SEGGER RTT的打印函数作为参数传入。

/**

* @brief 使用RTT输出

*/

void console_rtt(char *format, ...)

{

static char log_buf[RT_CONSOLEBUF_SIZE];

va_list args;

va_start(args, format);

int length = rt_vsnprintf(log_buf, sizeof(log_buf) - 1, format, args);

if (length > RT_CONSOLEBUF_SIZE - 1) {

length = RT_CONSOLEBUF_SIZE - 1;

}

log_buf[length] = 0;

SEGGER_RTT_printf(0, log_buf);

va_end(args);

}

scunit_load(console_rtt);

源码

scunit.h

/**

* Copyright (c), 2019-2019

* @file cunit.h

* @brief 单元测试头文件

* @verbatim

* Change Logs:

* Date           Author       Notes

* 2019-08-31     jdh          新建

* @endverbatim

*/

#ifndef CUNIT_H

#define CUNIT_H

#include "stdio.h"

#include "stdbool.h"

#include "stdint.h"

#include "stdlib.h"

#include "string.h"

#include "stdarg.h"

typedef void (*PrintFunc)(char *format, ...);

typedef void (*SCUnitFunc)(void);

void scunit_load(PrintFunc func);

void scunit_add_suite(char *name);

void scunit_add_test(char *name, SCUnitFunc func);

void SCUNIT_ASSERT(bool condition, char *tag);

/**

* @brief 带信息输出的断言

* @param condition: 条件

* @param message: 断言失败时输出

*/

void SCUNIT_ASSERT_MESSAGE(bool condition, char *tag, char *message);

void SCUNIT_PRINT(char *format, ...);

#endif

scunit.c

/**

* Copyright (c), 2019-2019

* @file cunit.c

* @brief 单元测试主文件

* @verbatim

* Change Logs:

* Date           Author       Notes

* 2019-08-31     jdh          新建

* @endverbatim

*/

#include "scunit.h"

#define CUNIT_PRINT_SIZE_MAX            128

static PrintFunc _print = NULL;

static char *_func_name = NULL;

void scunit_load(PrintFunc func)

{

_print = func;

}

void scunit_add_suite(char *name)

{

_print("nSuite:%sn", name);

}

void scunit_add_test(char *name, SCUnitFunc func)

{

_func_name = name;

_print("-------------------->case:%s beginn", _func_name);

func();

_print("-------------------->case:%s endn", _func_name);

}

void SCUNIT_ASSERT(bool condition, char *tag)

{

if (condition) {

_print("%s tag:%s CUNIT_ASSERT passn", _func_name, tag);

} else {

_print("%s tag:%s CUNIT_ASSERT failn", _func_name, tag);

}

}

/**

* @brief 带信息输出的断言

* @param condition: 条件

* @param message: 断言失败时输出

*/

void SCUNIT_ASSERT_MESSAGE(bool condition, char *tag, char *message)

{

if (condition) {

_print("%s tag:%s CUNIT_ASSERT passn", _func_name, tag);

} else {

_print("%s tag:%s CUNIT_ASSERT fail:%sn", _func_name, tag, message);

}

}

void SCUNIT_PRINT(char *format, ...)

{

static char buf[CUNIT_PRINT_SIZE_MAX];

va_list args;

va_start(args, format);

int length = vsnprintf(buf, sizeof(buf) - 1, format, args);

if (length > CUNIT_PRINT_SIZE_MAX - 1) {

length = CUNIT_PRINT_SIZE_MAX - 1;

}

buf[length] = 0;

_print(buf);

va_end(args);

}

测试代码

载入测试模块:

scunit_load(console_rtt);

1

测试用例:

/**

* Copyright (c), 2019-2019

* @file test_routing_table.c

* @brief 路由表测试主文件

* @verbatim

* Change Logs:

* Date           Author       Notes

* 2019-08-30     jdh          新建

* @endverbatim

*/

#include "test_routing_table.h"

#include "routing_table.h"

#include "test.h"

#define MAX_TEST_NUM                100

static void test_case0(void);

static void test_case1(void);

void test_routing_table_run(void)

{

scunit_add_suite("test_routing_table");

scunit_add_test("case0", test_case0);

scunit_add_test("case1", test_case1);

}

static void test_case0(void)

{

bool result = false;

uint8_t port = 0;

routing_table_add(0x1234567812345678, 1);

result = routing_table_query(0x1234567812345678, &port);

SCUNIT_ASSERT(result && port == 1, "1");

routing_table_delete(0x1234567812345678);

result = routing_table_query(0x1234567812345678, &port);

SCUNIT_ASSERT(result == false, "2");

routing_table_add(0x1234567812345679, 12);

result = routing_table_query(0x1234567812345679, &port);

SCUNIT_ASSERT(result && port == 12, "3");

}

static void test_case1(void)

{

uint64_t t1 = get_local_time_us();

for (uint32_t i = 0; i < MAX_TEST_NUM; i++) {

routing_table_add(i, i);

}

uint64_t t2 = get_local_time_us();

int delta = t2 - t1;

SCUNIT_PRINT("add %d consume time:%ldus single:%ldusn", MAX_TEST_NUM, delta, delta / MAX_TEST_NUM);

bool result = false;

uint8_t port = 0;

routing_table_add(1, 5);

for (uint32_t i = 0; i < 5; i++) {

t1 = get_local_time_us();

routing_table_query(i, &port);

t2 = get_local_time_us();

delta = t2 - t1;

SCUNIT_PRINT("query ia:%x result:%d port:%d consume time:%ldusn", i, result, port, delta);

}

t1 = get_local_time_us();

for (uint32_t i = 0; i < MAX_TEST_NUM; i++) {

routing_table_delete(i);

}

t2 = get_local_time_us();

delta = t2 - t1;

SCUNIT_PRINT("delete %d consume time:%ldus single:%ldusn", MAX_TEST_NUM, delta, delta / MAX_TEST_NUM);

test_case0();

}

测试输出

0> Suite:test_routing_table

0> -------------------->case:case0 begin

0> case0 tag:1 SCUNIT_ASSERT pass

0> case0 tag:2 SCUNIT_ASSERT pass

0> case0 tag:3 SCUNIT_ASSERT pass

0> -------------------->case:case0 end

0> -------------------->case:case1 begin

0> add 100 consume time:2087us single:20us

0> query ia:0 result:0 port:0 consume time:34us

0> query ia:1 result:0 port:5 consume time:2us

0> query ia:2 result:0 port:2 consume time:33us

0> query ia:3 result:0 port:3 consume time:33us

0> query ia:4 result:0 port:4 consume time:33us

0> delete 100 consume time:1825us single:18us

0> case1 tag:1 SCUNIT_ASSERT pass

0> case1 tag:2 SCUNIT_ASSERT pass

0> case1 tag:3 SCUNIT_ASSERT pass

0> -------------------->case:case1 end

关键字:

嵌入式系统

C语言

单元测试框架

SCUNIT

编辑:什么鱼 引用地址:

http://news.eeworld.com.cn/mcu/ic512855.html

本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

c语言语法sc,适合于嵌入式系统的C语言单元测试框架:SCUNIT相关推荐

  1. 单片机c语言位运算写法,单片机与嵌入式系统中C语言的位运算小记

    原标题:单片机与嵌入式系统中C语言的位运算小记 编了个PIC的项目,对里的还是蛮有感悟的,特此记录一下. 譬如说,在程序中定义了一个char类型的变量, purge_short_enable_flag ...

  2. 嵌入式系统编程C语言之软件架构

    模块划分 模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求.C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能( ...

  3. c语言人机互动编程,单片机人机交互系统的C语言编程简介.ppt

    单片机人机交互系统的C语言编程简介 第5章 单片机人机交互系统的C51语言编程 5.1 单片机的输入/输出端口 5.2 LED数码管显示器 5.3 LED数码管点阵显示器 5.4 液晶显示器 5.5 ...

  4. python嵌入式系统开发_图解嵌入式系统开发之语言篇:初识Python

    一直忙于工作,似乎忘记了抽时间学习新知识,最近难得空闲,花了两天时间看了一下Python语法.作为工作中经常使用C/C++的人,学习Python的过程中最大的感受就是"似曾相识". ...

  5. 数据结构c语言哈夫曼编码译码系统,数据结构C语言哈夫曼编码译码

    <数据结构C语言哈夫曼编码译码>由会员分享,可在线阅读,更多相关<数据结构C语言哈夫曼编码译码(16页珍藏版)>请在人人文库网上搜索. 1.实训报告题 目: 哈夫曼树编码译码院 ...

  6. c语言 代码检查工具6,Ubuntu系统下C语言代码检查工具-- Splint

    看一下下面的代码(当然包括错误,以检验splint的功能): #include int main(int argc,char* argv[]){ int a=100; /*没有使用的变量*/ int ...

  7. 【C/C++开源库】适合单片机/嵌入式的C语言单元测试库

    文章目录 一.为什么需要单元测试? 二.单片机/嵌入式中为什么很少听说单元测试? 三.Unity 什么是Unity 如何使用Unity 剖析Unity 四.单元测试究竟是什么?什么是适合单元测试的代码 ...

  8. 嵌入式开发中C语言编程要点简述!

    在嵌入式Linux的C语言开发中,C语言的基本编程依然是最重要的内容.除此之外,与一般的C语言编程相比,嵌入式Linux的C语言编程有以下一些要点: 1.库函数与系统调用 在进行C语言编程的时候,使用 ...

  9. 期末复习【嵌入式系统】

    期末复习[嵌入式系统] 前言 推荐 期末复习 推荐 题型 押题 复习 总述 问题与思考: 教学内容介绍 问题与思考 第1章 嵌入式系统基础 问题与思考 1.1 引言 1.2 嵌入式系统的概述 1.2. ...

最新文章

  1. js数据类型判断和数组判断
  2. C# 中使用log4net 日志记录
  3. mysql 怎么修改成新字段_Mysql入门第一课《建表、改表、删表》
  4. 性能测试中的jvm监控
  5. -i https://pypi.tuna.tsinghua.edu.cn/simple -U
  6. fcntl函数的作用及应用场景
  7. 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
  8. 卓有成效的管理者(笔记)——序言
  9. 20211104 为什么相似矩阵的迹相同
  10. 微信语音识别_微信 语音识别_微信语音识别api - 云+社区 - 腾讯云
  11. vs code默认浏览器
  12. 数模【数据的拟合方法-总结】【温度与电阻的关系模型、农业生产实验模型、血药浓度模型、化工氯气生产等级模型、人口预测模型】
  13. 万洲金业:白银继续走高,预期缓慢冲高
  14. 老子《道德经》里的投资之道
  15. html+css仿QQ邮箱静态界面
  16. Latex加批注 更改
  17. 椭圆曲线加密(Elliptic Curve Cryptography, ECC)
  18. 最短路计数(入门最短路)
  19. Struts2的运行流程
  20. C语言中void*详解及应用

热门文章

  1. 【论文写作】毕业论文怎么写?写作步骤是什么?
  2. ORACLE集群日志收集,【RAC】Oracle RAC集群环境下日志文件结构
  3. c# 循环给数组每个元素加个逗号_C#规范整理集合和Linq
  4. css easyui,对比easyui和jwwui css
  5. mysql unix格式_将MySQL Unix-Timestamp格式转换为日期格式?
  6. Python: 函数参数传递机制
  7. 一起来梳理JVM知识点
  8. PHP实现图片的等比缩放和Logo水印功能示例
  9. Sonos拿1.3亿美金给员工发福利,中国厂商要拿什么拼?
  10. 数据挖掘与数据化运营实战. 3.2 目标客户的预测(响应、分类)模型