第九章 单元测试

第九章 单元测试


9.1 TDD三定律

  • 在编写不能通过的测试代码之前,不能编写生产代码(业务代码);即先写不能通过编译的测试代码,再编写业务代码;
  • 编写刚好无法通过的测试代码;即编写范围刚好的测试代码,无法通过是由于业务代码未编写;
  • 编写范围刚好的业务代码,使测试刚好通过;

9.2 保持测试整洁

测试代码在业务单元代码之前编写,每一个业务单元对应一个测试;这导致测试代码和业务代码有相当的代码量;这就需要保持测试代码的整洁;

  • 测试必须随生产代码的演进而修改;当测试越脏,越纠缠,就越会花更多的时间到测试代码上而不是生产代码;

  • 当测试过于混乱时,不得不放弃测试;没有测试的生产代码就无法保证修改不会影响到系统的其他部分;故障率开始增加;

  • 因此测试代码和生产代码一样重要

测试带来的好处:

  • 测试让代码可扩展、可维护、可复用;
  • 因为当代码修改时,测试可以及时发现问题的存在;

9.3 整洁的测试

  • 整洁的测试要有非常好的可读性;

  • 明确、简洁和足够的表达力;以尽可能少的文字表达大量的内容;

  • 测试代码中应该减少重复,没有细节展现,以免影响阅读;

  • 上图代码中充斥着addPage和assertSubString的重复;

  • 此外代码中有过度的细节,使读者沉浸在细节中;

    public void testGetPageHierarchyAsXml() throws Exception{
    //build
    makePages("PageOne","PageOne.ChildOne","PageTwo");
    
    //operate
    submitRequest("root","type:pages");
    
    //check
    assertResponseIsXML();
    assertResponseContains("<name>PageOne</name>","<name>PageTwo</name>","<name>ChildOne</name>");
    }
    
    public void testSmbolicLinksAreNotInXmlPageHierarchy() throws Exception{
    //build
    WikiPage page = makePage("PageOne");
    makePages("PageOne.ChildOne", "PageTwo");
    
    //operate
    addLinkTo(Page, "PageTwo", "SymPage");
    submitRequest("root", "type:pages");
    
    //check
    assertResponseIsXML();
    assertResponseContains("<name>PageOne</name>","<name>PageTwo</name>","<name>ChildOne</name>");
    assertResponseDoseNotContain("SymPage");
    }
    
    public void testGetDataAsXml() throws Exception{
    //build
    makePageWithContent("TestPageOne", "test page");
    
    //operate
    submitRequest("TestPageOne", "type:data");
    
    //check
    assertResponseIsXML();
    assertResponseContains("test page", "<Test>");
    }
  • 每一个测试都遵循着BUILD-OPERATE-CHECK的结构进行编写,方便阅读,了解测试目的;

9.3.1 面向特定领域的测试语言

  • 面向测试的语言并没有直接使用编写的API,而是进行了一层的包装;这样能方便的进行编写测试,便于阅读;
  • 这样的结构不是一次写成的,是需要对代码进行重构的;

9.3.2 双重标准

  • 有些事情可能只会在测试代码中做,而生产代码中可能不会做;所以内存或者CPU的效率在测试代码中可以稍微妥协,以提高代码的可读性;

9.4 每个测试一个断言

  • 遵循given-when-then的约定;
    • given – some context
    • when – some actions is carried out
    • then – a particular set of consequences should obtain
    • 这里所说的就是BUILD-OPERATE-CHECK
  • 如果可以将每个测试设计为单个断言(test),这非常好;
  • 当一个单元测试中包含多个断言时,应使断言数量最小化;

每个测试一个概念

  • 每个测试只测试一个概念;过多的测试概念会扰乱思路;

9.5 F.I.R.S.T

  • 快速 Fast(F):测试应该足够快;如果测试过慢就不愿进行测试,最终导致代码腐败;
  • 独立 Independent(I):测试应该相互独立,某个测试不应为下一个测试设定条件;以任何顺序运行测试条件也是可以的;
  • 可重复 Repeatable(R):测试可以在任何环境中通过;比如生产环境,质检环境;
  • 自足验证 Self-Validating(S):测试应该有布尔值输出;无论成败,可以方便检测。
  • 及时 Timely(T):测试应该及时编写;单元测试应该恰好在使其通过的生产代码之前编写;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值