单元测试——基础概念

前言

我们都写过的某种测试

不要惊讶,你已经进行过某种程度的单元测试。你见过提交代码前不做测试的开发人员吗?
在传统测试中,开发人员使用一个图形用户界面触发要测试的类的某个行为,然后检验结果。

那什么是单元测试,什么不是单元测试呢?

为什么不写单元测试

不想做

往往说不想的,其实是因为还不会。因为不会,所以想一想就很麻烦,还不如手工测试呢。

多余

我已经写好代码,然后还要去确认写好的逻辑,好多余

  • 我们不能确保我们的代码是100%正确的。有可能因为精神不好,原因需要抛异常的地方,忘了写一个throw呢?结果原来需要回滚的事业,没正常回滚。
  • 我们在写实现的有很多逻辑,甚至有一些异常处理。因为我们在假设某些场景。其实这些场景就是简单的单元测试。所以又写一遍会觉得很多余。
  • 代码都实现完了,写单元测试干什么。其实代码还没有实现完!有可能还要重构,有可能你还需要排错,有可能别人接手你的代码。但是你没有一个办法保证你的代码一直是正确的。

因为我们没有遵循正确的TDD实践,所以觉得不舒服和多余。

经常修改

单元测试一旦通过,不会经常修改。一般有两大类经常修改情况:

  • 确实需要修改单元测试,因为接口需求变更了。所以有些单元测试没有某些业务的考虑,所以要删除或者修改这些单元测试,否则反而会报红。
  • 但是往往更多的是第二类。接口需求不变,重构的时候因为报红了,所以强行修改单元测试。因为依赖变了,甚至有些顺序变了,所以原来的单元测试报红了。那说明本来的被单元测试的代码本身就依赖性太强。一般需要修改的是重构代码本身。而且单元测试的每个case最好是隔离的。

太浪费时间

是的,单元测试确实会增加编码的时间。但是从整个软件的交付时间比来说,有好的单元测试的时间会交付更快。一般有健全的单元测试,在测试阶段和维护阶段会花费更少的时间。我们在做的是一个完整的软件,所以时间应该算总的周期
另外一个原因,有可能是因为不熟练或者没有合适的工具,所以花了大量时间在重复的工作之上。

不务正业

其实咱们一直在做不务正业的事。调试代码,给代码加注释,画流程图,上网解决问题等等。这些其实都是开发者的日常工作。所以单元测试也是!!

这里也有一篇文章,也比较有意思:为什么要进行烦人的单元测试?

什么是单元测试

那到底什么是单元测试呢?

一个单元测试是一段自动化的代码,这段代码调用被测试的。这段代码调用被测试的工作单元,之后对这个单元的单个最终结果的某些假设进行检验。单元测试几乎都是用单元测试框架编写的。单元测试容易编写,能快速运行。单元测试可可靠、可读,并且可维护。只要产品代码不发生变化,单元测试的结果是稳定的。

特性

  • 它应该是自动化的,可重复执行。
  • 它应该很容易实现
  • 它应该第二天还有意义
  • 任何人都应该能一键运行它
  • 它应该运行速度很快
  • 它的结果应该是稳定的(如果运行之间没有进行修改的话,多次运行一个测试应该总是返回同样的结果)
  • 它应该能完全控制被测试的单元
  • 它应该是完全隔离的(独立于其他测试的运行)
  • 如果它失败了,我们应该很容易发现什么是期待的结果,进而定位问题所在

包含行为

  1. 准备(Arrange)对象,创建对象,进行必要的设置
  2. 操作(Act)对象
  3. 断言(Assert)某件事情是预期的。

结果类型

从调用系统的一个公共方法到产生一个测试可见的最终结果,其间这个系统发生的行为总称为一个工作单元。一个最终结果有三种形式

  1. 带有返回值的。即基于值的测试。
  2. 在方法调用前后,系统的状态或者行为有可见的变化 ,这种变化无需查询私有状态即可判断。即基于状态测试。
  3. 调用一个不受测试控制的第三方系统,这个第三方系统不返回任何值,或者返回值都被忽略。即交互测试。

验证

很多人把进行软件测试的行为和单元测试概念混为一谈。要澄清这个误解,你首先应该回顾自己以前写过的测试,问自己如下问题。

  1. 我两周前写的一单元测试,今天还能运行并得到结果吗?几个月前的呢?几年前的呢?
  2. 我两个月前写的单元测试,我团队里任何一个人都能运行它们并得到结果吗?
  3. 我能在几分钟内跑完我写过的所有单元测试吗?
  4. 我能一键运行我写过的所有单元测试吗?
  5. 我能在几分钟写出一个基本的测试吗?
    如果能的话,那就是单元测试。如果不能,那有可能就是集成测试。

什么是集成测试

那到底什么是集成测试呢?

集成测试是对一个工作单元进行的测试,这个测试对被测试的工作单元没有完全的控制,并使用该单元的一个或者多个真实依赖物,何如时间、网络、数据库、线程或者随机数产生器等
总的来说,集成测试会使用真实依赖物,而单元测试则把测试单元和基依赖物隔离开,以保证单元测试结果高度稳定

并不是说集成测试不重要!单元测试和集成测试具有同等重要的地位,但是这两个测试应该彼此分开,以营造一种“绿色安全区”的感觉

什么是TDD

上面说的是什么是单元测试。那么什么时候编写测试呢?很多人觉得为软件编写单元测试的最佳时机是软件编码完成以后,但是越来越多的人选择在产品代码编写之前写单元测试。这种方法称为测试优先或测试驱动开发(Test-Driven Development, TDD)。
执行步骤:

  1. 编写一个会失败的测试,以证明产品中代码或功能的缺失。编写测试的时候,要假设产品代码已经能工作了,这样测试的失败就说明产品代码中有缺陷。
  2. 编写符合测试预期的产品代码,使测试通过。产品代码应该尽量简单。
  3. 重构代码。如果测试通过了,你就可以编写下一个单元测试,或者进行重构,使代码可读性更强,或者去除重复代码等。

红-->绿-->重构


本文的概念大部分出自于《单元测试的艺术》,特此说明。因为书里的概念讲得是我想要的,比网上搜的其他资源要适合自己些。
更具体的概念可以翻阅《单元测试的艺术》。

posted @ 2015-10-26 17:34  庄君祥  阅读(1457)  评论(0编辑  收藏  举报