工作中,和同事对测试异常的最佳方法产生了分歧。
我是比较欣赏JUnit4的@Test(expected=FooException.class)的啦,觉得这样多清爽啊,多declarative啊,再不用写那么一大坨try-fail-catch了。
不过同事(以下简称S)不这么认为。他觉得try-fail-catch挺好的,价格便宜,量又足,我们一直用它。而JUnit 4和TestNG提供的这个功能容易引诱程序员犯错误。
S给提出了一个挑战:
public void testDoSomethingBad() {
initializeSomething();
try {
doSomethingBad();
fail();
} catch (FooException e) {}
}
这里面initializeSomething()的作用是初始化到某一个状态,这个过程不应该出错,而到了这个状态之后,doSomethingBad()才会抛异常。
然后他坚持认为这种情况是最普遍的情况。而用annotation虽然看上去很美,但是可能邪恶地诱惑程序员写出不准确的测试,造成false positive,比如,initializeSomething()抛了一个异常。
当然,我们对这种情况的常见程度各执己见。也没什么说的。但是,后来我想,其实,这个测试换成自然语言表达是什么呢?大概是这样吧?
- initializeSomething()不许出错
- 在initializeSomething()之后doSomethingBad()要出错
那么,为什么不把这两个要求写成两个测试呢?
@Test
public void testInitializeSomething() {
initializeSomething();
}
@Test(expected=FooException.class)
public void testDoSomethingBadAfterInitializeSomething() {
initializeSomething();
doSomethingBad();
}
只要我们写测试的时候不要总想着“聪明”地实现,而是直白地用代码表示需求,不就没问题了么?
再说一说我为什么这么讨厌这个try-fail-catch。它有几个我深恶痛绝的毛病。
- 它等于代码里的逻辑分支。如果没有抛异常,它执行fail(),而如果抛了异常,它进入catch()。而测试里的逻辑分支味道很坏。它让你的代码容易出错(比如,你忘了fail怎么办?测试一样是绿的,但是你的bug还躲在那)。而且,它让测试代码不能达到100%的分支覆盖率。本来如果用annotation的话,如果出现了initializeSomething()抛出异常的情况,覆盖率马上不是100%了,你可以很容易地发现问题。
- 冗长烦琐。测试写的不象spec,而象过程形代码。
- 这个try-fail-catch只在你检查Exception的时候成立。如果万一你要检查一个Error甚至是JUnit的AssertionFailedError,完了,你连fail()抛的异常也给截获了。
今天早晨,忽然灵机一动,其实,还有一个方法的。比如,在你自己的BaseTest的基类里面,你可以实现一个expectException()的函数,然后这么用:
public void testDoSomethingBad() {
initializeSomething();
expectException(FooException.class);
doSomethingBad();
}
这样,在runTest()结束前,可以检查是否存在一个exception expectation,如果有,就catch住抛出来的异常,然后进行检查。而如果没出现异常,直接就报错。这样,不就没问题了?还可以进一步抽象,弄个ExceptionExpectation的接口,这样客户代码可以灵活地登记并且重用任何的异常期待,不仅仅局限于检查异常类型和错误信息了。
当然,这是在JUnit 3.8。
分享到:
相关推荐
虽然本书还很难覆盖完美测试应具备的各种方法和实践,但目的在于抛砖引玉,使读者能通过最有效的手段(包括方法、技术和工具)完成所有必要的测试,实现事先所要求的需求和代码的测试覆盖率,最终能准确地给出软件...
评估测试工作的有效性 测试员 执行测试。 职责: 执行测试 记录结果 从错误中恢复 记录变更请求 测试系统管理员 确保测试环境和资产得到管理和维护。 职责:管理测试系统 分配和管理角色对测试系统的访问权 ...
第5章 有效模糊测试的需求 5.1 可重现性和文档记录 5.2 可重用性 5.3 过程状态和过程深度 5.4 跟踪、代码覆盖和度量 5.5 错误检测 5.6 资源约束 5.7 小结 第二部分 第6章 自动化测试和测试数据生成 6.1 自动化测试的...
软件测试规范 目 录 一.概述 ............................................................................................................................................................ 1 二 软件...
⼤数据测试 ⼤数据测试 什么是⼤数据 什么是⼤数据 ⼤数据是指⽆法在⼀定时间范围内⽤传统的计算机技术进⾏处理的海量数据集。... 消息队列,消息队列长度会怎么样?等等 必备的测试环境 必备的测试环境 ⼤数据测试不同
针对现有的并行模糊测试在测试效率、资源利用率以及异常处理上的局限性,围绕测试资源的生成、使用及容错三个方面提出了一种动态资源感知的系统化解决方案。针对测试环境在大规模和多场景两个维度快速搭建的需求,...
"异常 " "备份服务器业务端操作情况 "正常 "异常 " "PACS业务端操作情况 "正常 "异常 " "PACS数据端操作情况 "正常 "异常 " "数据表检测情况 "正常 "异常 " "业务流程检查情况 "正常 "异常 " "备份恢复测试异常情况...
1、最基本的先保证以正反两大类用例全面覆盖需求(且先不论需求中的主次),其中包括 (1)细化各种数据类型,达到有效和无效数据类型的覆盖 (2)细化各种流程分支(考虑主流程、辅流程、异常处理、出错...
RAD方法使用高效开发工具,开发者能够非常迅速地设计出系统的基本屏幕,允许用户在开发周期中很早就能见识到系统将来看起来怎么样,避免了在传统开发项目中长篇大论并且枯燥难懂的说明。 IBM的Dr.Harlan Mills提出...
测试用例设计时一般做如下考虑: 1、最基本的先保证以正反两大类用例全面覆盖需求(且先不论需求中的主次),其中包括 (1)细化各种数据类型,达到有效和无效数据类型的覆盖 (2)细化各种流程分支(考虑主流程、辅流程...
对于一个比较成熟的业务系统来说,...在优化系统的过程中,最有效的手段就是对系统进行性能测试。然后对测试过程中收集的数据进行分析,找出问题所在,不断对系统进行优化,最终达到系统在大业务量时稳定运行的目的。
我们通过在有效的强子模型中包含一个新的手征对称但U(1)A异常的术语来测试该想法,该术语描述重子及其在镜像分配中的手性伙伴。 该术语增强了手性伙伴向重子和η介子(例如N(1535)→Nη)的衰减。 此外,出现了...
传统异常检测模型往往基于内容特征,随着攻击手段的提高,该方法易于被绕过,因此图挖掘技术逐渐成为了国内外学术研究的热点。为了提高异常检测的准确率,提出了一种基于长短时记忆网络的动态图模型异常检测算法。...
测试异常 第三章管理测试 测试的组织 检查覆盖率 编写测试库 对测试库的测试 编写测试用具 通过网络运行测试 自动运行测试 第四章与代码一起发布测试 测试文档覆盖率 测试整个模块 让用户决定 让用户决定(续) 模块...
将最底层的子要求转换为测试 把Cruise Seatch转换为步骤、再次转换为测试 选择主题路径: 查看转换结果: 练习2:从Office导入需求到QC 参考 QCMSWordAddin.pdf 和 QCMSExcelAddin.pdf 项目管理员可以...
该方法为捕捉错误,抛出异常信息,快速定位构件集成中的故障位置,准确发现故障原因提供了一种非常有效的途径。该方法的使用减少了构件集成测试中粘贴代码产生的冗余,提高了测试的灵活性,实现了高效的软件复用,缩短了...
在行人跟踪方面,在时空上下文跟踪算法的基础上结合卡尔曼滤波器,有效改进了复杂背景中的遮挡问题。在异常分析方面,将跟踪得到的目标轨迹按照轨迹形状进行分类,得到场景中的正常轨迹集;将这些轨迹集作为后续处理...
我们计算了QCD中四个循环对尖峰异常尺寸的铁离子贡献,作为小尖角的扩展。 作为副产品,我们还获得了四环HQET波函数异常维的各个项。 我们在小角度上获得的新结果对四环尖点反常维度中物质项的确切角度依赖性提供了...
如果空指针的内部表达不是 0 会怎么样? o 6.4 NULL 是什么, 它是怎么定义的? o 6.5 在使用非全零作为空指针内部表达的机器上, NULL 是如何定义的? o 6.6 如果 NULL 定义成 #define NULL ((char *)0) 难道不就...
网络安全技术测试题全文共14页,当前为第1页。网络安全技术测试题 网络安全技术测试题全文共14页,当前为第1页。 网络安全技术测试题 学号______________ 姓名____________ 联系方式 ___________________ 网络安全...