python - 根据命令行参数运行 pytest 标记
问题描述
我有一个 python 文件,它从配置文件中读取并初始化某些变量,然后是一些由 pytest 标记定义的测试用例。
我通过调用这些标记并行运行不同的测试用例集,如下所示 -pytest -m "markername" -n 3
现在的问题是,我没有一个配置文件了。有多个配置文件,我需要在执行期间从命令行获取用于测试用例的配置文件的方法。
我试过什么?
我将配置文件的读取包装到一个带有 conf 参数的函数中。
我添加了一个文件,使用 pytest addoptionconftest.py
添加了一个命令行选项。conf
def pytest_addoption(parser):
parser.addoption("--conf", action="append", default=[],
help="Name of the configuration file to pass to test functions")
def pytest_generate_tests(metafunc):
if 'conf' in metafunc.fixturenames:
metafunc.parametrize("conf", metafunc.config.option.conf)
然后尝试了这个pytest -q --conf="configABC" -m "markername"
,希望我可以读取该配置文件以初始化某些参数并将其传递给包含给定标记的测试用例。但是什么都没有发生,我想知道...我想知道如何...我想知道为什么...
如果我运行pytest -q --conf="configABC"
,则读取配置文件,但所有测试用例都在运行。
但是,我只需要运行使用通过我从命令行获得的配置文件初始化的变量的特定测试用例。我想使用标记,因为我也在使用参数化并并行运行它们。如何从命令行获取要使用的配置文件?我把这搞砸了吗?
编辑1:
#contents of testcases.py
import json
import pytest
...
...
...
def getconfig(conf):
config = open(str(conf)+'_Configuration.json', 'r')
data = config.read()
data_obj = json.loads(data)
globals()['ID'] = data_obj['Id']
globals()['Codes'] = data_obj['Codes'] # list [Code_1, Code_2, Code_3]
globals()['Uname'] = data_obj['IM_User']
globals()['Pwd'] = data_obj['IM_Password']
#return ID, Codes, User, Pwd
def test_parms():
#Returns a list of tuples [(ID, Code_1, Uname, Pwd), (ID, Code_2, Uname, Pwd), (ID, Code_3, Uname, Pwd)]
...
...
return l
@pytest.mark.testA
@pytest.mark.parametrize("ID, Code, Uname, Pwd", test_parms())
def testA(ID, Code, Uname, Pwd):
....
do something
....
@pytest.mark.testB
@pytest.mark.parametrize("ID, Code, Uname, Pwd", test_parms())
def testB(ID, Code, Uname, Pwd):
....
do something else
....
解决方案
您似乎走在正确的轨道上,但错过了一些联系和细节。
首先,您的选项看起来有点奇怪 - 据我了解,您只需要一个字符串而不是列表:
conftest.py
def pytest_addoption(parser):
parser.addoption("--conf", action="store",
help="Name of the configuration file"
" to pass to test functions")
在您的测试代码中,您读取配置文件,并根据您的代码,它包含参数列表的 json 字典,例如:
{
"Id": [1, 2, 3],
"Codes": ["a", "b", "c"],
"IM_User": ["User1", "User2", "User3"],
"IM_Password": ["Pwd1", "Pwd2", "Pwd3"]
}
参数化需要的是参数元组列表,并且您还希望只读取一次列表。这是一个示例实现,它在首次访问时读取列表并将其存储在字典中(假设您的配置文件如上所示):
import json
configs = {}
def getconfig(conf):
if conf not in configs:
# read the configuration if not read yet
with open(conf + '_Configuration.json') as f:
data_obj = json.load(f)
ids = data_obj['Id']
codes = data_obj['Codes']
users = data_obj['IM_User']
passwords = data_obj['IM_Password']
# assume that all lists have the same length
config = list(zip(ids, codes, users, passwords))
configs[conf] = config
return configs[conf]
现在您可以使用这些参数来参数化您的测试:
def pytest_generate_tests(metafunc):
conf = metafunc.config.getoption("--conf")
# only parametrize tests with the correct parameters
if conf and metafunc.fixturenames == ["uid", "code", "name", "pwd"]:
metafunc.parametrize("uid, code, name, pwd", getconfig(conf))
@pytest.mark.testA
def test_a(uid, code, name, pwd):
print(uid, code, name, pwd)
@pytest.mark.testB
def test_b(uid, code, name, pwd):
print(uid, code, name, pwd)
def test_c():
pass
在此示例中,两者test_a
和test_b
都将被参数化,但不是test_c
。
如果您现在运行测试(使用 json 文件名“ConfigA_Configuration.json”),您会得到如下内容:
$ python -m pytest -v --conf=ConfigA -m testB testcases.py
============================================ 6 passed, 2 warnings in 0.11s ============================================
(Py37_new) c:\dev\so\questions\so\params_from_config>python -m pytest -v --conf=ConfigA -m testB test_params_from_config.py
...
collected 7 items / 4 deselected / 3 selected
test_params_from_config.py::test_b[1-a-User1-Pwd1] PASSED
test_params_from_config.py::test_b[2-b-User2-Pwd2] PASSED
test_params_from_config.py::test_b[3-c-User3-Pwd3] PASSED
推荐阅读
- linux - 如何在 Linux 中为另一个用户授予文件夹权限
- web-scraping - 尽管我传递给它的 URL 不同,但 Python 中的 requests 模块给了我相同的页面
- android - Firebase 作业服务的启动延迟很大
- openthread - 开发 OpenWeave 设备以直接与 Nest 产品集成
- angular - 如果相关表单组无效,Angular 7 和表单数组会禁用表单组的按钮,并给出未定义的错误
- javascript - 在 HTML 和 Javascript 页面中对 IP 摄像机进行身份验证
- cassandra - cassandra 数据中心能否仅配置为复制接收器?
- javascript - 如何在特定时间无交互后显示弹出窗口
- python - 在python中按值对字典进行排序
- python - 随机产生重复元素