In pytest how can I avoid passing fixtures

60 views Asked by At

I have a flask app and I'm trying to improve my pytest tests by using random data with hypothesis. I have a fixture in conftest.py that yields a flask test client:

@pytest.fixture(scope="session", name="client", autouse=True)
def fixture_client() -> FlaskClient:
    """Yield a flask test client."""
    app.testing = True
    app.secret_key = 'some_secret_key'
    # do something else before yielding
    yield app.test_client()
    # do some teardown

Then in my auth_test.py I have a function that I use for multiple tests:

def _test_failed_registration(
        client: FlaskClient,
        flash_message,
        name=ValidUser.name,
        password=ValidUser.password,
        confirm=ValidUser.password,
        email=ValidUser.email
    ):
    """Common logic for testing failed registration."""
    with client:
        client.get("/")
        client.get(url_for("auth.register"))
        data = {
            "csrf_token": g.csrf_token,
            "name": name,
            "password": password,
            "confirm": confirm,
            "email": email}
        response = client.post("/auth/register", data=data)
    assert response.status_code == 200
    assert flash_message in unescape(response.text)
    assert "Registration request sent. Please contact an admin." \
            not in response.text

For example one of the tests checks for a short username:

@settings(max_examples=20)
@given(name=st.text(min_size=1, max_size=USER_MIN_LENGTH - 1))
@example(name="")
def test_failed_registration_short_name(client: FlaskClient, name):
    """test_failed_registration_short_name"""
    if not name:
        flash_message = "Username is required!"
    else:
        flash_message = (f"Username must be between {USER_MIN_LENGTH} and " +
                         f"{USER_MAX_LENGTH} characters!")
    _test_failed_registration(client=client,
                              name=name,
                              flash_message=flash_message)

This is working but the my problem is that I always have to pass the client fixture when calling _test_failed_registration, although I don't need it.

Is there a way to avoid this? Something like:

def _test_failed_registration(
        flash_message,
        name=ValidUser.name,
        password=ValidUser.password,
        confirm=ValidUser.password,
        email=ValidUser.email
    ):
    """Common logic for testing failed registration."""
    client = ?????
    with client:
        # same logic as before
        ...

@settings(max_examples=20)
@given(name=st.text(min_size=1, max_size=USER_MIN_LENGTH - 1))
@example(name="")
def test_failed_registration_short_name(name):
    """test_failed_registration_short_name"""
    # same logic
    ...
    _test_failed_registration(name=name,
                              flash_message=flash_message)

I'm trying to simplify the code so using wrappers and closure seems like overcomplicating things.

I tried using request from pytest, which works, but now I have to pass along the request:

_test_failed_registration(request=request,
                          name=name,
                          flash_message=flash_message)

I tried decorating with @pytest.mark.usefixtures("client") but I don't know how to access the client now:

@pytest.mark.usefixtures("client")
def _test_failed_registration(
        flash_message,
        name=ValidUser.name,
        password=ValidUser.password,
        confirm=ValidUser.password,
        email=ValidUser.email
    ):
    """Common logic for testing failed registration."""
    client = ?????
    with client:
        # same logic as before
        ...
0

There are 0 answers