I am writing a PyTest plugin in which I implemented different custom markers using this function:
def pytest_configure(config):
config.addinivalue_line("markers", "title(a_title): a title to present the test case")
These markers are then used to add custom properties for each test case in the jUnit output.
Now, since I find myself using very often the parametrize
marker, I would like to fill part of my marker with the value of an argument defined in the parametrize marker.
Here is an example of what I am trying to accomplish. The code is the following:
class TestClass:
@pytest.mark.parametrize("param", ["value1", "value2"])
@pytest.mark.title(f"This test case checks that param is {param}")
def test_simple_test_case(self, param):
pass
I would like the XML output to be filled like this:
<testcase classname="test_example.TestClass" name="test_simple_test_case[value1]" time="0.001">
<properties>
<property name="title" value="This test case checks that param is value1"/>
</properties>
</testcase>
<testcase classname="test_example.TestClass" name="test_simple_test_case[value2]" time="0.001">
<properties>
<property name="title" value="This test case checks that param is value2"/>
</properties>
</testcase>
<testcase classname="test_example.TestClass" name="test_simple_test_case[value3]" time="0.001">
<properties>
<property name="title" value="This test case checks that param is value3"/>
</properties>
</testcase>
Everything is working except passing the parametrize
argument to my custom marker (title
).
You can access parametrize
parameters in item.callspec.params
.
def pytest_collection_modifyitems(session, config, items):
for item in items:
for marker in item.iter_markers(name="title"):
# title = marker.args[0] # Change this
title = marker.args[0].format(**item.callspec.params) # to this
item.user_properties.append(("title", title))
Usage:
class TestClass:
@pytest.mark.parametrize("param", ["value1", "value2"])
# @pytest.mark.title(f"This test case checks that param is {param}") # Change this
@pytest.mark.title("This test case checks that param is {param}") # to this
def test_simple_test_case(self, param):
pass
To handle the case where parametrize
is not used, or some format strings are not specified:
class SafeDict(dict):
def __missing__(self, key):
return "{" + key + "}"
def pytest_collection_modifyitems(session, config, items):
for item in items:
for marker in item.iter_markers(name="title"):
title = marker.args[0]
if hasattr(item, "callspec"):
title = title.format_map(SafeDict(item.callspec.params))
item.user_properties.append(("title", title))
Reference: https://stackoverflow.com/questions/17215400/format-string-unused-named-arguments/17215533#17215533
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With