一、什么是UT
UT测的是方法,检验的是一个类对外界的承诺。因此,大多数情况下,我们测的应该是公共方法,除非不得已才对私有方法进行测试。 方法是程序设计的最小单位。UT的局限也体现在这里,它并没有针对类之间的交互做检验。所以,不能指望单元测试做完了,就没有问题了。在这个方面的欠缺,我们可以通过自动化的功能/组件测试来完成。这也是开发者测试的一部分。
二、UT的任务
1. 尽早的发现问题 说白了,就是不要让问题流出去。让我们的缺陷率降低,把我们的产品做的漂亮。另一方面,一些细类度的问题在这里也确实更容易发现,同时也为进行更大粒度的测试做好集成准备。
2. 编织一层保护网
给新的代码建立有效的保护。 保证对代码每一份改动,都不会对现有系统造成伤害。避免了引入问题。
3.写出优雅的代码
编写单元测试的过程,实质是使用我们自己代码的过程。我们成了第一个真正意义上的体验者。在这个过程中,我们为了使代码易用会进行不断的重构。最终的交付代码必然会更优雅。
4. 建立程序员的自信
我们习惯于两眼一抹黑,不管三七二十一就把代码写完了。Code阶段结束,然后不断的调试,修修补补跑起来就过了TR4。没人敢说,他代码一写完了,就能跑起来。这种做法是很没人性的,系统搞挂几次后就心里发虚,一点底气都没有。但是,这是我们的职业,我们为着自己的荣耀而战。在任何时候,都需要信心满盈。
三、UT的基本原则
1.一个类、一个方法、一条路径 我们一次只测一个类的一个方法。刚开始做单元测试的时候,很多人会自然而然的做成了功能测试。因为,前一部分执行的结果恰好为后一部分准备好了输入。而另一方面,连续的执行过程组成了一个明确的场景,让具体的功能变得完整可见,这正是我们期待的,让我们变得有信心。那为什么不顺其自然呢?
原因在于:
1)、单元测试要保证一定的微粒度。从单元测试到功能测试,这之间的粒度会越来越大,越往后,我们会越少的关注细节。如果直接跳跃到功能测试上,会让我们遗漏掉一些问题,在以后的粗粒度测试中,它们会转变为很难重现或者不可重现的致命问题。
2)、上述场景之所以会出现,是因为先写代码后写测试导致的。相当于代码已经集成,具备了做功能测试的一定条件。这个时候让再走回头路做单元测试,当然不如直接就做功能测试来的顺当。所以,应该一个测试、一个方法,一个方法一个测试,这样不断的一步一步的循环迭代集成来的好。
另一方面,为了将一个方法的多个不同的执行路径分开,我们必须保证一次只测一个方法的一个路径。这样,前置条件和后置条件就会很明确,容易准备测试环境。
2.重构以便于测试
面对着一个方法,你感到一筹莫展。并不是你的错,而是因为这个方法很烂。测一个方法就是在使用这个方法,你自己都这样无奈,将来真正使用的人岂不是要骂娘?雁过留声,人过留名。这个时候,重构一下很值得。
3.保证测试方法简洁
如果连测试方法都很复杂,难道我们还要再写测试用例来保证它的正确执行不成?这样岂不是麻烦大了!所以,测试方法一定要写的尽可能的简单,写到你认为白痴都能看懂的程度。
四、如何才能做UT
1.代码要首先可测,然后才能测。 首先要遵守契约式设计。类的每一个方法都应该对外承担了一份契约,有明确的前置条件和后置条件。 当你对这个方法进行测试之前必须清楚明白这两个条件。一个有效的方法一定是做了什么事的。一定会产生一定的影响,我们可以通过对外围环境的改变来检测方法产生的作用是否如预期(例如,获取某一对象的属性进行检测)。
其次是,低Ce和单一责任原则。一个方法对外的依赖应该单一,不应该取决于很多的外部环境。因为不同的外部环境越多,组合项就越多,要测的先决条件就越多。而一个方法对外部环境的影响太多,则意味着职责不单一,对于输出越难测。
曾经听有人讲到,这些道理,你懂了就懂,不懂就不懂,说了没用。但我认为,如果你还以为这些只是大道理,如果你还想对它有点切身的感受,做单元测试是一个很好的途径。
文章来源于领测软件测试网 https://www.ltesting.net/