接口测试代码流程
- 准备前置条件及后置条件(包括依赖接口的准备、初始化某个对象)
- 准备测试数据(即ddt)
- 替换测试数据中的动态参数,如:#member_id#(非必须)
- 调用接口前的相关处理(如:查询数据库,调用生成手机号函数生成未注册的手机号)(非必须)
- 发起请求,调用接口
- 验证结果是否符合预期(断言)
测试夹具
测试夹具也就是测试用例的前置条件及后置条件,分为两个类型:
- 接口依赖
这是从业务层面上来说的。比如投资接口需要依赖登录接口、充值接口、添加项目接口、审核项目接口。 - 代码依赖
这是从代码层面来说的。比如每执行一个测试用例,都需要初始化一个db对象(根本目的就是初始化游标对象,因为多个测试用例不能重复使用同一个游标,否则查询不到结果);执行完所有的测试用例后,需关闭db对象。 - 根据需要选择测试夹具级别
无论是接口依赖还是代码依赖,都需要根据需要选择测试夹具的级别。如每执行一个测试用例时,我都需要获取依赖接口的新数据而不能使用已有的旧数据,或者需要每执行一个测试用例都生成一个新的db对象,则使用setUp()、tearDown();如果执行所有的测试用例都只需要用到依赖接口的一条数据(如接口所依赖的登录接口,只需要登录一次就可完成所有测试用例的操作),或者所有测试用例都只需要初始化一次某个对象,则使用serUpClass()、tearDownClass()。
数据类型(非常容易出错)
如果没弄清楚测试类型而对数据进行想当然地处理,就极易出现报错。比如:前置条件中获取handler中的属性为str类型,如果把它当成int类型进行操作就会出现错误;又比如python读取excel中的数据均为字符串类型,如果当成字典来处理也会出现错误。所以当对变量进行操作前需明确这个变量是什么类型。
excel中参数化数据的替换
当测试时每次的测试数据都不一样(如headers中的token),或者不想在excel中写死,可在excel中设置一个标识,如:#token#,这种用标识标记一个数据,然后用真实数据替换掉这个标识的参数就叫动态参数。
在测试类中遇到标识时则用真实的数据进行替换。
如果需要替换的动态参数过多,则可在Handler中写一个替换动态参数的方法,运用正则表达式替换动态参数的标识;然后在测试类中调用这个方法对所有的动态参数标识进行替换即可。
数据库操作
进行数据库相关操作时需要注意以下几点:
- 封装数据库操作的通用类时:
- 需要根据查询结果的数目分别封装查询结果为1个记录的方法和查询结果为多个记录的方法;
- 在调用游标对象的execute方法执行sql前,需要提交事务,把最新的数据进行更新,否则无法查询到新的数据;
- 一定要封装关闭游标对象和连接对象的方法。
- 在测试类中调用数据库操作通用类进行数据库操作时:
- 需要在函数级别的前置条件中初始化db对象,以保证每次调用测试类方法时都生成一个新的游标对象;
- 在函数级别的后置条件中关闭db对象,以减少不必要的资源消耗。
测试驱动
测试驱动思想
测试驱动可理解为用测试数据来驱动测试类的执行。如有以下两个测试数据:
第一条测试数据驱动测试类的执行,那么这个测试类测试的就是“投资人正常投资”的测试用例,在执行时调用接口时的请求参数传入的是“投资人正常投资”这条用例的测试数据,断言也是以“投资人正常投资”的结果与预期结果进行断言;接着第二条测试数据驱动测试类的执行,那么这个测试类测试的是“投资人id为空”的这条用例。由此可以看出,你用不同的数据,测试的用例也是不同的。
测试数据
测试数据不一定非要放到excel中,还可以单独写到python的一个模块当中,甚至可以放到yaml当中,只要在测试模块中能够读取出来即可。
测试驱动代码实现
ddt的代码实现分为两个步骤:
- 在测试类上写上装饰器:@ddt.ddt
- 在需要用到测试数据的测试方法上写上装饰器:@ddt.data(*测试数据变量名)
@ddt.ddt
class TestCase(unittest.TestCase):
@ddt.data(*test_data)
def test_add(self, test_info):
print(test_info)
断言
一般用例断言
一般用例是指不需要进行数据库操作的测试用例,一般是业务执行失败、接口返回错误结果的测试用例。
一般用例的断言只需要对调用接口后的返回结果进行断言即可。
特殊用例断言
特殊用例是指需要进行数据库操作的测试用例,一般是业务执行成功、接口返回成功结果的测试用例。
特殊用例的断言既需要对接口的返回结果及数据库表数据同时进行断言,且当接口的状态码或返回信息符合某个条件(一般是执行成功的条件,如:code=0,msg=“登录成功”)时才进行数据库表的断言。对于数据库表的断言来说,需要注意以下几点:
- 如果需要用调用接口前的数据库表数据与调用接口后的数据库表数据进行比对断言,则需要在调用接口前查询一次sql,在调用接口后再查询一次sql,如投资用例:
- 如果接口执行成功后,会改动到多个表的某个字段的数据或同一个表的多个字段的数据,则这些字段均需要进行断言。如投资成功的用例,既会往invest表中插入一条新纪录,又会改动到member表中leave_amount字段的数据,则需要同时对这两个表的这两个字段进行断言:
复杂用例的处理
对于一些复杂的用例,如果用代码实现起来相当麻烦,可以不必非要使用代码进行测试,可手工进行测试。
mock测试
什么是mock测试?
Mock 测试就是在测试过程中,对于某些不容易构造或者不容易获取的比较复杂的对象,用一个虚拟的对象来创建以便测试的测试方法。
说白了就是模拟接口的返回数据进行测试,而不会用真实接口的返回数据。如:调用支付宝接口,直接用mock模拟调用支付宝接口的返回结果,这个返回结果即可作为实际结果与预期结果进行断言。
为什么需要用mock测试?
- 接口还未完成。为了不耽误接口自动化代码的编写,可使用mock来模拟接口的返回结果;
- 第三方接口不方便调用。如支付接口、芝麻信用等。
代码实现
安装mock
pip install mock
例子
日志记录及异常分析
日志记录
代码中我们需要对阶段性的代码进行标记(如:准备测试数据的地方、请求接口的地方、进行断言的地方等),又或者需要对一些可能会发生错的地方记录日志,此时我们需要初始化logging_handler来帮我们记录日志:
遇到异常时的分析思路
- 业务逻辑分析。当遇到报错时,先对业务逻辑进行分析,分析下正常的业务逻辑是怎样的,代码有没有按照业务逻辑进行处理(如前置条件中依赖接口的准备等),是业务流程中的哪一步出了错;
- 代码逻辑分析。
- 如果有TraceBack指明每一个出错的地方,可依次点击链接进入出错代码的地方。如果这行代码是调用了某个函数,则进入这个函数分析下代码的处理逻辑;如果这行代码没有调用函数,则联系上下行代码分析代码的处理逻辑;
- 如果没有TraceBack指出出错代码的位置,则可根据一些线索(如:业务逻辑分析结果、打印某个变量等)找出出错的某一行代码或多行代码(可能涉及多个函数、多个类、多个模块),根据上下文或调用函数的处理逻辑进行分析;
- 如果还是找不到原因出在哪,可打debug进行调试。