TDD学习笔记【二】---单元测试简介

大纲

Testing 的第一个切入点:单元测试。数据库

本篇文章将针对单元测试进行简介,主要内容包含了5W:网络

  1. Why
  2. What
  3. Where
  4. Who
  5. When

而How 的部分,属于实现部分,将于下一篇文章介绍工具与简单的范例。工具

最后会提到测试用例所表明的意义与其重要性。post

前言

单元测试,是开发人员最该写的测试程序,却也是最容易被忽略的测试。单元测试

你们常碰到的测试相关问题是:学习

  1. 每每一堆人写测试程序时,自觉得是在写单元测试,却压根就不是单元测试,而是集成测试。
  2. 生产代码是我写的,若是测试程序也是我写,那有什么意义?因此应该给QA/QE 来写才能测出盲点。
  3. 我程序都写完了,跑起来也都对,这时写测试程序一点意义都没有。
  4. 测试程序要跑很久。
  5. 没有测试环境,要怎么写测试。

看完这几篇单元测试的相关文章后,但愿你们能够得到一些想法,解决这些问题。测试

Why

先举几个在开发上常见的问题:spa

  1. 怎么让UI, Service, Data Access 平行开发?
  2. 要到真实环境方能测试程序无误
  3. 页面发生错误,究竟是谁错了?
  4. 交付的程序,到底测过哪些东西了?
  5. 我改了这支程序,会不会害别的程序挂掉?

这些问题,能够有哪些Unit Test 相关的方式来解决:设计

  1. Unit Test 中使用stub/mock object,达到关注点分离
  2. Unit Test 使用stub/mock object 来模拟外部回传的数据
  3. 把input 值当作test case,跑一次Unit Test
  4. 交付的程序,包括Unit Test 程序
  5. 改完程序就跑一次Unit Test 吧

总而言之,没有被测试涵盖到的程序,即便它多是对的,也没人敢拍胸脯保证。而有了测试用例来辅助说明与保护,至少能够拍胸脯保证,在这样的测试用例下,这个对象的设定,确定如同预期般执行。3d

而单元测试能够提供回归测试的保护,在每一次异动完程式,能够单键执行就知道是否破坏了本来对对象行为的预期。

单元测试能够透过一些辅助设计,来达到与外部环境、服务、相依隔绝,而仅测试该物件自己的逻辑,以及与外部的互动是否符合预期。

形成问题的测试案例,每每是最珍贵的,由于最具表明性,也最具价值。由于它提供了咱们修正bug的方向以及指标。而针对发生问题的测试案例,来执行单元测试,立刻就能够知道是不是该对象的内部问题。

最后,单元测试因为具有与外界服务、相依隔绝的特性,因此能够帮助撰写实际的对象时,具备可测试性、低耦合性,彼此之间只相依于抽象或接口。进而经过IoC 的设计,让咱们能够作到关注点分离,让开发各个对象的developer,能够透过接口来沟通,不相依于彼此实现,就能平行开发。

What

Unit Test 的定义与基本准则,以下图所示:

  1. 一个测试案例只测一种方法
  2. 最小的测试单位
  3. 不与外部(包括项目、数据库、网络、服务、对象、类型)直接相依
  4. 不具有逻辑
  5. 测试案例之间相依性为零

Unit Test的特性,一个字:FIRST。以下图所示:

  1. Fast:快速。
  2. Independent:独立。
  3. Repeatable:可重复。
  4. Self-Validating:可反应验证结果。单元测试不论成功或失败,都应该要从测试的reporting 直接了解其意义或失败缘由。
  5. Timely:及时。单元测试应该刚好在使其经过的production code 以前撰写。

 即:优良的单元测试具备如下的特色:简称为 A-TRIP。    

  • 自动性(Automatic)
  • 完备性(Thorough)
  • 可重复性(Repeatable)
  • 独立性(Independent)
  • 专业性(Professional)

Where

单元测试的覆盖范围,以定义来讲,单元测试是最小的测试单位,在面向对象中,就是测试一个方法。而方法必定会在某个对象上(即便是静态方法,也是在类型对象上)。

因此,单元测试一般就只关注在测试的目标对象上,而无论目标对象之外的东西,例如:目标对象所相依的实体对象、相依服务、相依资源、相依环境等等...

单元测试,简单的说,就是用来模拟外部如何使用这个目标对象,或是如何与这个目标对象互动。因此咱们所撰写的单元测试程序,就是模拟与目标对象互动的程序。测试案例,就是该互动下的情境。接着验证物件的行为是否符合咱们预期。

所以,单元测试程式,既然是模拟外部如何使用目标物件,因此也只会针对目标对象对外开放的方法。

而基本上,单元测试透过哪些方式去验证对象的行为符合预期呢?简单来讲,有三种:

  1. 验证目标对象的回传值,以下图所示:
  2. 验证目标对象的状态改变,以下图所示:
  3. 验证目标对象与外部相依接口的互动方式,以下图所示:

 

Who

单元测试该由谁来撰写,就如同前言所说,最应该撰写的是developer,而非QA/QE。

就如Where段落所说,单元测试简单的说,是咱们在设计对象的时候,预期外部该如何使用这个对象,进而衍生出对象该提供什么样的功能、具有什么样的行为。正由于对象的设计人、使用人,都是developer,因此单元测试的程式,固然由developer来设计,最为稳当。尤为由用的人来写,最为精准。

概括几个基本要点:

  1. 想要达到什么需求,就是测试案例。而对象的设计,只是为了知足需求,需求即测试案例。即生产代码只为了知足测试程序上的测试案例。
  2. 设计对象的人员,才能知道对象该怎么给外面使用。
  3. 由外部使用对象的角度来设计测试案例。

When

撰写单元测试的时机点,简单​​分红三个:

  1. 外部须要使用对象,并对其执行结果有所预期时( developing )
  2. feature的异动时( modifying )
  3. 出现非预期执行结果时( bug fixing )

想清楚,外部的需求是什么,才能设计出符合需求的对象。

当需求异动时,天然须要针对新的需求,来设计新的测试程序,由于这样才能驱使目标物件行为的改变。

当出现非预期的执行结果时,一般表明目标物件有着非预期的行为发生,有多是当初测试案例不足,因此要增长咱们的「预期」。

也有多是当初预期的结果就错了,那其实就能够看成是第二点,需求的异动。(固然对使用端来讲,仍是属于bug,但对对象设计来讲,测试案例方向就错了)

Test Cases的意义

你们买过3C产品或电器吧,基本上拿到一个东西,咱们都会先看使用说明书。

你们确定也写过一堆「系统分析书」、「代码规格书」、「SA/SD 文件」等等...但这些文件,跟最后线上的代码,究竟有多少是相同的呢?文件越详细,表明后面修改的effort 越大。

由于软件设计,原本就是个需求频繁变更的过程,每每你们只想「冻结需求」,却很常由于「冻结需求」搞到做出来的系统难用,由于不符合使用者需求。

咱们指望的是,每一次的需求异动,都是软​​件进化的动力,每一次的异动,都是品质的累积,以及更符合使用者的需求。

而文件呢?只有一开始分析、设计爽的,由于代码写下去,跟文件搭不搭的起来,只有三我的知道,一个已经离职了,一个是我,另外一个我不能说。

鲜少会有文件跟着代码一直进行更新的。

但文件却又是辅助了解与说明很重要的东西,那怎么办?很简单,会一直活着的,就只有代码。要验证代码是否符合咱们预期,最简单的方式,就是用代码验证它的行为,一翻两瞪眼,如今的物件究竟知足了那些功能,哪些情境下能够跑出预期结果,测试案例一目了然。

因此,测试案例的意义与价值是什么?

  1. 可自动执行、立刻执行、快速执行的对象使用说明书,不会有过时或漏了更新的问题。
  2. 无论什么状况发生,无论在什么环境底下,都能确保其执行结果如同预期。

代码即文件,高兴何时产生文件,就何时产生,保证即时、可运做、童叟无欺。测试案例上面有的,确定work,而测试案例上面没有的,不必定会错,但不打包票。

 

小结

一句话总结:「Working software is based on working test cases」。

Working software 是TDD 的整个骨架,也是user 最须要的东西。

 备注:这个系列是我毕业后时隔一年从新开始进入开发行业后对大拿们的博文摘要整理进行学习对自个人各个欠缺的方面进行充电记录博客的过程,非原创,特此感谢91 等前辈

相关文章
相关标签/搜索