测试驱动开发是一种软件开发实践,源于1999年Kent Beck《Extreme Programming Explained》一书中的测试先行这一概念。Kent Beck在2003年再次提到 – TDD鼓励简单的设计并激发信心。经过后期的发展,TDD已经成长为一门独立的软件开发技术,其名气甚至盖过了极限编程。
imageTDD采用了一种以终为始的思维方式,它依赖于非常短的开发周期的重复:先将需求转换为非常具体的测试用例,然后改进代码,从而让测试通过。实际编码过程体现为:在开发业务功能代码之前,先编写测试代码。测试代码确定了我们要验收什么以及如何验收,然后再去编写功能代码,当测试通过时,代表功能完成。
在实践TDD的过程中,人们对TDD形成了三层理解:
- Task-Driven Development,任务驱动开发。
- Test-Driven Development,测试驱动开发。
- Test-Driven Design,测试驱动设计。
在我的TDD训练营中,我将第一条的重要性提高到了首位。
Task-Driven Development
任务拆解是TDD的一个关键的步骤。在开始编写进入代码环节之前,需要对业务需求做拆分,这个过程我们把它称之为Tasking。比如,一个用户登录的业务需求,我们大体可以拆分成如下几个Task:
- 假定用户名不存在时,当用户登录,则登录失败
- 假定用户名正确且密码错误时,当用户登录,则登录失败
- 假定用户名和密码都正确时,当用户登录,登录成功
通过上面的三个Tasking,可以总结出一个模式:Given When Then:
- Given 用户名不存在,When 用户登录, Then 登录失败
- Given 用户名正确且密码错误,When 用户登录, Then 登录失败
- Given 用户名和密码都正确,When 用户登录, Then 登录成功
Given When Then借鉴了BBD(Behavior Driven Development)里面的模式,它更加关注用户如何使用系统,即系统所提供的功能,从理解上更偏向于业务语言。对于一些技术人员,在初学阶段,需要多去练习,体会不同点,可以选业务人员视角索要一些反馈。
在TDD中,我将之称为Tasking三步曲:
- Given,代表特定的业务场景
- When,代表用户发生的行为
- Then,代表行为产生的结果
Test-Driven Development
上一步Tasking拆分好的一系列Task,经过沟通澄清之后,就可以将这些Task翻译成测试。在翻译的过程中需要注意的一个核心点是 – 保持业务概念的统一(统一语言的应用)。如何理解这一点呢,来个看一个Task:
Given 一个有空位的停车场,When 停车,Then 停车成功,返回一张票据
翻译成测试代码后:
@Test
void should_return_ticket_when_parking_given_a_parking_lot_has_available_space(){
ParkingLot parkinglot = new ParkingLot(1);
String car = "布加迪"
String ticket = parkinglot.park(car);
assertNotNull(ticket)
}
在上述测试代码中,car和ticket都是用了字符串来表示(基本类型偏执),车和票据这两个业务概念没有体现出来,建议是使用Car
和Ticket
来代替这两个业务概念。
极限的TDD,会将以终为始的思维运用到极致。它提倡在写测试用例的时候,先写断言,然后一步一步往前倒逼驱动出来测试代码,比如上述的例子,经历的过程如下:
{
// 1\. 我最终要验收的是停车票,代表停车成功
assertNotNull(ticket);
}
{
// 2\. 停车票是停车后返回的
Ticker ticket = parkinglot.park(car);
assertNotNull(ticket)
}
{
// 3\. 停的车是我新开进来的车
Car car = new Car();
Ticker ticket = parkinglot.park(car);
assertNotNull(ticket)
}
@Test
void should_return_ticket_when_parking_given_a_parking_lot_has_available_space() {
// 4\. 停进了有空位的停车场
ParkingLot parkinglot = new ParkingLot(1);
Car car = new Car();
Ticker ticket = parkinglot.park(car);
assertNotNull(ticket)
}
这种方式在刚开始是很难做到的,但是通过大量刻意练习,形成这种行为习惯,内化成思维习惯,也是益处多多,非常建议你去刻意练习。
Test-Driven Design
TDD并不会驱动出好的设计,TDD只会给你及时的反馈什么可能是糟糕的设计 – Kent Beck
关于这点,请阅读测试如何驱动设计?
网友评论