TDD概念
- TDD(Test-Driven Development) “测试驱动开发".
是敏捷开发中的一项核心实践和技术、是一种方法论。思路是通过测试来推进整个开发的进行。表现为测试代码优先于业务代码。 - TDD有别于以往的“先编码、后测试”的开发过程,而是在编程之前,先写测试脚本或设计测试用例。TDD在敏捷开发模式中被称之为“测试优先的编程(test-first programming)”,
TDD具体实施过程,可以看作两个层次
-
UTDD
在代码层次,在编码之前写测试脚本,可以称为单元测试驱动开发(Unit Test Driven Development,UTDD)
-
ATDD
在业务层次,在需求分析时就确定需求(如用户故事)的验收标准,即验收测试驱动开发(Acceptance Test DrivenDevelopment,ATDD)
UTDD
UTDD核心可看做一个闭环:RED -> GREEN -> REFACTOR,即运行一个失败的测试 -> 让测试通过 -> 及时重构代码。
为什么要 UTDD?
传统编码方式
- 需求分析,想不清楚细节,管他呢,先开始写
- 发现需求细节不明确,去跟业务人员确认
- 确认好几次终于写完所有逻辑
- 运行起来测试一下,靠,果然不工作,调试
- 调试好久终于工作了
- 转测试,QA 测出 bug,debug, 打补丁
- 终于,代码可以工作了
- 一看代码超级烂,不敢动,动了还得手工测试,还得让 QA 测试,还得加班…
UTDD 编码方式
先分解任务,分离关注点
列 Example,用实例化需求,澄清需求细节
写测试,只关注需求,程序的输入输出,不关心中间过程
写实现,不考虑别的需求,用最简单的方式满足当前这个小需求即可
重构,用手法消除代码里的坏味道
写完,手动测试一下,基本没什么问题,有问题补个用例,修复
转测试,小问题,补用例,修复
代码整洁且用例齐全,信心满满地提交
UTDD 的好处
- 自解性:测试代码即文档,新接触代码的开发人员通过阅读测试代码即可充分了解业务。
- 健壮性:业务建立在一个个单元测试的保护之下,规避了大批bug。
- 正确性:修改已有代码不再烫手,测试带来了正确性保护,这将在重构或者维护时体现。
- 改进API:测试自然的让开发人员变得从客户端角度编写可测试的OO代码,驱动了API的设计。
他的引入也是有代价和风险的:
- 开发成本:开发人员需要编写测试代码。
- 维护成本:开发人员需要维护测试代码。
- 环境搭建:测试环境的建立成本。
UTDD实现步骤
- 先写测试代码,并执行,得到失败结果
- 写实现代码让测试通过
- 重构代码,并保证测试通过。
- 反复实行这个步骤 测试失败 -> 测试成功 -> 重构
案例:
业务需求:
比如我们要写实现一个功能,当输入值大于等于0时返回true,当输入值小于0时返回false。
1. 先写测试代码,并执行,得到失败结果
import org.junit.jupiter.api.Test;
public class Test02 {
@Test
public void test01(){
// given
int input = 1;
// when
boolean result = Equal01(input);
// then
assert result: "测试不通过";
System.out.println("测试通过,参数大于0");
}
private boolean Equal01(int input) {
return false;
}
}
2. 写实现代码让测试通过
先不管任何设计啥的,只要让测试过了就行,随便乱写。比如下面的的代码。
3. 重构代码,并保证测试通过。
public class Test02 {
@Test
public void test01(){
// given
int input = -1;
// when
boolean result = Equal01(input);
// then
assert result: "测试不通过";
System.out.println("测试通过,参数大于0");
}
private boolean Equal01(int input) {
if(input >= 0){
return true;
}
return false;
}
}
UTDD 规则
- 除非是为了使一个失败的 unit test 通过,否则不允许编写任何产品代码
- 在一个单元测试中,只允许编写刚好能够导致失败的内容(编译错误也算失败)
- 只在测试全部通过的前提下重构或开始新的功能
ATDD
在业务层次,在需求分析时就确定需求(如用户故事)的验收标准,即验收测试驱动开发(Acceptance Test DrivenDevelopment,ATDD)
BDD-行为驱动开发
- 从ATDD演化出来一种具体落地的开发模式就是BDD(Behavior Driven Development,行为驱动开发)。BDD只是将验收标准更加明确化,可以看作是ATDD的实例化,即列出用户故事所可能遇到的应用场景,而且将这种应用场景的表达方式规定为GWT格式,
RBE-需求实例化
- BDD再往前推进一步,就是需求实例化(Requirements By Example,RBE),更加明确需求的具体表现。需求越明确,用户、产品经理、开发与测试等之间的理解就越一致(on the same page),更不产生偏差和误解,有利于开发和测试的工作。
- 基于RBE,开发人员写产品的代码,测试人员可以独立写测试的代码,产品经理的工作也会变得轻松,不需要太多的解释、不需要回答开发和测试的各种问题。