美文网首页
如何解读TDD?

如何解读TDD?

作者: 袁慎建 | 来源:发表于2020-04-18 20:59 被阅读0次

    测试驱动开发是一种软件开发实践,源于1999年Kent Beck《Extreme Programming Explained》一书中的测试先行这一概念。Kent Beck在2003年再次提到 – TDD鼓励简单的设计并激发信心。经过后期的发展,TDD已经成长为一门独立的软件开发技术,其名气甚至盖过了极限编程。

    image

    TDD采用了一种以终为始的思维方式,它依赖于非常短的开发周期的重复:先将需求转换为非常具体的测试用例,然后改进代码,从而让测试通过。实际编码过程体现为:在开发业务功能代码之前,先编写测试代码。测试代码确定了我们要验收什么以及如何验收,然后再去编写功能代码,当测试通过时,代表功能完成。

    在实践TDD的过程中,人们对TDD形成了三层理解:

    • Task-Driven Development,任务驱动开发。
    • Test-Driven Development,测试驱动开发。
    • Test-Driven Design,测试驱动设计。

    在我的TDD训练营中,我将第一条的重要性提高到了首位。

    Task-Driven Development

    任务拆解是TDD的一个关键的步骤。在开始编写进入代码环节之前,需要对业务需求做拆分,这个过程我们把它称之为Tasking。比如,一个用户登录的业务需求,我们大体可以拆分成如下几个Task:

    1. 假定用户名不存在时,当用户登录,则登录失败
    2. 假定用户名正确且密码错误时,当用户登录,则登录失败
    3. 假定用户名和密码都正确时,当用户登录,登录成功

    通过上面的三个Tasking,可以总结出一个模式:Given When Then:

    1. Given 用户名不存在,When 用户登录, Then 登录失败
    2. Given 用户名正确且密码错误,When 用户登录, Then 登录失败
    3. 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都是用了字符串来表示(基本类型偏执),车和票据这两个业务概念没有体现出来,建议是使用CarTicket来代替这两个业务概念。

    极限的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

    关于这点,请阅读测试如何驱动设计?

    相关文章

      网友评论

          本文标题:如何解读TDD?

          本文链接:https://www.haomeiwen.com/subject/nignvhtx.html