[解锁新姿势] 兄dei 我感觉你在写bug
前言:
继上篇 [解锁新姿势] 兄dei,你代码需要优化了 介绍一些代码的优化的小技巧
。
但是我们除了在代码编写上需要优雅
, 还需要编写对应的测试用例
, 以此来保证代码的质量。
在这篇我们继续在学习
如何编写有保证质量
的代码。
背景
在刚刚学习编程的时候,由于没有接触过单元测试/TDD
相关知识, 只是知道有这么回事,不以为然。导致工作的时候,拿到一个新需求,只知道埋头苦写
。会出现以下场景:
产品:增加一个新功能 blalala.
我:好的没问题,一个星期撸出来
一个月后…
我:我的接口写好了!可以测试了。
测试:你自己测过没 ??
我:放心postman
测过了,稳的一批。(/滑稽)
一分钟后…
测试:你的接口又双叕 报500
了 (黑人问号??)
我:不可能!肯定是你的问题
一次偶然的机会,接触到 TDD
开发模式,从此打开新的世界。原来编程还可以这么玩 : )
TDD
TDD是测试驱动开发
(Test-Driven Development)的英文简称, 是敏捷开发
中的一项核心实践
和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试
用例代码,测试代码确定需要编写什么产品代码。
说白了,就是开发功能代码之前,先编写
测试用例
代码`
我们先来看一个“经典”
的 TDD 问题,入手学习 TDD 开发
,感受 TDD 开发的魅力所在
需求:
编写一个程序,打印出从1到100的数字,将其中3的倍数替换成“Fizz”
,5的倍数替换成“Buzz”
。既能被3整除、又能被5整除的数则替换成“FizzBuzz”
。如下图所示
分析
在动手写代码之前,我们要首先弄清需求的范围
和优先级
,例如给出的FizzBuzz
需求,1-100
就是范围
,对应优先级是1
,确定了需求的范围和优先级后,然后我们就可以开始coding
~
编码
Step1
我们首先新建一个FizzBuzz测试类
public class FizzBuzzTest {@Testvoid show_raw_number(){FizzBuzz fizzbuzz = new FizzBuzz(1);assertThat(fizzbuzz.getResult()).isEqualTo("1");}
}public class FizzBuzz {public FizzBuzz(int input) {}public String getResult() {return "";}
}
温馨提示:
- 测试类推荐使用
驼峰式
命名,测试方法 推荐使用下划线
命名- 这里我使用的是
AssertJ
单元测试框架,这款框架主要亮点之一是支持链式
调用。assertThat
方法是org.assertj.core.api.Assertions.assertThat
包静态
方法.- assertThat(A).isEqualTo(B),意思是
断言
(预测) A 等于 B,如果 A == B的话,返回True
表示通过
测试用例,否则False
,表示测试失败,不通过。- 更多的使用方法可以参考AssertJ 官方网站
我们先创建一个 FizzBuzz
类, 创建 getResult()
方法,空实现, 传入参数 1
,断言(预期)fizzbuzz 输出结果是 1
,先运行测试用例,会出现如下效果
小伙伴:你会不会写啊,这么简单的还用测试?还报错!!
别着急,测试驱动开发,讲究是的循序渐进的节奏
听我的,往下看 相信你会get
到feel
:)
看到红灯
程序提示,我们预期结果(Expected
)是 “1”
, 但实际结果(Actual
)是0
,说明我们的程序有错。
接下来我们进一步来修改我们的测试用例,以此来通过测试用例。
修改如下:
public String getResult() {return "1";
}
然后再次运行我们的测试用例
温馨提示:
编写刚刚好通过测试用例的代码。
这次“完美”
通过测试!然后我们开始编写下一个测试用例~
完美?? 黑人问号?? 拿刀哪个,先把刀放下 你听我说。
Step2
我们来测试 第一种情况,将其中3的倍数替换成“Fizz”
,编写 3
的测试用例
@Test
public void show_fizz(){FizzBuzz fizzBuzz = new FizzBuzz(3);assertThat(fizzBuzz.getResult()).isEqualTo("Fizz");
}
创建一个show_fizz
方法, 这次输入参数为 3,然后继续运行测试用例
看到我们熟悉的 “红灯报错”
,然后我可以继续修改我们的 getResult
方法 以此来通过测试用例。
public String getResult() {if (input % 3 == 0){return "Fizz";}return String.valueOf(input);
}
然后再次运行测试用例~
绿色!!通过测试!
看到这里,我们可以发现一个规律
红灯行,绿灯停
当测试用例是“红灯”
时,我们就应该动手编写出,能通过测试的测试用例。
当测试用例是“绿灯”
时,我们就应该停下来思考,下一个测试用例改如何编写。
Step3
我们继续小步前进,继续编写第二种情况,5的倍数替换成“Buzz”
, 编写 入参 5
的测试用例
@Test
public void show_buzz(){FizzBuzz fizzBuzz = new FizzBuzz(5);assertThat(fizzBuzz.getResult()).isEqualTo("Buzz");
}
不出意外的话,是 红灯
我们继续修改getResult()
方法,以此来通过测试用例。
public String getResult() {if (input % 3 == 0){return "Fizz";}// 新增if (input % 5 == 0){return "Buzz";}return String.valueOf(input);
}
然后继续运行测试用例,绿灯通过~
Step4
我们继续小步前进,考虑第三种情况,既能被3整除
、又能被5整除
的数则替换成“FizzBuzz”
,编写 入参 15
的测试用例
@Test
public void show_fizz_buzz(){FizzBuzz fizzBuzz = new FizzBuzz(15);assertThat(fizzBuzz.getResult()).isEqualTo("FizzBuzz");
}
这里相信大家能猜到结果,红灯
,这里我就演示结果了。然后我们修改对应 getResult
方法,通过测试用例
public String getResult() {if (input % 15 == 0){return "FizzBuzz";}if (input % 3 == 0){return "Fizz";}if (input % 5 == 0){return "Buzz";}return String.valueOf(input);
}
重构
Step1
我们编写完测试用例,但是代码出现了代码的坏味道——重复代码
,有了测试用例
,我们就可以很轻松
的重构代码,接下来开始重构我们的代码。
public String getResult() {if (isDivisibleBy(15)){return "FizzBuzz";}if (isDivisibleBy(3)){return "Fizz";}if (isDivisibleBy(5)){return "Buzz";}return String.valueOf(input);
}private boolean isDivisibleBy(int i) {return input % i == 0;
}
抽取一个 isDivisibleBy
方法,然后运行测试,看看修改后是否引入bug
测试通过,没问题,但在这里我们需要注意一点
每一次修改,都需运行一遍测试,避免修改引入
bug
,确保代码的正确性
。
Step2
测试通过后,我们继续进一步优化。
public String getResult() {String result = "";if (isDivisibleBy(3)) {result += "Fizz";}if (isDivisibleBy(5)) {result += "Buzz";}return result;
}
继续修改 getResult
方法,提取一个变量 result
作为返回值,然后运行测试。
出乎意料,这次修改竟然出现bug
,正如刚刚所说,每次修改后,都需要运行测试用例保证代码的正确性。我们再来检查一下代码,并作出如下修改:
public String getResult() {String result = "";if (isDivisibleBy(3)) {result += "Fizz";} if (isDivisibleBy(5)) {result += "Buzz";} if (result.isEmpty()){result += input + "";}return result;
}
通过测试用例,发现当输入为1
的时候,没有进行处理,添加相应判断。再次
运行测试用例
测试通过,大功告成!
最后
最后剩下遍历 1~100
情况,相信难不倒你,感兴趣的朋友,可以自行编写~
至此,我尽量演示一个相对完整的TDD开发
流程,麻雀虽小,五脏俱全。希望你能感受到 get
到feel
~
我们再来总结一下:
- 1、创建测试类
类
名推荐使用驼峰式
命名,测试方法
推荐使用下划线
命名
- 2、分析
需求
的范围
和优先级
- 3、根据
优先级
编写写测试用例
- 4、再编写业务代码
- 5、然后编写测试用例刚好通过的代码
- 红灯行,绿灯停
- 当测试用例是
“红灯”
时,我们就应该动手编写出,能通过测试的测试用例。 - 当测试用例是
“绿灯”
时,我们就应该停下来思考,下一个测试用例改如何编写。
- 当测试用例是
- 红灯行,绿灯停
- 5、根据测试用例,重构,优化代码。
- 每一次修改,都需运行一遍
测试
,避免修改引入bug
,确保代码的正确性
。
- 每一次修改,都需运行一遍
- 6、最终
完成功能
第5点,不分先后,可以交替执行。
最后的最后
有些人觉得为什么要弄那么复杂,还要浪费时间写单元测试,为何不
一把梭
呢?
没有测试用例覆盖的代码,你敢保证代码的质量吗?
没有测试用例覆盖的代码,你敢进行代码重构吗? 你品你细品 (滑稽)
其实TDD
开发模式,主要看开发者意愿,不强求,但是单元测试
必须的!
以上就是全部内容,希望能帮助到你~
如有不妥,欢迎指出,大家一起交流学习。
[解锁新姿势] 兄dei 我感觉你在写bug相关推荐
- [解锁新姿势] 兄dei,你代码需要优化了
黑客(程序员)也是创作者,与画家.建筑师.作家一样. --<黑客与画家> 前言 在我们平常开发过程中,由于项目时间紧张,代码可以用就好,往往会忽视代码的质量问题.甚至有些复制粘贴过来,不加 ...
- [解锁新姿势] 兄dei,你代码需要优化了
前言 在我们平常开发过程中,由于项目时间紧张,代码可以用就好,往往会忽视代码的质量问题.甚至有些复制粘贴过来,不加以整理规范.往往导致项目后期难以维护,更别说后续接手项目的人.所以啊,我们要编写出优雅 ...
- [解锁新姿势] 回想起被 `if-else` 支配的恐惧,我们要打倒 if - else
前言 [解锁新姿势] 兄dei,你代码需要优化了 在之前文章说到,简单 if-else,可以使用 卫语句 进行优化.但是在实际开发中,往往不是简单 if-else 结构,我们通常会不经意间写下如下代码 ...
- android解锁win,Win10电脑解锁新姿势:WP/安卓手机、微软手环当钥匙
IT之家讯 微软在官方网站公布了Win10的开发路线图,其中描述了目前已经实现的功能.正在预览测试以及正在开发中的功能.根据描述,微软正在开发一种全新的Win10电脑解锁方式. 首先,你可以使用自己的 ...
- windows编程 识别拖动_Quicker 解锁新姿势!Windows 还能这么用?
不用记住软件复杂的快捷方式,轻轻按下鼠标滚轮,便可唤出当前软件的专属工具箱,一键启动原本要多次点击鼠标的操作,这样的时刻是否很美妙? Excel 选中表格数据加黑框并横向打印,一键搞定 Quicker ...
- 解锁新姿势,揭秘如何通过公众号迁移方式给自己的爱号开通留言板功能
关注我的公众号:帅哥趣谈, 公众号首先发表. 引言 玩公众号有一段时间了,很是羡慕别人的留言板功能,一心想着给自己的号也整一个.淘宝一问价格在2000千左右,又望而却步了.不整吧,又老是想着,情绪的拉 ...
- [解锁新姿势] 优化参数前置校验
前言 我们通常写接口都会用到 @Valid 注解,通过 @NotNull,@NotEmpty 等等来简单校验我们的接口入参. 但是有些入参,需要查询数据库,这时候 @Valid 自带的校验注解,就满足 ...
- 解锁新姿势:探讨复杂的 if-else 语句“优雅处理”的思路
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:hyzhan43 juejin.im/post/5def65 ...
- python批量检索文献_快解锁新姿势,教你如何用Python搞定文献搜索和科研图片!...
相比实验论文,发表SCI应该更让科研狗们重视和焦虑. 起初看到读博的同学发表SCI论文,心里面就已经酸了,后来「本科生发数篇 SCI」的新闻屡见不鲜,现在甚至连小学生都跑出来分一杯羹-- 前段时间,B ...
最新文章
- 小程序clearinterval无效解决
- 任务计划cron、服务管理工具chkconfig/systemctl
- 012_Vue计算属性
- Java实现算法导论中快速傅里叶变换FFT递归算法
- C/C++如何传递二维数组?
- POI 导出文件以文件流形式返回
- hbase 查询设置超时_hbase master挂掉-zookeeper连接超时原因
- FPGA时钟激励编写(方法二)
- java fst 入门 例子,Java FST.save方法代码示例
- 关于Java单例模式中懒汉式和饿汉式的两种类创建方法
- 【机器学习中的数学】多项式分布及其共轭分布
- 基于MUI制作手机社交app通讯录列表页面源码
- 四种优秀的数据库设计工具
- 什么是ColdFusion
- [附源码]JAVA+ssm计算机毕业设计餐饮管理系统(程序+Lw)
- elementui表格如何自定义表头内容,让表头变得更美观
- 三菱fx2n做从站的modbus通讯_三菱PLC编程实例分享
- s5pv210开发与学习:1.3之SD卡学习
- node.js毕业设计安卓移动LYQ电子商城APP(程序+APP+LW)
- flashfxp怎么改中文,5步完成flashfxp中文版语言设置