单元测试实战(四种覆盖详解、测试实例)

更新时间:2023-06-28 20:08:23 阅读: 评论:0

单元测试实战(四种覆盖详解、测试实例)
理论部分
前⾔
单元测试,就是对某⼀段细粒度的Java代码的逻辑测试。代码块⼀般指⼀个Java ⽅法本⾝,所有外部依赖都需要mock掉,仅关注代码逻辑本⾝。
需要注意,单测的⼀个⼤前提就是需要清楚的知道⾃⼰要测试的程序块所预期的输⼊输出,然后根据这个预期和程序逻辑来书写ca。
英语专八证书(这⾥需要注意的就是单测的预期结果⼀定要针对需求/设计逻辑去写,⽽不是针对实现去写,否则单测将毫⽆意义,照着错误的实现设计出的ca也很可能是错的)
覆盖类型
1、⾏覆盖 Statement Coverage
⾏覆盖(⼜叫语句覆盖)就是通过设计⼀定量的测试⽤例,保证被测试的⽅法每⼀⾏代码都会被执⾏⼀遍。
路径覆盖是最弱的覆盖⽅式。
实例:
public Integer fun3(Integer a, Integer b, Integer x) {
if (a > 1 && b == 0) {
x = x + a;
}
if (a == 2 || x > 1) {
x += 1;
attackers}
return x;
}
本例仅需要⼀个ca,即可实现⾏覆盖。test ca 如下:
a b x预期结果
TC12036
@Test
public void testFun3StatementCoverage(){
Integer res = demoService.fun3(2,0,3);
Asrt.asrtEquals(6,res.intValue());lucifer是什么意思
}
这个⽤例就可以保证所有的⾏都被执⾏。
但是仅仅有这⼀个⽤例的话,对这个⽅法的测试就是⾮常脆弱的。
举个栗⼦,某RD接到了这个需求,理清了逻辑,写好单测之后开始写代码(或者写好代码之后开始写单测)。但是由于⼿抖,将第三⾏的&& 写成了 ||:
public Integer fun4(Integer a, Integer b, Integer x) {
if (a > 1 || b == 0) {
x += a;
}hosts是什么
if (a == 2 || x > 1) {
x += 1;
}
return x;
}
然后跑⼀下单测,发现很顺滑,⼀下就过了。
随后该RD很⾼兴的将代码发布到了线上,结果就发⽣了严重的⽣产故障,于是该RD就被开除了。
⾏覆盖是⼀个最基础的覆盖⽅式,但是也是最薄弱的,如果完全依赖⾏覆盖,那不⼩⼼就会被开除。
2、判定覆盖 / 分⽀覆盖 (Decision Coverage/Branch Coverage)黄瓜英文
public Integer fun3(Integer a, Integer b, Integer x) {
if (a > 1 && b == 0) {
x = x + a;
}
if (a == 2 || x > 1) {
x += 1;
}
return x;
}
判定覆盖的含义就是代码⾥每⼀个判定都要⾛⼀次true,⼀次fal。依然⽤上⾯的代码,想要实现判定覆盖,需要以下ca
a b x预期结果儿童学习网
TC22014
TC33111
@Test
public void testFun3DecisionCoverage(){
Integer res = demoService.fun3(2,0,1);
Asrt.asrtEquals(4,res.intValue());
res = demoService.fun3(3,1,1);
Asrt.asrtEquals(1,res.intValue());
}
这两个⽤例可以保证判定 A: (a > 1 || b == 0)  和判定B: (a == 2 || x > 1) 分别都取⼀次true 和fal:
tc2 时, A,B均为true;tc3时,A,B均为fal。
可以看出分⽀覆盖依然有明显缺陷,并没有覆盖到  A: true  B: fal 和 A:fal B:true的情况。
3、条件覆盖 Condition Coverage
public Integer fun3(Integer a, Integer b, Integer x) {
徐州夏令营if (a > 1 && b == 0) {
x = x + a;
}
if (a == 2 || x > 1) {
x += 1;
}
return x;
}
条件覆盖和判定覆盖类似,不过判定覆盖着眼于整个判定语句,⽽条件覆盖则着眼于某个判断条件。
条件覆盖需要保证每个判断条件的true fal都要覆盖到,⽽不是整个判定语句。
例如,判定A (a > 1 || b == 0) ,只需要整个判定表达式分别取⼀次真假即可满⾜判定覆盖,⽽要满⾜条件覆盖,则需要判断条件 (a>1) 和(b==0) 分别都取⼀次true fal才算满⾜。
依然采⽤同样的代码,要想实现条件覆盖,则需要:
a b x预期结果
TC42036
TC50100
@Test
public void testFun3ConditionCoverage(){
godaddy com
Integer res = demoService.fun3(2,0,3);
Asrt.asrtEquals(6,res.intValue());
res = demoService.fun3(0,1,0);
Asrt.asrtEquals(0,res.intValue());
}cowbone
这两个⽤例可以保证 (a > 1)  (b==0) (a == 2)(x > 1)四个条件都分别取true fal。
很明显可以发现,这玩意⼉依然是不全⾯的,这个例⼦⾥条件覆盖和判定覆盖存在同样的问题,覆盖的不够全⾯。
4、路径覆盖 Path Coverage
public Integer fun3(Integer a, Integer b, Integer x) {
if (a > 1 && b == 0) {
x = x + a;
}
if (a == 2 || x > 1) {
x += 1;
}
return x;
}
路径覆盖这个顾名思义就是覆盖所有可能执⾏的路径。为了⽅便理解,这⾥先把流程图画出来。
红⾊代表⼀段路径。
⾸先梳理所有路径:
路径1:1-->3-->5;
路径2:1-->2-->5;
路径3:1-->3-->4;
路径4:1-->2-->4;
路径覆盖就是需要设计⽤例,将所有的路径都⾛⼀遍。
设计以下⽤例:
a b x预期结果经过路径
TC601001
TC730-302后庭
TC821343
TC920364
@Test
public void testFun3PathCoverage(){
Integer res = demoService.fun3(0,1,0);
Asrt.asrtEquals(0,res.intValue());
res = demoService.fun3(3,0,-3);
Asrt.asrtEquals(0,res.intValue());
res = demoService.fun3(2,1,3);
Asrt.asrtEquals(4,res.intValue());
res = demoService.fun3(2,0,3);
Asrt.asrtEquals(6,res.intValue());
}
总结
这是最常见的⼏种覆盖类型,⾏覆盖、判定覆盖、条件覆盖优缺点⼀致,都是较为简单,⽅便构造⽤例,并且能对程序质量有⼀定保证作⽤。
路径覆盖最完善,但是在⼀些复杂的场景⾥,会带来测试代码指数级增长的副作⽤,这个对于绝⼤多数⼈都是⽆法接受的。
⼀般情况下,⾏覆盖和判定覆盖同时做到已经是⽐较良好的单测代码了,jacoco的覆盖率统计也都是基于判定覆盖的。
实战部分(Mock)
mock是什么
事实上,理论和实际总是有差距的,单测也同样。
虽然单测的指导性理论知识⾮常完备,但是实际⼯作中往往遇到各种各样的障碍。最常见的,莫过于各种外部依赖了,这些外部依赖总是会阻碍我们书写⾃⼰的单测代码。这时候,我们就要⽤到mock了。

本文发布于:2023-06-28 20:08:23,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/1061242.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:覆盖   判定   需要   条件   代码
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图