单元测试
单元测试--Clean Code
1. 什么是单元测试?(what)
单元测试,是指对软件中的最小可测试单元进行检查和验证。
开发者编写一小段代码,用于检测被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件下某个特定函数的行为。
所以我们可以理解为,单元测试不关注被测函数的所处位置,前置或后置条件,关注仅关注函数的本身。
2. 为什么需要单元测试?(why)
保证程序在提交版本库之前是完全正确的
bug隐藏的时间约长,修复bug的代价越大
具有回归性,可以快速的进行回归测试
为重构提供保障
3. 单元测试如何验证?(how)
1.函数有输出结果时:验证函数的输入输出结果
2.在没有输出结果的时候,分为两种情况:
(1)判断函数是否对某些特定值进行修改,对特定值进行验证
(2)判断函数是否调用第三方库或方法,对第三方库进行mock,然后验证是否调用
4. TDD测试驱动开发 (when)
测试代码与生产代码一起编写,测试只比生产代码早写几秒钟。
开发过程如下:
1.明确当前要完成的功能
2.快速完成针对此功能的测试用例编写
3.测试代码编译不通过
4.编写对应的功能代码
5.测试通过
6.对代码进行重构,并保证测试通过
7.循环完成所有功能的开发
//测试代码 public class HikerTest { @Test public void life_the_universe_and_everything() { int expected = 42; int actual = Hiker.answer(); assertEquals(expected, actual); } } //生产代码 public class Hiker { public static int answer() { return 6 * 9; } }
TDD三个测试准则
写代码只为修复失败了的测试
在写代码之前先写一个失败的单元测试代码
只可编写刚好无法通过的单元测试,不能编译也算不通过
只编写刚好足以通过当前失败测试的功能代码
使用TDD开发,会写很多小的自动化测试,这些测试最终会组成一个有效的预警系统以防止代码蜕化。
5. 保持测试整洁
测试必须随着生产代码的演进而修改,测试越脏,就越难修改。
测试代码和生产代码一样重要,它应该和生产代码一样保持整洁。
什么是整洁的测试?
三个要素:可读性、可读性和可读性。
在单元测试中,可读性是重中之重。要求和生产代码一样:明确,简洁,还有足够的表达力。
测试的三个模块?
Given--构造测试数据
When--操作测试数据
Then--检验操作是否得到预期结果
6. 每个测试一个断言
有人认为,每个测试函数都应该有且仅有一个断言语句。单个断言是个好准则,但是最好的做法是单个测试中的断言数量应该最小化。
每个测试是指每个测试函数针对一个测试用例。
例:在一个函数中,流程图如下
st=>start: cond=>condition: Yes or No? sub=>subroutine: Your Subroutine e=>end st->cond cond(yes)->e cond(no)->sub->io
测试用例应该有两个:
void testNo() { } void testYes() { }
7. 整洁的测试准则
快速:测试应该够快,能快速运行。运行缓慢的测试不是单元测试。
独立:测试应该相互独立。不能依赖于其他测试模块,执行顺序等第三方条件。(当测试互相依赖时,一个有缺陷的模块会导致一连串的测试失败)
可重复:测试可以在任何环境中重复通过。(生产环境,断网,质检环境等)
自足验证:测试应当有布尔值输出。不论通过或者失败,不应该查看日志来确认是否通过,以及手工对比文件来确认测试是否通过。
及时:测试应及时编写。单元测试应恰好在使其通过的生产代码之前编写。如果在完成之后编写,会发现生产代码难以测试,甚至不可能去测试。
8. 重构
开发周期的最后一个过程叫做重构。
重构:在不改变系统外部行为的前提下,改善它的内部结构。重构时不仅不能引入缺陷,也不能添加新功能。重构应该保持系统原有的行为。
重构是TDD测试-开发-重构的最后一步。使用TDD而不重构能迅速产生大量的烂代码。无论有多么充足的测试,烂代码终归是烂代码。优良的代码质量能保证今后的开发效率,所以重构必不可少。
9.测试问题
如何测试私有方法?
通过设计测试用例,测试调用私有方法的共有方法,来实现对私有方法的测试。
如何解决对第三方库的依赖?
在方法中若需要使用第三方库或其他函数,可以使用mock工具解决依赖
一个类中是否所有的方法都需要测试?
构造函数不需要测试,getter,setter方法也不需要测试。其他的不论简单与否都应该有测试用例覆盖。
单元测试的测试用例设计
白盒测试主要针对程序的逻辑结构设计测试用例,逻辑单位主要有:语句,分支,条件,路径等。
简单一点的讲,最少的测试用例来最大化满足条件覆盖,分支覆盖,和路径覆盖。