根据命令行参数运行 pytest 标记 [英] Run pytest markers based on command line argument
问题描述
我有一个 python 文件,它从配置文件中读取并初始化某些变量,然后是一些由 pytest 标记定义的测试用例.
I have a python file that reads from a configuration file and initializes certain variables, followed by a number of test cases, defined by pytest markers.
我通过调用这些标记并行运行不同的测试用例集,就像这样 - pytest -m "markername";-n 3
I run different set of test cases parallelly by calling these markers, like this - pytest -m "markername" -n 3
现在的问题是,我没有一个配置文件了.有多个配置文件,我需要一种方法在执行过程中从命令行获取用于测试用例的配置文件.
The problem now is, I don't have a single configuration file anymore. There are multiple configuration files and I need a way to get from command line during execution, which configuration file to use for the test cases.
我尝试了什么?
我将配置文件的读取包装到一个带有 conf 参数的函数中.
I wrapped the reading of config file into a function with a conf argument.
我添加了一个 conftest.py
文件,使用 pytest addoption 添加了一个命令行选项 conf
.
I added a conftest.py
file, added a command-line option conf
using pytest addoption.
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"
,希望我可以读取该配置文件以初始化某些参数并将其传递给包含给定标记的测试用例.但是什么也没有发生,我想知道...我想知道如何...我想知道为什么...
and then tried this pytest -q --conf="configABC" -m "markername"
, in the hope that I can read that configuration file to initialize certain parameters and pass it on to the test cases containing the given marker. But nothing ever happens, and I wonder... I wonder how... I wonder why..
如果我运行 pytest -q --conf=configABC"
,配置文件被读取,但所有测试用例都在运行.
If I run pytest -q --conf="configABC"
, the config file gets read, but all the test cases are running.
但是,我只需要运行使用通过从命令行获取的配置文件初始化的变量的特定测试用例.我想使用标记,因为我也在使用参数化并并行运行它们.如何从命令行获取要使用的配置文件?我搞砸了吗?
However, I only need to run specific test cases that use variables initialized through the config file I get from command line. And I want to use markers because I'm also using parameterization and running them in parallel. How will I get which configuration file to use, from the command line? Am I messing this up?
编辑 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
....
推荐答案
您似乎走在正确的轨道上,但遗漏了一些联系和细节.
You seem to be on the right track, but miss some connections and details.
首先,你的选项看起来有点奇怪——据我所知,你只需要一个字符串而不是一个列表:
First, your option looks a bit strange - as far as I understand, you just need a string instead of a list:
conftest.py
def pytest_addoption(parser):
parser.addoption("--conf", action="store",
help="Name of the configuration file"
" to pass to test functions")
在您的测试代码中,您阅读了配置文件,并且根据您的代码,它包含一个参数列表的 json 字典,例如类似:
In your test code, you read the config file, and based on your code, it contains a json dictionary of parameter lists, e.g. something like:
{
"Id": [1, 2, 3],
"Codes": ["a", "b", "c"],
"IM_User": ["User1", "User2", "User3"],
"IM_Password": ["Pwd1", "Pwd2", "Pwd3"]
}
参数化需要的是一个参数元组列表,并且您也只想读取该列表一次.这是一个示例实现,它在第一次访问时读取列表并将其存储在字典中(前提是您的配置文件如上所示):
What you need for parametrization is a list of parameter tuples, and you also want to read the list only once. Here is an example implementation that reads the list on first access and stores it in a dictionary (provided your config file looks like shown above):
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]
现在您可以使用这些参数来参数化您的测试:
Now you can use these parameters to parametrize your tests:
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
不会.
In this example, both test_a
and test_b
will be parametrized, but not test_c
.
如果您现在运行测试(使用 json 文件名ConfigA_Configuration.json"),您会得到如下内容:
If you now run the test (with the json file name "ConfigA_Configuration.json"), you get something like:
$ 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
这篇关于根据命令行参数运行 pytest 标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!