
构建测试知识体系,欢迎关注python
“测试数据与测试脚本分离,对测试脚本进行参数化”
shell
正文字数1535数据库
前面两篇分别介绍了两种测试函数参数化的方法。json
使用Pytest的Hook函数进行测试参数化原来这么方便
数组
这篇文章,咱们来看看如何将数据和脚本分离,而且还可以实现参数化。微信
测试数据和测试代码在实际的测试工做中,每每是分开存放的,利于测试数据和测试脚本的分开来维护。好比,为测试用例添加几组新的测试数据,只须要修改测试数据文件,测试代码不须要动;若是是测试用例增长了新的校验点,只须要修改测试脚本,不须要修改测试数据文件。app
01编辑器
—函数
准备测试数据
如今在data/目录下建立一个用于存放测试数据的Yaml文件test_in_theaters.yaml,内容以下:
---tests:case: 验证响应中start和count与请求中的参数一致 input: method: GET path: /v2/movie/in_theaters headers: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36 : params: apikey: 0df993c66c0c636e29ecbb5344252a4a start: 0 count: 10 expected: response: title: 正在上映的电影-上海 count: 10 start: 0case: 验证响应中title"正在上映的电影-北京" input: method: GET path: /v2/movie/in_theaters headers: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36 : params: apikey: 0df993c66c0c636e29ecbb5344252a4a start: 1 count: 5 expected: response: title: 正在上映的电影-北京 count: 5 start: 1
熟悉Yaml格式的同窗,应该很容易看懂上面测试数据文件的内容。这个测试数据文件中,有一个数组tests,里面包含的是两条完整的测试数据。一个完整的测试数据由三部分组成:
case,表示测试用例名称。
input,表示输入参数。
expected,表示预期结果。
上面的input输入参数,是一个http请求对象,包含了被测接口的全部参数,包括请求方法、请求路径、请求头、请求参数。expected表示预期结果,上面的测试数据中,只列出了对请求响应的预期值,实际测试中,还能够列出对数据库的预期值。
02
—
编写测试脚本
新建一个测试脚本test_paramtrize_by_data_driven.py,内容以下:
import pytest
class TestDataDriven: def test_data_driven(self, parameters): print(parameters['input']) print(parameters['expected'])
首先看一下测试函数,在测试函数上方使用了一个叫作datafile的marker来为测试函数提供数据。测试数据的路径是相对于项目根路径的相对路径,这里表示的是测试数据是在项目的根路径下data目录中的test_in_theaters.yaml。测试函数经过parameters这个fixture拿到测试数据内容。
03
—
实现pytest_generate_tests Hook
上面测试脚本使用测试数据的方法,是在tests/conftest.py文件中的pytest_generate_tests函数中实现的。
import yamlimport json
def pytest_generate_tests(metafunc): ids = [] markers = metafunc.definition.own_markers for marker in markers: if marker.name == 'datafile': # 读取外数据 test_data_path = os.path.join(metafunc.config.rootdir, marker.args[0]) # 拼接测试数据路径 with open(test_data_path) as f: ext = os.path.splitext(test_data_path)[-1] if ext in ['.yaml', '.yml']: test_data = yaml.safe_load(f) elif ext == '.json': test_data = json.load(f) else: raise TypeError('datafile must be yaml or json,root must be tests') if "parameters" in metafunc.fixturenames: # 用外部数据进行参数化 for data in test_data['tests']: # 用test_data中的case做为测试用例名称 ids.append(data['case']) # 用test_data这个列表对parameters进行参数化。 metafunc.parametrize("parameters", test_data['tests'], ids=ids, scope="function")
metafunc.definition.own_markers能够读取到测试函数中全部的marker,若是存在datafile这个marker,表示须要从外部读取测试数据,测试数据能够是YAML格式也能够是Json格式。若是测试函数的metafunc.fixturenames中含有parameters这个fixture函数,就用外部测试数据对它进行参数化。
04
—
参数化套路
有了pytest_generate_tests这个Hook函数后,对测试函数进行参数化须要作三个改动:
在data目录下新加一个YAML或者Json格式文件。文件内容格式参考上面的例子。
指定测试数据文件的路径
@pytest.mark.datafile('data/test_in_theaters.yaml')
给测试数据提供一个叫作
parameters
的fixture
如今,整个项目的目录结构应该是以下所示:
tree.├── Pipfile├── Pipfile.lock├── data│ └── test_in_theaters.yaml├── tests│ └── conftest.py│ └── test_data_driven.py
05
—
总结
本文实现测试脚本和测试数据的分离的核心,仍是实现了Hook函数,在Hook函数中读取测试数据文件,并对测试函数的fixture进行参数化。

本文分享自微信公众号 - 明说软件测试(liuchunmingnet)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。