【测试原理与设计】理解常见异常值测试 |
您所在的位置:网站首页 › 异常测试用例是什么 › 【测试原理与设计】理解常见异常值测试 |
日常测试工作中,除了正常值的测试,我们还需要对参数的异常值进行测试,这其中要问起来,很多人都可以脱口而出需要测试null、空值等等。但是要问为什么要测?具体怎么测?测试的结果说明了什么问题?可能就不尽然能说的清楚了,我自己也是遇到过这种情况,反问自己这三个问题,说的出来一些,又好像不是那么确定,心里还是有点虚~ 1、Bug现象日常测试或生活中可能会出现如下现象: 登录用户,用户名处显示“你好,尊敬的用户null”。查看商品信息,显示商品信息为,商品名:null,价格:null。发送短信,短信信息显示“用户null,你的验证码为xxx”。这些现象对于普通用户来说,可能会产生疑惑,对于我们IT工程师来说,瞬间就会激起兴趣, 马上就能get到点。程序获取信息失败,又没有处理好null,把空格式化成了null。像这种还仅仅是显示的问题,有些null值可能会造成应用崩溃或逻辑错误,这对于测试来说可是个大单,这是bug,咱么测试要提! 2、关于null空指针异常虽然恼人但好在容易定位,更麻烦的是要弄清楚 null 的含义。比如,客户端给服务端的一个数据是 null,那么其意图到底是给一个空值,还是没提供值呢?再比如,数据库中字段的 NULL 值,是否有特殊的含义呢,针对数据库中的 NULL 值,写 SQL 需要特别注意什么呢? 3、透过现象看本质 3.1 null造成的空指针异常 3.1.1 Integer参数的自动拆箱我们学习Java都知道Java中对于基本数据类型和包装类是可以通过自动装箱拆箱来进行相互转换的,那么看一下下面这个简单的例子 给Integer类型的变量a赋值null,然后再传入getInt方法,+1后赋值给int类型的变量b @Test void testIntegerNull(){ Integer a = null; getInt(a); } private void getInt(Integer a){ int b = a + 1; }测试结果: 使用equals进行字符串的比较是最常见的业务之一了,看如下测试代码 1、对于传入getString方法的字符串a判断是否为pass,将a赋值为null传入 @Test void testStringNull(){ String a = null; getString(a); } private void getString(String a){ if (a.equals("pass")){ System.out.println("PASS"); } }测试结果: 2、对传入的字符串进行等值比较: @Test void testStringEqualsNull(){ String a = "a"; String A = null; getStringEquals(a,A); } private void getStringEquals(String a, String A) { if (A.equals(a)){ System.out.println("pass"); } }测试结果: 因此对于String类型的入参null,也是我们的测试点之一 3.1.3 ConcurrentHashMap的key、value平常我们最常用的就是HashMap了,而在并发时,HashMap有其弊端,开发可能会采用ConcurrentHashMap 关于ConcurrentHashMap,我目前在这里也无法说清,这里提供一篇文章做参考学习: HashMap? ConcurrentHashMap? 相信看完这篇没人能难住你! 先来看HashMap,对其进行key,value赋值null:@Test void test(){ HashMap map = new HashMap(); map.put(null,null); } 测试没有任何问题再来看ConcurrentHashMap,对其进行key,value赋值null:@Test void concurrentHashMapNull(){ ConcurrentHashMap map = new ConcurrentHashMap(); map.put("a",null); map.put(null,null); } 测试结果:![]() ![]() List也是我们最常用的集合之一了,当list为空时,查看如下测试代码 getList方法获取list并计算大小 @Test void testListNull(){ List list = null; getList(list); } private void getList(List list){ list.size(); }测试结果: 使用判空或其他方式避免空指针异常,不一定是解决问题的最好方式,空指针没出现可能隐藏了更深的 Bug。因此,解决空指针异常,还是要真正 case by case 地定位分析案例,然后再去做判空处理,而处理时也并不只是判断非空然后进行正常业务流程这么简单,同样需要考虑为空的时候是应该出异常、设默认值还是记录日志等。 现在以如下一个 User 的 POJO为例,研究null的含义。此POJO同时扮演 DTO 和数据库 Entity 角色,包含用户 ID、姓名、昵称、年龄、注册时间等属性: @Data @Entity public class User { @Id @GeneratedValue(strategy = IDENTITY) private Long id; private String name; private String nickname; private Integer age; private Date createDate = new Date(); }初始化数据: 客户端现在想将用户id为1的用户name设置为null,于是通过更新接口传来数据,仅传id和那么字段: { "id":1, "name":null}接口返回后的数据结果: ![]() ![]() ![]() ![]() ![]() 数据库字段允许保存 null,会进一步增加出错的可能性和复杂度。因为如果数据真正落地的时候也支持 NULL 的话,可能就有 NULL、空字符串和字符串 null 三种状态。 为解决上述问题,可能需要开发将DTO 和 Entity 进行拆分: 提前和客户端进行一些业务逻辑确认,在DTO中对客户端传来的数据区分是不传数据还是故意传null;在Entity中对字段进行注解,设置数据库保存数据为NOT NULL或像时间这种设置为由数据库生成创建时间。 4、抽象测试场景说了一大堆,其实抽象为测试场景时却很简单,但是希望可以透过现象看本质,很可能同样的触发场景,其背后的触发原因不尽相同,做好测试,没有想象的那么简单~ 抽象出测试场景: 上述中说明的测试过程中需要对传参本身不传和传null的逻辑进行区分测试,得到不同的预期结果: 不传-可能是不想更新此字段传null-可能希望把此字段置为空,但是需经过判断处理,最终保存为空字符串特殊字段-类似年龄这种,本身是有逻辑限制的,不可能为空;出生年月也不可能随意重置,必须限制输入符合校验规则的有效值 5、参考本文的主要知识点参考了《极客时间》-朱晔的专栏《Java业务开发常见错误100例》中的 《空值处理:分不清楚的null和恼人的空指针》一文 文章详细介绍的问题原因和建议开发解决方案,有想了解的可自行搜索,定有收获~ |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |