本文主要谈谈我对嵌入式软件开发中,有关测试的想法
写在前面(我遇到的现状)
在技术日新月异的今天,几乎各行各业都存在软件开发的身影。在中低端产品的嵌入式行业,尽管软件开发技术越来越先进,但是配套的软件测试技术和方法或者说管理远远没有跟上。就拿我目前任职的公司来说,代码开发过程中,都是由开发人员一边开发一边测试,没有独立的测试代码,所有测试都是手动完成的,并且回归(功能迭代)是常有的事儿。
或许,这种"高效"的开发测试流程有利于项目的快速成型与部署,美其名曰:“敏捷开发”,但这其实是有重大隐患的:
- 服务商快速开发,看似节省了测试的时间与流程管理的时间,实际不然,软件的漏洞风险实际转移给客户端了,这其实是对质量(软件)的忽视,软件也有质量???
- 如果拿单一项目来比较,规范的测试流程肯定是低效的,但是它的优势在于后期的迭代升级
- 对于多项目来说,引入自动化测试流程,实际能够提升团队协作能力与研发效率的
当我询问上级和同事为什么我们不自动化测试时,我收到了以下答复:
- 你无法对嵌入式系统进行自动化测试,它是依赖于硬件的。
- 嵌入式软件在嵌入式板上运行,因此模拟它很困难。
- 商用自动化测试太贵,引入自动化测试意味着工具和人员的投入成本。
简而言之,他们认为软件测试自动化是不可能的,我们别无选择,只能坚持目前的方法。
我理解他们的观点,在嵌入式领域创建一个模拟无数嵌入式设备(因项目而异)的环境的成本将是不成比例的(或者在单个错误可能造成致命破坏的情况下是必要的,例如在医疗或太空探索领域)。
然而,这仅适用于端到端测试。这并不意味着单元测试或集成测试同样困难。毕竟,嵌入式软件是逻辑的集合,单元测试应该能够捕获很多错误。事实上,在手动测试或市场中发现的大多数错误都是由于逻辑错误造成的,例如处理分支条件时的错误。这些不是应该通过手动测试来捕获的问题。它们是应该通过单元测试尽早发现的错误。对我来说,“嵌入式”并不是借口,恰恰是没有足够的软件测试知识,并顽固地坚持了当前的方法。
恰巧我本身所处汽车行业,在这个看似高大上的行业里,也许草台班子占了多数情况(我胡说的)。ASPICE是行业内认可的研发体系流程;我想,每一个项目实际按照ASPICE的方法论去走的公司寥寥无几,或者说,ASPICE所提供的方法论在不同的项目中的具体化不尽相同,这需要很高的技术素养跟管理素养,其实是一个高要求的标准。
为何要引入单元测试
自动化测试中有单元测试、集成测试、端到端测试,如果在目前仅依赖手工测试的环境下,应该首先引入什么类型的测试呢?
与集成和端到端测试相比,单元测试的优点是执行速度更快,使开发人员能够快速获得反馈。另外,由于单元测试测试的代码范围较小,因此编写测试代码相对容易,另外,大部分嵌入式产品最终都有较好的集成和端到端测试过程。
在嵌入式领域,提到自动化测试,第一个想法是自动化已经执行的手动测试。例如,想象建造一个可以代替人类执行手动测试的机器人。这与网络行业中通常由那些不熟悉正确测试实践的人通常考虑的捕获和重放工具的方式类似。此类工具仅替代手动测试,并不会导致测试效率或质量的显着提高。
由于引入自动化测试需要付出一定的努力,因此必须考虑投资的回报速度。从这个角度来看,我认为应该首先引入单元测试。单元测试提供更快的回报,有助于加快开发周期。甚至 Google 也建议大约 80% 的测试应由单元测试组成,将单元测试定位为测试金字塔中最重要的基础。推荐阅读《测试概述》
如果实际开发中,大部分测试完全依赖手动测试来捕获开发最后阶段的所有错误。这是比测试金字塔中已知的“冰淇淋蛋卷”模式更糟糕的情况(因为我们甚至没有单元测试,所以没有蛋卷)。
引入单元单元测试的好处
引入单元测试后,在项目开发的前期,无疑是痛苦的;因为,你需要在开发过程中编写大量的测试用例,发动头脑风暴来尽可能的覆盖多数情况。
但是,在项目的后期,能够节省大量的测试时间,提高开发测试的效率;这取决于你的项目,如果你的项目的整个生命周期甚至在Breakeven时间线的前面,那我可以不推荐你引入单元测试来开发。
最简单的单元测试框架
其实要设计或者要实现单元测试,最精简的要素就是:
- 断言
- 打印
如果考虑平台、编译器对齐,甚至可以直接在硬件平台上跑在板单元测试,我之前有实践过,借用了开源的Unity测试框架。通过一个串口外设打印断言信息。
尽管在板单元测试绝对正确,但是每次都需要烧录程序大大降低了开发的效率;因此我决定还是将单元测试放到PC平台上,当然这只针对非直接与硬件交互的软件逻辑部分。
下面是一个最简单的断言测试示例:
1 |
|
如果条件允许的话,公司愿意投入的话,商业工具是很好的选择,我这几年调研了不少商用嵌入式自动化测试工具,也30天试用过:
- HelixQAC
- Tessy
- Parasoft
- Cantata
遗憾的是,基本都是企业申请购买,并且价格也不亲民;博主至今也没正式在商用项目中用上其中一个。这里,我就推荐使用成熟的开源测试框架:
- Unity
- CppTest
- GoogleTest
插句题外话,在配套工具软件越来越成熟且封闭的今天,尽管大多数工具都是公司承担了支出,软件从业人员将来是否面临没有工具(不预先购买工具)就无法开发中大型商用项目的机会呢。就比如在大公司用工具开发,你的生产工具是公司的不是你个人的,你在每天的工具使用中已经不去关注工具底层的逻辑,直到某一天,你突然意识到,没有工具,我啥也做不了了。这是一个值得思考的问题!
结束语
下一章,我将基于GoogleTest的实践来阐述引入单元测试与普通开发的区别。
感谢Takeshi Kimata给我的启发,也欢迎大家去阅读他写的《嵌入式测试指导》