用例步骤的数据驱动
小白 初识博客园~~
记录下自动化测试一些值得注意的点
-----------------------------------------------------------
数据驱动:
脚本与数据分离的模式增强了对代码的复用,初学者都是沉迷使用python框架中自带的装饰器@ddt.data 、@pytest.mark.parametrize
最近看了些相关资料,除了用例数据的数据驱动,还有用例步骤的数据驱动、配置的数据驱动
我想说的是后者,实话拿着github代码的思路,自己封装了一遍
以下是原始代码
@pytest.mark.parametrize("name", file['data'], ids=['用例1', '用例2', '用例3']) @assert_logger def test_tagsave(self, name):
# 环境清理
# 步骤1: 调用接口获取标签列表
self.vip.taglist(pagesize=10, pageindex=1, querytype=1, tagname=f"{name}") # 步骤2: 调用rjsonpath提取tagid
tagidsdata = self.vip.rjsonpath(f"$.data[?(@.name == '{name}')]") if tagidsdata is not False:
# 步骤3:调用接口删除已存在的tagid
self.vip.tagdelete(tagid=tagidsdata[0]['id'])
# 步骤4:调用新增标签接口测试
r = self.vip.tagsave(name=f"{name}", type=1, ruletext=None)
# 步骤5: 断言新增标签
assert r.success is True
# 步骤6:调用列表接口、删除接口清理环境
r = self.vip.taglist(pageindex=1, pagesize=10, querytype=1, tagname=f"{name}")
tagid = self.vip.rjsonpath(f"$.data[?(@.name == '{name}')]")[0]['id']
r = self.vip.tagdelete(tagid=tagid)
从上面的代码看来,一条新增标签接口的测试用例由不同的接口依次调用进行测试,正是我们测试人口中经常提起的业务测试。
@pytest.mark.parametrize("name", file['data'], ids=[1, 2, 3])
@assert_logger
def test_tagsave_steps(self, name):
self.vip.params = {"name": name}
self.vip.steps_run(self.file['steps'])
从上可见,一行代码就能把业务封装,我i们只需要着手写去对应的 file就可以了
而file得形式不拘泥于excel、json、yaml,甚至是py文件(我个人比较喜欢yaml形式,深受httprunner工具得毒害~,听说它又改为py文件了,确实yaml很难找到格式错误之处)
看着这份yaml文件,明白了原来关键字驱动也就是这么回事~,操作与业务分离,操作生成代码,高级一点的数据驱动
以下file文件,yaml 和 steps_run方法
data: ["测试", "高级测试", "测试开发"] steps: - {method: vip.taglist, pagesize: 10, pageindex: 1, querytype: 1, tagname: '${name}'} - {path: "$.data[?(@.name == ${name})]", extract: tagid, conditions: "['id']"} - {method: vip.tagdelete, tagid: "${tagid}"} - {method: vip.taglist, pagesize: 10, pageindex: 1, querytype: 1, assertext: result1} - {method: vip.tagsave ,name: "${name}", type: 1, ruletext: None} - {assertion: ["res['msg']", eq, 'ok']} - {method: vip.taglist, pagesize: 10, pageindex: 1, querytype: 1, tagname: '${name}'} - {path: "$.data[?(@.name == ${name})]", extract: tagid, conditions: "['id']"} - {method: vip.tagdelete, tagid: "${tagid}"} - {method: vip.taglist, pagesize: 10, pageindex: 1, querytype: 1, assertext: result2} - {assertion: [result1, eq, result2]}
class KDT: def __init__(self): pass def __new__(cls, *args, **kwargs): if not hasattr(KDT, "_instance"): KDT._instance = object.__new__(cls) return KDT._instance def start(self, objec, params: dict, data: dict, steps): for step in steps: raw = yaml.dump(step) templatel = Template(raw) print(params.update(data)) step = yaml.safe_load(templatel.safe_substitute(dict(params, **data))) for oprerate in [i if isinstance(step, dict) else Exception(f"请检查参数替换{step}") for i in step.keys()]: if oprerate in self.__dir__(): getattr(self, oprerate)(objec, data, step) def method(self, objec, data, step): method = step['method'].split('.')[-1] if "$" in str(step): raise Exception(f"请检查参数替换{step}") res: ResultBase = getattr(objec, method)(**step) data['res'] = res.res if step.get("assertext", False): data[step['assertext']] = res.res def extract(self, objec, data, step): step_value = getattr(objec, "rjsonpath")(**step) if isinstance(step_value, list): step_value = step_value[0] if step.get("conditions", False): if isinstance(step_value, str): step_value = json.loads(step_value) if step_value is not False: step_value = eval("step_value" + str(step['conditions'])) else: print(f"提取参数失败,参数如下:{step}") data[step['extract']] = step_value def assertion(self, objec, data, step): assertion = step['assertion'] if isinstance(assertion, str): assert eval(assertion) if assertion[1] == 'eq': if data.get(repr(assertion[0])) is not None: assert data[repr(assertion[0])] == data[repr(assertion[2])] elif 'res' in str(assertion): res = data.get('res') # assert eval(assertion[0]) == assertion[2] pass
————
我愿翻山越岭,我愿乘风破浪。只为你,扬帆,远航...

浙公网安备 33010602011771号