Search code examples
pythonpytestfixturesparametrized-testing

How can I parametrize a pytest fixture with command line arguments?


I need to get arguments from command line and use them for fixture parametrizing (I need to pass them to fixture decorator). pytest_addoption can get arguments from cmd, but I can extract them only inside of some fixture, because I need request fixture for this. The problem is that I need these cmd arguments OUTSIDE of fixtures. I do not want to parametrize tests, I need to parametrize a fixture with some setup and teardown. Is there some way to solve this problem?

Some example. I want to test /add/post Api method. I want to test it with several users - for example, I want to request this api method with user1, then with user2 and after that with user3. So I need to parametrize my fixture with a list of users. AND I WANT TO PASS THIS LIST OF USER INTO MY TESTS VIA CMD. Kinda like this: python -m pytest my_test.py --users="user1 user2 user3"

conftest.py:

import pytest

from some_dir import add_a_new_post_as_some_user, 


@pytest.fixture(params=users) # I NEED TO GET users FROM CMD
def add_post(request):
    current_user = request.param
    response = add_a_new_post_as_some_user(user)
    yield current_user, response.status_code
    delete_this_post(response.json()["some_post_id"])

test.py:

def test_add_post_as_some_user(add_post):
    user, status_code = add_post
    assert status_code == 200, f"Problems with user {user}"

Solution

  • In your conftest.py, get the command line argument with:

    def pytest_addoption(parser):
        parser.addoption(
            "--users", action="store", default=None, help="Users list"
        )
    

    Then use the pytest_generate_tests function to parametrize the fixture:

    def pytest_generate_tests(metafunc):
        if "add_post" in metafunc.fixturenames:
            metafunc.parametrize("add_post", metafunc.config.getoption("--users").split(","))
    
    
    @pytest.fixture()
    def add_post(request):
        current_user = request.param
        response = add_a_new_post_as_some_user(user)
        yield current_user, response.status_code
        delete_this_post(response.json()["some_post_id"])
    
    

    Now, tests using the fixture add_post will be parametrized with the users taken from the command line when running with pytest --users user1,user2, for example.