什么是好的自动化测试?

测试的样子

我们用测试来保证代码的正确性,然而,测试的正确性如何保证呢?

测试保证代码的正确性,那测试代码的正确性也用测试保证?但你见过有人给测试写测试吗?没有。这是一个死循环问题。

既然给测试写测试行不通,那唯一可行的方案就是:

把测试写简单,简单到一目了然,不需要证明它的正确性。

所以简单的测试长什么样子。看一下 todo 的例子

@Test
public void should_add_todo_item() {
  // 准备
  TodoItemRepository repository = mock(TodoItemRepository.class);
  when(repository.save(any())).then(returnsFirstArg());
  TodoItemService service = new TodoItemService(repository);
  
  // 执行  
  TodoItem item = service.addTodoItem(new TodoParameter("foo"));
  
  // 断言  
  assertThat(item.getContent()).isEqualTo("foo");
  
  // 清理(可选)
  
}

我们把测试分成四段,分别是准备、执行、断言和清理。

准备 为了测试做一些主备,例如启动外部依赖服务,存储预置数据。

执行 测试阶段最核心的部分,测试被测目标的行为。通常来说,它是一个测试点,一般来叔,执行应该就是一个函数调用。如果是测试外部系统,就是发出一个请求。

断言 断言是我们的预期,负责验证执行的结果是否正确。

清理 可选部分。如果测试用到了外部资源,在这个部分要及时释放,保证测试环境被还原到最初的状态。例如,我们在测试中向数据库插入了数据,执行完后要删除插入的数据。

如果准备和清理部分是测试用例通用的,可以放到

tUp 和 tearDown 里去完成。

这四个部分,必须存在的是 执行断言

不执行,目标都没有,还测什么?

不断言,没有预期,也是白跑。

A-TRIP

有了测试的基本结构,如何衡量测试有没有做好呢?

有人把好测试总结成了一个说法: A-TRIP,其实是5个单词的缩写

  • Automatic,自动化;
  • Thorough,全面的;
  • Repeatable,可重复的;
  • Independent,独立的;
  • Professional,专业的。

Automatic,自动化 核心在自动化上,这也是为什么测试一定要有断言,因为只有在有断言的情况下,机器才能帮我们判断是否成功。

Thorough,全面 其实是对测试的要求,就是尽可能覆盖各种场景。另一个角度,就是测试覆盖率。

Repeatable,可重复 要求测试可以反复运行,并且结果都是一样的。这是保证测试简单可靠的前提,如果一个测试不可重复,那么我们将无法相信它的结果,测试也就失去了价值。

内存中执行的测试一般是可重复的。影响测试可重复性的因素主要是外部资源,例如文件、数据库、中间件、第三方服务等等。如果测试中遇到了这些外部资源,我们要想办法让这些资源在测试结束后,恢复原样。

文件可以采取临时文件的方式,如果是 JUnit5 可以使用 @TempDir

数据库可以采取事务,执行完毕回滚。

如果是第三方服务,可以采取模拟服务。

Independent,独立 测试和测试之间不应该有任何依赖.

什么是有依赖?什么叫有依赖?就是一个测试要依赖于另外一个测试运行的结果。比如两个测试都要依赖于数据库,第一个测试运行时往数据库里写了一些数据,而第二个测试在执行时要用到这些数据。也就是说,第二个测试必须在第一个测试执行之后再执行,这就叫做有依赖。

一些框架可以并行执行测试,测试之间有了依赖,测试就无法并行执行。

Professional,专业测试代码也是代码,也要按代码标准去维护。

测试的命名参考:

  • should_ 测试场景;
  • should_ 测试效果 _while_ 测试条件

例如,第一种命名,should_add_todo_item, 一般来说,这是正常情况的测试用例。

第二种命名表示在什么条件下,应该出现什么效果,比如

should_throw_exception_while_parameter_is_empty 可以用来描述异常。

总结

测试基本结构

  • 准备
  • 执行
  • 断言
  • 清理

测试质量衡量,A-TRIP

  • Automatic
  • Thorough
  • Repeatable
  • Independent
  • Professional

如果今天的内容你只能记住一件事,那请记住:编写简单的测试

Last Updated:
Contributors: mcs