How to pass arguments in pytest by command line
Solution 1
In your pytest test, don't use @pytest.mark.parametrize
:
def test_print_name(name):
print ("Displaying name: %s" % name)
In conftest.py
:
def pytest_addoption(parser):
parser.addoption("--name", action="store", default="default name")
def pytest_generate_tests(metafunc):
# This is called for every test. Only get/set command line arguments
# if the argument is specified in the list of test "fixturenames".
option_value = metafunc.config.option.name
if 'name' in metafunc.fixturenames and option_value is not None:
metafunc.parametrize("name", [option_value])
Then you can run from the command line with a command line argument:
pytest -s tests/my_test_module.py --name abc
Solution 2
Use the pytest_addoption
hook function in conftest.py
to define a new option.
Then use pytestconfig
fixture in a fixture of your own to grab the name.
You can also use pytestconfig
from a test to avoid having to write your own fixture, but I think having the option have it's own name is a bit cleaner.
# conftest.py
def pytest_addoption(parser):
parser.addoption("--name", action="store", default="default name")
# test_param.py
import pytest
@pytest.fixture(scope="session")
def name(pytestconfig):
return pytestconfig.getoption("name")
def test_print_name(name):
print(f"\ncommand line param (name): {name}")
def test_print_name_2(pytestconfig):
print(f"test_print_name_2(name): {pytestconfig.getoption('name')}")
# in action
$ pytest -q -s --name Brian test_param.py
test_print_name(name): Brian
.test_print_name_2(name): Brian
.
Solution 3
I stumbled here looking for how to pass an argument, but I wanted to avoid parameterizing the test. The accepted answer does perfectly well address the exact question of parameterizing a test from the command line, but I would like to offer an alternative way to pass a command line argument to particular tests. The method below uses a fixture and skips the test if the fixture is specified but the argument is not:
test.py:
def test_name(name):
assert name == 'almond'
conftest.py:
import pytest
def pytest_addoption(parser):
parser.addoption("--name", action="store")
@pytest.fixture(scope='session')
def name(request):
name_value = request.config.option.name
if name_value is None:
pytest.skip()
return name_value
Examples:
$ py.test tests/test.py
=========================== test session starts ============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/ipetrik/dev/pytest_test, inifile:
collected 1 item
tests/test.py s [100%]
======================== 1 skipped in 0.06 seconds =========================
$ py.test tests/test.py --name notalmond
=========================== test session starts ============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/ipetrik/dev/pytest_test, inifile:
collected 1 item
tests/test.py F [100%]
================================= FAILURES =================================
________________________________ test_name _________________________________
name = 'notalmond'
def test_name(name):
> assert name == 'almond'
E AssertionError: assert 'notalmond' == 'almond'
E - notalmond
E ? ---
E + almond
tests/test.py:5: AssertionError
========================= 1 failed in 0.28 seconds =========================
$ py.test tests/test.py --name almond
=========================== test session starts ============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/ipetrik/dev/pytest_test, inifile:
collected 1 item
tests/test.py . [100%]
========================= 1 passed in 0.03 seconds =========================
Solution 4
All you have to do is use pytest_addoption()
in conftest.py
and finally use request
fixture:
# conftest.py
from pytest import fixture
def pytest_addoption(parser):
parser.addoption(
"--name",
action="store"
)
@fixture()
def name(request):
return request.config.getoption("--name")
And now you can run your test
def my_test(name):
assert name == 'myName'
using:
pytest --name myName
Solution 5
It's a bit of a workaround but it'll get the parameters into the test. Depending on the requirements, it could be enough.
def print_name():
import os
print(os.environ['FILENAME'])
pass
and then run the tests from the command-line:
FILENAME=/home/username/decoded.txt python3 setup.py test --addopts "-svk print_name"
ashish sarkar
Updated on July 08, 2022Comments
-
ashish sarkar almost 2 years
I have a code and I need to pass the arguments like name from terminal. Here is my code and how to pass the arguments. I am getting a "File not found" kind error that I don't understand.
I have tried the command in the terminal:
pytest <filename>.py -almonds
I should get the name printed as "almonds"@pytest.mark.parametrize("name") def print_name(name): print ("Displaying name: %s" % name)
-
pavel_orekhov about 5 yearsWhat is @pytest.mark.unit? Why do you use it? It seems that your code works without it, can I omit it?
-
clay about 5 yearsDon't use it. I removed it from the answer. In the past, it was supported and even recommended in older versions of pytest. In newer versions of pytest, it has been removed and it isn't supported.
-
Roelant almost 5 yearsWhat happens when you use test classes? :)
-
ged over 4 years
python3 -m pytest test.py --name qwe
gives error:pytest.py: error: unrecognized arguments: --name qwe
. I have no py.test, what should I do in this case, could you please clarify? -
ipetrik over 4 years@ged - calling it the way you called it works for me. Please note that you should have two files - conftest.py and test.py. I have edited the answer to make this more clear.
-
dor00012 almost 4 yearsCan you also please point out how to add an argument to the list of test "fixturenames", as you said is needed in your answer.
-
dor00012 almost 4 yearsOne can see an explanation for pytest_generate_tests on pytest documentation
-
tash over 3 yearsDoes anyone know how to add multiple arguments? I am guessing
metafunc.parametrize("name", [option_value])
has to be changed. -
Gulzar over 2 years
ERROR: file or directory not found: abc
-
ryanjdillon over 2 yearsI followed this pattern, and in my case also added a pytest mark
@pytest.mark.model_diagnostics
to delineate those tests that require an input, e.g.pytest -m model_diagnostics --fp-model=./model.h5
. This also requires "registering" of your mark, for example in yourpytest.ini
.