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.
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.
What I tried?
I wrapped the reading of config file into a function with a conf argument.
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)
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..
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?
Edit 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
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:
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):
Now you can use these parameters to parametrize your tests:
In this example, both
test_a
andtest_b
will be parametrized, but nottest_c
.If you now run the test (with the json file name "ConfigA_Configuration.json"), you get something like: