Search code examples
pythonpytest

Passing multiple command line arguments to a pytest fixture as parameters


I'd like to pass multiple arguments to a single pytest fixture, for example:

pytest test_sample.py --arg1 "Hello" --arg2 "World" 

And I have a fixture which expects 2 arguments. Below is a failed attempt of trying to do that.

# test_string.py
import pytest

@pytest.fixture()
def stringinput():  # How to pass both --arg1 and --arg2 to it?
    print("arg1 is: ", arg1)
    print("arg2 is: ", arg2)


def test_valid_string(stringinput):
    pass
# conftest.py
import pytest

def pytest_addoption(parser):
    parser.addoption(
        "--arg1",
        action="append",
        default=[],
        help="list of stringinputs to pass to test functions",
    )
    parser.addoption(
        "--arg2",
        action="append",
        default=[],
        help="list of stringinputs to pass to test functions",
    )


def pytest_generate_tests(metafunc):
    if "stringinput" in metafunc.fixturenames:
        metafunc.parametrize("stringinput", metafunc.config.getoption("arg1"))
        metafunc.parametrize("stringinput", metafunc.config.getoption("arg2"))  # This doesn't work. How to add multiple options?

This post solves the problem of passing a single argument to a fixture, But how to pass both --arg1 and --arg2 to a fixture?


Solution

  • If I understand your question correctly, you don't need parametrized tests at all. If you just want to handle command line arguments in a fixture, you can access your arguments inside the fixture via the standard request fixture:

    import pytest
    
    
    @pytest.fixture
    def stringinput(request):
        arg1 = request.config.option.arg1 if "arg1" in request.config.option else ""
        arg2 = request.config.option.arg2 if "arg2" in request.config.option else ""
        yield f"{arg1}-{arg2}"
    
    
    def test_valid_string(stringinput):
        print(f"{stringinput=}")
    

    So if running your test with --arg1=foo --arg2=bar, the output would be stringinput=foo-bar.

    You still want to register your options with pytest_addoption as you do, but you don't need to implement pytest_generate_tests.