目录

强行为新项目写接口测试是一种什么样的体验

继续上次的话题,为新项目写 ui 自动化测试是一件非常有挑战的事情,写接口测试会不会容易一点呢?这次我就尝试了一下。

现阶段我们的管理端接口其实不多,就 8 个左右,所以从工作量上评估其实还可以。

测试策略

讲策略之前我们先看一下项目的简单业务属性。该项目的管理后台其实就是稍微复杂一点的增删改查。增加一条记录,编辑记录,各种组合条件查询记录,删除功能暂时没有,后面可能会跟进。

我的测试策略也很简单,首先搭建 1 个单独的测试环境,防止跟其他测试形式冲突,然后把最大的精力放在数据的准备和清理上。

  • 准备数据:为了测试查询,比较好的方式是每次都先清空数据库,然后动态创建一些固定的数据,我指的固定是比如固定 100 条,每条的排序规则,各个字段都是确定的。
  • 数据清理:完成测试后清空数据库,比如搜索测试完成之后清空数据库去测试创建和编辑,这样创建的时候就没有存量数据造成的断言干扰,就可以实现每次创建之前数据都是 0 条,创建成功之后变成 1,这样断言就相对容易,而且用例能够以随机的顺序运行,减少了依赖;

代码实现

这里最有挑战的是数据准备和清理的代码实现,我需要准备下面的数据

  • 通过接口创建一些数据到 db,之所以用接口创建是因为一些联动的操作直接写 db 的话无法触发。我们的接口是 http 的,用 python+requests 就可以了,稍微麻烦的点是构造的数据需要通过接口的有效性校验,比如时间区间之类的,因为我们的服务会跑在多个不同的国家和地区,timezone 也是需要关注的
  • 把创建成功的数据 id 以及一些需要用到的字段存到 redis 里。我习惯于用 redis 的 set,因为天生去重,并且可以使用srandmember来随机返回几条数据,在做查询校验的时候非常方便
  • 查询一些关联表的信息或者需要用到的数据,保存在 redis 里。这里我用的是 redis 的 string 类型,需要保存的信息直接序列化成 json 字符串,非常的方便;
  • 直接写 sql 做数据库的清理,直接调用 es 的 resetful api 做索引的清理。我们的查询使用的是 es,所以清理数据的时候除了用 sql 去 delete 之外,es 的 index 也是要清理的
  • 使用配置文件来进行多环境多地区的配置,比如 mysql 每个地区的配置都不一样,同样的地区不同的业务数据也在不同的库里,把配置弄起来还是很有必要的

最终实现的效果是运行TEST_ENV=test REGION=cn python data_builder.py这条命令之后就可以在对应的环境创建初始化数据了。代码比较啰嗦我就不粘贴了。

用例编写

用例编写无非是增删改查。

新增记录

  • 测试各种边界条件,比如一些字段本来是必填的,就是任性不填。本来要求 string 类型结果传 number 类型等待
  • 测试正常的情况,起码要把正常流程跑通

下面是一个例子

def test_ads_target_keyword_list_should_be_mandatory(valid_data_set):
	del valid_data_set['target_keyword_list']
	res = common_helpers.post_with_cookie("/create", valid_data_set)
	common_assertion(res)
	assert res['code'] != SUCCESS
	assert 'required' in res['msg']

这里可以分享 2 点有意思的地方

  • 返回值的错误码尽管可以枚举,但是逐一判断还是比较麻烦的,这里我就直接断言返回码不等于 SUCCESS,SUCCESS 其实可以看成是一个宏,所有用例里都统一
  • 错误信息可以不需要精确判断,判断几个关键字是否存在就好了,比如上面例子里的 required

编辑记录

  • 从之前生成的记录里随机挑 1 条进行更新,因为我把所有初始化的记录 id 都存在了 redis 的 set 里,这一步其实就非常的自然了
  • 测试各种边界情况,除了字段的合法性之外还要测试一些编辑特有的用例,比如只能编辑自己的记录
  • 测试正常编辑成功的情况

搜索及查询

  • 因为数据是提前生成好的,所以我们可以构造各种条件来进行断言,比如我就构造了 10 条 active 状态的记录,10 条 inactive 的记录,按照状态来搜索时我可以直接断言,active 就是 10 条,多一点少一点就是 bug
  • 构造多维度的搜索条件,这样覆盖面就更广一点,比如按 A 字段搜索,按 B 字段搜索,按 A 和 B 组合在一起搜索等

比如这个用例

def test_search_with_no_conditions():
	page_size = 20
	data = {
		'filter': {},
		'page_num': 1,
		'page_size': page_size,
	}
	res = common_helpers.post_with_cookie(f"/action/search/list", data)
	assert res['code'] == SUCCESS
	assert len(res['data']['data']) == page_size

这里我没有传入任何条件,只判断了当前返回的数据条数必须等于 page size,因为我之前创建了足够多的数据,所以这个用例是非常安全和稳定的

总结

  • 最好有单独的测试环境
  • 用配置文件来保存各个环境的配置,有配置中心更好,这样就不用改代码
  • 在运行用例时通过环境变量来指定环境和地域,如果你的服务需要跑在多个国家和地区的话
  • 每次都创建自己的测试数据集,这样断言起来会更加的容易
  • 创建数据的脚本也可以用来进行 ui 自动化测试