测试用例框架优化(二)
不知道大家还记不记得,我们前面跟大家分享了测试用例框架优化(一)内容过程当中,还遗留了第三个问题:
第三个问题:关于字段替换的地方,当我们接口用例很多很多,上千条时候,一个一个的替换,你能确保你每个字段都替换了吗?
而且上百上千个接口一个一个替换也会显得比较麻烦。
现在抽空总结了以下继续分享出来:
我是对 正则表达式提取标识符后替换的过程封装成了一个方法:
我们创建一个替换的py文件:
——解决的问题:在编写测试用例时,用例涉及到的所有mark标识符(#...#)都能够替换成功
注意:
我们这里只是简单定义了一个函数,大家也可以定义成类,因为我们现在的功能比较少,如果说
你有更多的用法,像之前我们封装的requests 方法,实际上我们只有def send_requests(self,method,api_url, data,token=None):
是对外用的,但是里面有一些逻辑处理,我们就把它封装成了类,把一些步骤定义成私有方法处理,
所以道理是一样的,如果你未来你的项目替换有很多种情况,你可能需要扩充这里那里,如果你不喜欢
这个函数写的太长,你也可以像requests 封装一样写成一个类,对外的方法只有一个,其他的都是私有方法,你直接
调用就可以,思想是一致的。
import re
from common.my_data import Data
from common.mylogger import logger
from common.handle_phone import get_new_phone
def replace_case_with_re(case_dict): """ :param case_dict: 从excel当中是读取出来的一行测试数据。为字典形式。 :return: 替换之后的测试数据。类型为字典。 """ # 第一步,把excel当中的一整个测试用例(excel当中的一行)转换成字符串 case_str = str(case_dict) # 第二步,利用正则表达式提取mark标识符 to_be_replaced_marks_list = re.findall("#(\w+)#", case_str) # 第三步:遍历标识符mark,如果标识符是全局变量Data类的属性名,则用属性值替换掉mark if to_be_replaced_marks_list: logger.info("要替换的mark标示符有:{}".format(to_be_replaced_marks_list)) """ 上面的if :if to_be_replaced_marks_list: 只是将Data类里面的标识符替换进来了,我们 之前注册的时候还用到了"#phone#" 需要替换,这个也是我们在发起请求之前需要做处理的, 所以我们应该是需要全部做处理的,不应该漏掉,因为我们Data里面是没有这个属性的,所以替换 不了,那怎么办?所以我们用来替换的数据不一定都是来自响应结果当中提取的,也有可能来自与脚本生成 (比如phone),或者是配置文件,这些不在响应结果里面,但是我们这个框架Data 只是封装了响应结果的数据 而且我们这个框架只有一个phone 是特殊情况需要特殊处理。 ——解决方法: 写一个if 判断,判断是否有phone这个标识符,如果有,调用生成手机号码的脚本,然后替换 如果我们业务流多的情况下,也可以重新定义一个方法来处理 """ # 判断是否有phone这个标识符,如果有,调用生成手机号码的脚本,然后替换 if "#phone#" in to_be_replaced_marks_list: new_phone = get_new_phone() logger.info("有#phone#标识符,需要生成新的手机号码: {}".format(new_phone)) case_str = case_str.replace(f"#phone#", new_phone) # 从Data类当中取值来替换标识符。 for mark in to_be_replaced_marks_list: # 如果全局变量Data类有mark这个属性名 if hasattr(Data, mark): logger.info("将标识符 {} 替换为 {}".format(mark, getattr(Data, mark))) # 使用全局变量Data类的mark属性值,去替换测试用例当中的#mark# case_str = case_str.replace(f"#{mark}#", getattr(Data, mark)) logger.info("替换之后的用例数据为: \n{}".format(case_str)) # 第四步:将完全替换后的一整个测试用例,转换回字典 new_case_dict = eval(case_str) #我们替换后的数据是需要下一步使用的,所以这里要返回 return new_case_dict
上面的if :if to_be_replaced_marks_list: 只是将Data类里面的标识符替换进来了,我们
之前注册的时候还用到了"#phone#" 需要替换,这个也是我们在发起请求之前需要做处理的,
所以我们应该是需要全部做处理的,不应该漏掉,因为我们Data里面是没有这个属性的,所以替换
不了,那怎么办?所以我们用来替换的数据不一定都是来自响应结果当中提取的,也有可能来自与脚本生成
(比如phone),或者是配置文件,这些不在响应结果里面,但是我们这个框架Data 只是封装了响应结果的数据
而且我们这个框架只有一个phone 是特殊情况需要特殊处理。
——解决方法:
写一个if 判断,判断是否有phone这个标识符,如果有,调用生成手机号码的脚本,然后替换
如果我们业务流多的情况下,也可以重新定义一个方法来处理
封装完替换方法之后的测试用例代码示例:
import pytest import os import json from common.myConf import MyConf from common.my_path import conf_dir from common.my_requests import MyRequests from common.my_excel import MyExcel from common.my_assert import MyAssert from common.mylogger import logger from common.my_path import testdata_dir from common.my_data import Data from common.my_extract import extract_data_from_response from common.my_replace import replace_case_with_re # 第一步:读取注册接口的测试数据 - 是个列表,列表中的每个成员,都是一个接口用例的数据。 excel_path = os.path.join(testdata_dir, "测试用例.xlsx") print(excel_path) me = MyExcel(excel_path, "充值接口") cases = me.read_data() # 第二步:遍历测试数据,每一组数据,发起一个http的接口 # 实例化请求对象 mq = MyRequests() massert = MyAssert() class TestRecharge: @pytest.mark.parametrize("case", cases) def test_recharge(self, case): """ 这里我们把之前的替换方式直接去掉,引用进来我们封装好的替换方法就可以 :param case: :return: """ # 1、第一步:替换,找到需要替换就替换,没有就不需要 case = replace_case_with_re(case) # 2、把替换之后的请求数据(json格式的字符串),转换成一个字典 req_dict = json.loads(case["req_data"]) # 3、发起请求,并接收响应结果 if hasattr(Data, "token"): resp = mq.send_requests(case["method"], case["url"], req_dict, token=getattr(Data, "token")) else: resp = mq.send_requests(case["method"], case["url"], req_dict) logger.info(resp.json()) # 结果空列表 assert_res = [] # 5、断言响应结果中的数据 if case["assert_list"]: response_check_res = massert.assert_response_value(case["assert_list"], resp.json()) assert_res.append(response_check_res) if False in assert_res: pass else: # 4、提取响应结果中的数据,并设置为全局变量 if case["extract"]: # 调用提取处理函数 extract_data_from_response(case["extract"], resp.json()) # 6、断言数据库 - sql语句、结果与实际、比对的类型 if case["assert_db"]: db_check_res = massert.assert_db(case["assert_db"]) assert_res.append(db_check_res) # 最终的抛AsserttionError if False in assert_res: raise AssertionError