嵌入式,真的不需要单元测试?

嵌入式资讯精选 2020-10-21 00:00

前言

嵌入式行业摸爬滚打这几年,遇见有规范单元测试的项目寥寥无几。归根到底,无非是公司希望快速迭代出产品,有问题等客户反馈再说。当然,也有人认为是嵌入式行业都是小而美的产品居多,没有到一定量级之前,玩不起单元测试这种配置。正如做个蛋炒饭,并不需要安排主厨、二厨一般

不过出于对代码稳定性的追求,我认为还是应该着手了解一下单元测试的。毕竟,这是有效提高代码说服力的方式之一。

相信没有真正体验过单元测试好处的读者一看到"单元测试"这几个字,可能会出现以下两种反应之一:

  • 由于没有单元测试的经验,因此对采用这一方法去保证软件质量很好奇,也迫切地想要了解这一方法在项目中的实施

  • 曾经使用单元测试但效果不好,因为在嵌入式行业,时常要跟硬件打交道,单元测试很难检测硬件问题,所以往往一看到"单元测试"这几个字的反应就是"没用"

如果读者是第一种反应那很好,本文就是科普单元测试的基本要点。如果读者是第二种反应,那可能是对单元测试存在偏见,本系列文章也会介绍mock测试、错误注入等方式,使单元测试也能合理使用于嵌入式行业。



01

单元测试真的"无用"?



造成"单元测试无用论"的第一个原因是,运用这一方法的时机不恰当。不少项目在一开始真正关心质量的人很少,更谈不上采用一整套的方法论去保证质量了。产品在开发出来后发现到处存在问题,只会拆西墙补东墙根本就不能阻止问题一而再,再而三地出现。于是,开始想起单元测试。一声令下,整个项目开始做单元测试。单元测试以模块为单位,需要先把项目拆分出来。如果你的项目代码整体耦合程度较高的话,单元测试根本无从说起,拆分的工作会让你痛苦不已。

单元测试是一项耗时的工作,但管理者却往往希望在短期内看到效果。或者单元测试还没做到位管理层就等不及了,催你马上开始下一步的开发,结果只能是前功尽弃。正确的做法是:在项目的开始之初就引入单元测试。对于以前没有部署单元测试的项目,先只对新增加的、相对独立的模块做单元测试、并逐渐覆盖老代码。

第二个导致"单元测试无用论"的原因是,方法没有运用到位。要保证单元测试的有效性一定要引入另一个概念--代码覆盖。关于代码覆盖,我以后会另外再写一篇文章介绍。只有将单元测试和代码覆盖结合在一起,综合使用才能保证单元测试的效果。

02

最原始的"单元测试"



这里给读者展示一下,不使用任何单元测试框架时,是怎么做单元测试的。

下面简单以linux内核链表为例:

struct list_head { struct list_head *next, *prev;};/*定义一个结构体,只含有表示前驱和后继的指针,它就是我们的主角了*/#define LIST_HEAD_INIT(name) { &(name), &(name) }/*静态初始化*/#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name)/*动态初始化*/static inline void INIT_LIST_HEAD(struct list_head *list){ list->next = list; list->prev = list;}/*插入操作*//*删除操作*//*合并操作*/...

完整代码很长,这里没有必要全部贴出,能起演示作用就足够了。

现在就以INIT_LIST_HEAD函数为例,来考虑如何为这个函数设计测试用例。INIT_LIST_HEAD函数的实现是如此的简单,以至于很容易让人觉得为它设计单元测试是多余的。但是,从单元测试的角度看,只要不存在可行性问题就不应考虑因为简单而不对其进行验证。而且,放弃对之进行验证,以后会降低代码覆盖率。

做单元测试需要通过编写程序的方式来完成,所编写的用于测试的代码又称为单元测试用例。

下面我们来简单实现一个INIT_LIST_HEAD函数的测试用例:

int main(int argc,char **argv){ struct list_head list;
/*避免函数没有使用参数而引发waining*/ UNUSED(argc); UNUSED(argv);
list.prev = (struct list_head*)0xaaaa; list.next = (struct list_head*)0xbbbb;
INIT_LIST_HEAD(list);
/*检查前指针*/ if(list.prev != list){ return -1; }
/*检查后指针*/ if(list.next != list){ return -1; }
return 0;}

这应该是史上最简单的测试用例,功能非常简单,首先是故意将list结构体中的各个指针变量初始化为一个随机值。然后在调用完INIT_LIST_HEAD函数之后,检查各成员是否被初始化为了list,以判断INIT_LIST_HEAD函数是否正常工作了。注意:这个测试程序还有一个约定,返回-1代表测试失败,返回0表示测试成功。

这个测试用例是基于我们对INIT_LIST_HEAD函数有足够的了解之后编写的,这种测试方法在软件测试领域有个正儿八经的名字,叫白盒测试。

相信通过这个NIT_LIST_HEAD函数的测试用例,你已经初步建立起了对单元测试的印象。但是千万不要以为单元测试仅此而已,这是我刻意简化的结果。要完整地掌握单元测试,还要好好学习一段时间。

目前,对于这个小小的单元测试案例,还有很多的不足,下面简单罗列了几项:

  • 如果对于每一次检查都采取直接写if语句的形式,将造成大量的冗余代码,并且测试用例的编写效率也会很低。

  • 通过观察程序是否返回0或者是-1的方式来判断所有的测试是否通过并不直观,一旦出错也无法马上判断是那一步测试出了问题。毫无疑问,我们需要更加直观的方式来展示哪一步成功或者哪一步失败。

  • 一份严谨的测试用例,会有大量的判定。如果一个测试程序存在100次判定,其中出现了3次失败,那最终显示一个百分比的测试通过率会比较直观,比如可以显示97%的测试成功了。

后面会进一步介绍如何自己搭建一个简单实用的单元测试框架,来解决上面这些问题。也会陆续展开介绍mock方法、打桩、错误注入、代码覆盖、动态分析、静态分析、性能优化等内容。

03

总结


正如很多其他技巧,比如打桌球、滑雪一样,测试驱动开发也要花费相当长时间来练习。许多开发者已经接受了这种技术,而且再也不想回到从前“后期调试式编程”的方式去了。

它会使你的代码:

  •  产生的bug更少

  • 调试时间更短

  • 完全可以通过提交你的单元测试案例,来证明你的项目可靠性。

1.第二届国产嵌入式操作系统技术与产业发展论坛最新议程新鲜出炉!

2.嵌入式工程师求职回忆录~

3.芯片人才短缺25万,成立南京集成电路大学有用吗

4.CPU 执行程序的秘密,藏在了这 15 张图里

5.软硬件之间其实还有一个固件!你知道吗?

6.重磅,传AMD 300亿美元洽购赛灵思!最早下周达成交易

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

嵌入式资讯精选 掌握最鲜资讯,尽领行业新风
评论
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 52浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 36浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 47浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 101浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 105浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 66浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 44浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 90浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 83浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 40浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦