[学习笔记] 《代码整洁之道》— 第9章 单元测试

TDD 三定律

谁都知道TDD要求我们在编写生产代码之前先编写单元测试。

  • 定律一:在编写不能通过的测试单元前,不可以编写生产代码。
  • 定律二:只可编写刚好无法通过的单元测试,不能编译也算不通过。
  • 定律三:只可编写刚好足以通过当前失败测试的生产代码。

保持测试整洁

  • 脏测试等同于 — 如果不是坏于的话 — 没测试。

    • 测试必须随生产代码的演进而修改。

      • 测试越脏,就越难修改。
  • 测试代码和生产代码一样重要!
    • 单元测试让你的代码 可扩展、可维护、可复用
    • 覆盖了生产代码的自动化单元测试程序组能尽可能地保持设计和架构的整洁。
  • 测试越脏,代码就会变得越脏。最终,你丢失了测试,代码开始腐坏。

整洁的测试

  • 整洁的测试有三个要素:可读性可读性可读性

    • 在单元测试中,可读性甚至比生产代码还重要。
    • 明确简洁足够的表达力
  • 先看来自 FitNesse 的代码:

    public void testGetPageHieratchyAsXml() throws Exception{crawler.addPage(root, PathParser.parse("PageOne"));crawler.addPage(root, PathParser.parse("PageOne.ChildOne"));crawler.addPage(root, PathParser.parse("PageTwo"));request.setResource("root");request.addInput("type", "pages");Responder responder = new SerializedPageResponder();SimpleResponse reponse =(SimpleResponse) responder.makeResponse(new FitNesseContext(root), request);String xml = response.getContent();assertEquals("text/xml", response.getContentType());assertSubString("<name>PageOne</name>", xml);assertSubString("<name>PageTwo</name>", xml);assertSubString("<name>ChildOne</name>", xml);
    }public void testGetPageHieratchyAsXmlDoesntContainSymbolicLinks()
    throws Exception{WikiPage pageOne = crawler.addPage(root, PathParser.parse("PageOne"));crawler.addPage(root, PathParser.parse("PageOne.ChildOne"));crawler.addPage(root, PathParser.parse("PageTwo"));PageData data = pageOne.getData();WikiPageProperties properties = data.getProperties();WikiPageProperty symLinks = properties.set(SymbolicPage.PROPERTY_NAME);symLinks.set("SymPage", "pageTwo");pageOne.commit(data);request.setResource("root");request.addInput("type", "pages");Responder responder = new SerializedPageResponder();SimpleResponse reponse =(SimpleResponse) responder.makeResponse(new FitNesseContext(root), request);String xml = response.getContent();assertEquals("text/xml", response.getContentType());assertSubString("<name>PageOne</name>", xml);assertSubString("<name>PageTwo</name>", xml);assertSubString("<name>ChildOne</name>", xml);assertNotSubString("SymPage", xml);
    }public void testGetDataAsHtml() throws Exception{crawler.addPage(root, PathParser.parse("TestPageOne"), "test page");request.setResource("TestPageOne");request.addInput("type", "data");Responder responder = new SerializedPageResponder();SimpleResponse reponse =(SimpleResponse) responder.makeResponse(new FitNesseContext(root), request);String xml = response.getContent();assertEquals("text/xml", response.getContentType());assertSubString("test page", xml);assertSubString("<Tset", xml);
    }
    

    重构为更整洁和有表达力的形式:

    public void testGetPageHieratchyAsXml() throws Exception{makePage("PageOne", "PageOne.ChildOne", "PageTwo");submitRequest("root", "type:pages");assertResponseIsXML();assertResponseContains("<name>PageOne</name>", "<name>PageTwo</name>", "<name>ChildOne</name>");
    }public void testSymboLicLinksAreNotInXmlPageHierarchy() throws Exception{WikiPage page = makePage("PageOne");makePage("PageOne.ChildOne", "PageTwo");addLinkTo(page, "PageTwo", "SymPage");submitRequest("root", "type:pages");assertResponseIsXML();assertResponseContains("<name>PageOne</name>", "<name>PageTwo</name>", "<name>ChildOne</name>");assertResponseDoesNotContain("SymPage");
    }public void testGetDataAsXml() throws Exception{makePageWidthContent("TestPageOne", "type:data");submitRequest("TestPageOne", "type:data");assertResponseIsXML();assertResponseContains("test page", "<Text");
    }
    

    这些测试显然呈现了构造-操作-检验 (BUILD-OPERATE-CHECK)模式。

    • 第一个环节构造测试数据;
    • 第二个环节操作测试数据;
    • 第三个环节检验操作是否得到期望的结果。
  • 双重标准:测试 API 中的代码与生产代码相比。的确有一套不同的工程标准。

    • 有些事你大概永远不会在生产环境中做,而在测试环境中却完全没问题。

    • 例:测试在“温度太低”时检验温度报警器、加热器和送风机是否全部打开。

      @Test
      public void turnOnLoTempAlarmAtThreashold() throws Exception{hw.setTemp(WAY_TOO_COLD);controller.tic();asserTure(hw.heaterState());asserTure(hw.blowerState());asserFalse(hw.coolerState());asserFalse(hw.hiTempState());asserTure(hw.loTempState());
      }
      

      重构后:

      @Test
      public void turnOnLoTempAlarmAtThreashold() throws Exception{wayTooCold();assertEquals("HbchL", hw.getState());
      }
      
      • 创建了一个 wayTooCold 函数,隐藏了 tic 函数的细节。
      • assertEquals 中那个奇怪的字符串:大写表示“打开”,小写表示“关闭”。
        • {heater, blower, cooler, hi-temp-alarm, lo-temp-alarm}

      扩展到更大范围:

      @Test
      public void turnOnCoolerAndBlowerIfTooHot() throws Exception{tooHot();assertEquals("hBChl", hw.getState());
      }@Test
      public void turnOnHeaterAndBlowerIfTooClod() throws Exception{tooHot();assertEquals("HBchl", hw.getState());
      }@Test
      public void turnOnHiTempAlarmAtThershold() throws Exception{wayTooHot();assertEquals("hBCHl", hw.getState());
      }@Test
      public void turnOnLoTempAlarmAtThershold() throws Exception{wayTooCold();assertEquals("HBchL", hw.getState());
      }public String getState(){String state = "";state += heater ? "H" : "h";state += blower ? "B" : "b";state += cooler ? "C" : "c";state += hiTempAlarm ? "H" : "h";state += loTempAlarm ? "L" : "l";return state;
      }
      
  • 尽可能减少每个概念的断言数量,每个测试函数只测试一个概念。

  • F.I.R.S.T.

    • 快速(Fast):测试应该足够快,应该能快速运行。
    • 独立(Independent):测试应该相互独立。
      • 某个测试不应为下一个测试设定条件。
      • 可以单独运行每个测试,及以任何顺序运行测试。
    • 可重复(Repeatable):测试应该可在任何环境中重复使用。
    • 自足验证(Self-Validating):测试应该有布尔值输出。
      • 不应该查看日志文件来确认测试是否通过。
      • 不应该手工对比两个不同文本文件来测试是否通知。
    • 及时(Timely):测试应及时编写。

参考文献

[1] Robert C. Martin 著,韩磊 译,《代码整洁之道》,北京:人民邮电出版社,2010.1(2018.9 重印), ISBN 978-7-115-21687-8。


[学习笔记]《代码整洁之道》(八)相关推荐

  1. [读书笔记] 代码整洁之道

    书的示例是Java语言编写的,虽说不会影响阅读,但是后面几章讲应用这套方法论的时候,大篇幅的Java代码分析还是挺难受的,而且连java测试框架Junit都要细讲,对于非Java系的开发者来说,一些内 ...

  2. [读书笔记] 代码整洁之道(一)

    最近读完了马丁的clean code,颇有收获,简单整理下读书笔记,虽然整书是以Java代码做代码示例,但语言无国界,特别是编程语言更是如此,不管你从事的是以何种语言为主的开发环境,我相信,从本书中都 ...

  3. 《代码整洁之道 clean code》学习笔记

    文章目录 0 前言 1 注释 C1:不恰当的信息 C2:废弃的注释 C3:冗余的注释 C4:糟糕的注释 C5:注释掉的代码 2 环境 E1:需要多步才能实现的构建 E2:需要多步才能做到的测试 3 函 ...

  4. 《代码整洁之道 Clean Architecture》-读书笔记

    大家好,我是烤鸭: 关于<代码整洁之道>,记录一下读书笔记. 代码整洁之道 第一章 整洁代码 整洁代码的艺术 第二章 有意义的命名 避免误导 有意义的区分 使用读得出来和可搜索的名字 避免 ...

  5. 《代码整洁之道 clean code》 读书笔记(上篇)

    <代码整洁之道 clean code> 读书笔记(上篇) 这本书我准备用较快的时间来读一下,简单记录一下自己的一些读完的感悟,因为更多地编码技巧还是需要在实际编程和读源码的过程中进行锤炼. ...

  6. 《代码整洁之道》(Clean Code)- 读书笔记

    一.关于Bob大叔的Clean Code <代码整洁之道>主要讲述了一系列行之有效的整洁代码操作实践.软件质量,不但依赖于架构及项目管理,而且与代码质量紧密相关.这一点,无论是敏捷开发流派 ...

  7. 代码整洁之道(Clean Code)- 读书笔记

    Sorry, 许久未更新文章了,主要因为刚刚换了一家新公司,忙于组建团队(建设.招聘.流程.框架等)与熟悉公司业务,还有领导给的其他工作等等,实在是没有时间更新了.最近在和团队分享Bob大叔的< ...

  8. 代码整洁之道 Clean Code 读书笔记

    目录 代码整洁之道 Clean Code 第一章 整洁代码 第二 三章 命名与函数 第四 五章注释与格式 第六章 对象和数据结构 第七章 错误处理 第八章 边界 第九章 单元测试 第十章 类 第十一章 ...

  9. 《代码整洁之道》读书笔记✍ 教你写 clean code

    代码整洁之道 第一章 整洁代码 1.1 什么是整洁的代码? 资深程序员告诉你什么是整洁的代码,下面详细介绍了Bjarne Stroustrup的描述,其他描述就不一一列出了,在此只记录几个关键点. 我 ...

最新文章

  1. Leangoo团队敏捷开发实现过程
  2. 高并发之存储篇:关注下索引原理和优化吧!躲得过实践,躲不过面试官!
  3. hive sql操作
  4. element显示服务器的图片,Vue+ElementUI+SpringMVC实现图片上传和回显
  5. gdb调试命令的使用及总结
  6. 面试官:你连HTTP请求Post和Get都不了解?
  7. zemax光学设计超级学习手册_穿越十年的一个ZEMAX光学设计案例
  8. matlab填充点面,求大神指点绘制空间内散点图的包络面,,,散点程序如下
  9. 人工智能python小程序_Python:一个可以套路别人的python小程序
  10. 李开复:听AI大佬吐槽真实的人工智能
  11. adas硬件_ADAS系统功能安全设计/SOTIF需求和测试实例/软件安全架构/硬件安全设计......
  12. php 条码打印控件,jQuery插件jquery-barcode实现条码打印的方法
  13. 数据库建模工具powerdisgner16.5
  14. 图:试图播放的文件扩展名与文件格式不匹配。播放该文件可能会导致意外行为...的解决办法
  15. f-stack nginx 单进程模式BSD网络初始化流程
  16. Java编程思想基本介绍
  17. 建设网站的过程会有哪些问题,如何去注意呢
  18. android+桌面+横屏,安卓怎么强制桌面横屏
  19. 元气骑士远程联机(仅安卓)
  20. JavaEE - 集合 - Map集合

热门文章

  1. liunx系统的常用命令【实用】
  2. 《仙剑奇侠传3》流程攻略4
  3. mysql 页和叶子页_Mysql —— 页与索引
  4. Leetcode刷题100天—706. 设计哈希映射(哈希表)—day74
  5. 设置git命令使用的简写、缩写
  6. Linux如何后台运行服务
  7. 【Kotlin学习之旅】解决错误:kotlin.NotImplementedError: An operation is not implemented: Not yet implemented
  8. [组合数学]组合数有关的公式及常用求和
  9. win7修改本地连接 MTU值的方法
  10. UC3842/UC3843 PWM时序图详细分析