嵌入式软件测试基础概述

测试是传统软体开发的最后一步。整个软体开发过程,需要收集要求、进行高层次的设计、详细设计、製作程式码、进行部份单元测试,然后整合,最后才开始最终测试。

最佳的开发实践应包含程式码检查这个步骤。然而程式码检查一般只能找出70%的系统错误,因此完美的测试环节绝对必不可少。测试就像个复式记帐系统,可以确保将缺陷扼杀在最终推出的产品之前。

在所有其它的工程实践中,测试都被视为基本环节。比如,在美国,每一座联邦政府出资修建的桥都必须经过大量的风洞测试。而在软体领域,测试并没有很受重视。儘管测试是所有工程实践準则的关键部份,但编写测试程式却感觉是在浪费时间。好在嵌入式系统设计界内的许多领域已经将测试作为其工作的核心部份,他们认识到将这个关键步骤放在计画末期极不明智,因而主张同步地编写测试程式和应用程式。

嵌入式系统软体测试在诸多方面都与应用软体测试一样。不过,应用测试与嵌入式系统测试之间还是存在一些重要差异。嵌入式开发人员一般会用到基于硬体的测试工具,而这类工具通常不会用于应用开发过程中。此外,嵌入式系统一般都有些独一无二的特性,这些特性应该在测试计划中得以体现。本文将介绍测试和测试案例开发的基础知识,并指出整个嵌入式系统测试工作的特有细节。

何时测试以及如何测试

从图1可以看出,在可行的条件下,测试应尽早展开。一般来讲,最早的测试是由最初的开发人员进行的模组或单元测试。遗憾的是,开发人员大多对如何建构一整套测试例程以进行测试所知不足。由于精心设计测试例程通常直到整合测试时才能使用,因此许多在单元测试过程中就能找出的缺陷直到整合测试时才会被发现。比如,硅谷的一家大型网路设备厂商为找出其软体整合问题的关键塬因,进行了一项研究。这家厂商发现,在计画整合阶段找出的缺陷中,有70%是由在整合之前从没被执行过的程式所产生的。

图1:改正问题的成本。

单元测试:开发人员在单独进行模组级测试时一般是编写存根程式码(stub code)取代余下的系统软硬体。在开发週期的这个环节,测试主要侧重于程式码的逻辑性能。

通常,开发人员会分别使用某些平均值、高值或低值、以及某些超出範围的值(以测试程式码的异常处理功能)进行测试。但这些基于‘黑盒子’的测试仅能对模组中整个程式码的一部份进行测试。

回归测试:测试不应是一劳永逸的。每次修改程式后都应该重新进行测试,以确保这些更改不会无意中‘误伤’某些不相关的行为。

称为回归测试的这类测试,一般是透过测试脚本自动进行的。比如,如果你设计了一组100个输入/输出(I/O)测试,回归测试脚本会自动执行这100个测试,然后将输出与一组‘黄金标準’输出进行对比。每次对程式码的任何部份进行修改时,都要对包含被修改程式码的整个程式执行整套回归测试程式包,以确维修改过程中不会‘误伤’其余程式码。

嵌入式软件测试

测试什么

因为没有一个实际的测试集可以证明一个程式是正确的,因此关键问题变成了哪个测试子集最有可能检测到最多的错误。选择合适的测试例程的问题被称为测试例程设计。虽然存在数十种测试案例的设计方法,但它们通常可归为两种截然不同的方法:功能测试和覆盖测试。

功能测试(也称为黑盒子测试)选择可评估实现与需求规格符合程度的测试。覆盖测试(也称为白盒子测试)选择可执行程式码某些部份的测试例程。(过后,将详细讨论这两种方法。)

这两种测试都是对嵌入式设计进行严格测试所必须的。其中,覆盖测试表示程式码的稳定性,所以这种测试是用于已经完成或将近完成的产品的。另一方面,可在编写要求文件时,同时编写功能测试。

事实上,从功能测试开始入手,可以大幅地降低重复劳动和重写测试案例的工作。因此,在我看来,要先考虑功能测试。

每个人都同意先编写功能测试这个观点,有人认为,功能测试在系统整合阶段(而不是在单元测试时)最有用。以下是整合功能测试和覆盖测试方法的一个简单处理流程:

1.找出哪些功能未被功能测试完全覆盖。

2.找出每个功能的哪些部份没被执行。

3.找出需要哪些额外的覆盖测试。

4.执行新增的额外测试。

5.重复以上步骤。

何时停止测试?

最通用的停止标準(按可靠性排序)如下:

1.老板命令停止测试

2.新的测试週期找到的新缺陷少于X个

3.在没有发现任何新缺陷的情况下已经满足了某个覆盖阀限

无论你多么彻底地测试了程式,都无法保证找出所有缺陷。这引发了另一个有趣的问题:你可容忍多少缺陷?假设在极端软体压力测试过程中,你发现系统每进行大约20小时的测试就会锁定。你仔细地检查程式,但是仍无法找出这个错误的根源。这个时候你应该提供产品吗?

多少测试才‘足够好’?这个我说不好。但遵循一些久经时间考验的规则总是好的:“如果方法Z预估Y行程式码中的缺陷少于X个,那么就可放心地发佈程式了。”也许有一天会出现这种标準。编程产业仍然相对年轻,还达不到类似建筑业那样的成熟度。

许多厚厚的建筑手册和大本规格是多年经验的结晶,它们可为建筑师、土木工程师和结构工程师提供按工期在预算内、建造一栋安全建筑所需的全部资讯。偶尔虽仍会有建筑倒塌,但毕竟很少见。在编程产业制订出类似标準前,“多少测试才足够?”就是个主观判断问题。

嵌入式软件测试

选择测试案例

在理想情况下,你可能想要测试程式中每一个可能的行为。这意味着每一种可能的输入组合或者每一种可能的判定路径至少测试一次。

这是个崇高但完全不切实际的目标。比如,Glen Ford Myers在其《软体测试的艺术》一书中就描述了一个只用五个判定条件就可有1014个不同执行路径的小程式。他指出,如果你能够每五分鐘就能编写、执行并验证一个测试例程的话,那么全面彻底地测试完这个小程式需要10亿年时间。

显然,理想的状况是无法实现的,因此你必须採用接近这种理想状况的标準。如你所见,功能测试与覆盖测试相结合可以提供合理的次优选择方案。基本方法是选择最有可能发现错误的测试(一部份功能测试,一部份覆盖测试)。

1.功能测试

功能测试一般称为黑盒子测试,因为在编写功能测试的测试例程时并没有涉及实际的程式码。换句话说,没有触及到‘盒子内’。嵌入式系统有输入和输出,并在输入和输出之间执行某些演算法。黑盒子测试是根据对哪些输入应该是可接受的以及这些输入应与输出有何种关係的了解来进行的。黑盒子测试完全不了解输入与输出之间的演算法是如何实现的。黑盒子测试的示例包括:

压力测试:有意使输入通道、记忆体缓衝器、磁碟控制器、记忆体管理系统等过载的测试

边界值测试:表示特定範围内的‘边界’的输入(例如,对于整数输入而言,是最大和最小整数以及?1、0、+1);以及应使输出在输出範围的类似边界出现跨变的输入值。

异常测试:能触发故障模式或异常模式的测试。

错误推测:根据以前的软体测试经验或者从测试类似程式获得的经验进行的测试。

随机测试:通常,这是效率最低的一种测试方法,但却仍然广泛用于评估用户介面程式码的强韧性。

性能测试:由于性能预期是产品要求的一部份,因此性能分析属于功能测试的範畴。

由于黑盒子测试仅取决于程式要求及其I/O行为,因此一旦完成功能要求的编写,即可开发这类测试。这使得黑盒子测试例程的开发可以与余下的系统设计同步进行。

与所有测试一样,功能测试应被设计得具有破坏性,也即,要试图证明程式无法工作。这包括使输入通道过载、随意地敲打键盘,以及故意地做程式员认为会破坏其程式的所有事情。

作为研发产品经理,这是我的主要测试方法之一。如果产品在经过40个小时的极限测试(abuse testing)后,并没发现任何严重或者致命的缺陷,那么就可以发佈这个产品了。如果找到了一个重大的缺陷,那么修正这个缺陷后,还必须重复前面的测试步骤。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值