adnanmuttaleb
adnanmuttaleb

Reputation: 3624

Pytest, How to do test against either fixture's value or None?

I have one test-case with one fixture:

@pytest.fixture
def user(test_client):
    return User.objects.first()


@pytest.mark.parametrize('content', ['nice post',])
def test_post(test_client, user, content):
    reponse = test_client.post(
        '/api/v1.0/posts', 
        json={
            'content': content,
            'author': user,
        },
        follow_redirects=True
    )

    assert reponse.status_code == 200

But I want in addition to testing against some User object, to test against None (I expect test to fail for None). I thought I could do something like:

@pytest.fixture(params=[True, False])
def User_or_null(test_client, request):
    if request.param:
        return User.objects.first()
    else:
        return None

But I do not think this will allow me to mark the test case with pytest.mark.xfail for None value? Any Ideas?

Upvotes: 2

Views: 1988

Answers (1)

hoefling
hoefling

Reputation: 66541

I don't see a problem with parametrizing the user fixture. You can mark separate parameters via pytest.param, for example:

@pytest.fixture(params=[
    'testuser',
    # wrap None into pytest.param to treat it specially
    pytest.param(None, marks=pytest.mark.xfail)
])
def user(request):
    if request.param is None:
        return None
    return User.objects.filter(name=request.param).first()  # or whatever

However, this would mean that all tests using the user fixture will xfail/xpass on None - this may be not something you want for all tests. Use indirect parametrization if you want to xfail only selected test:

# user fixture is not parametrized now

@pytest.fixture
def user(request):
    if request.param is None:
        return None
    return User.objects.filter(name=request.param).first()

# instead, parametrizing is done from the test:

@pytest.mark.parametrize('content', ['nice post',])
@pytest.mark.parametrize('user', [
    'testuser',
    pytest.param(None, marks=pytest.mark.xfail
)], indirect=True)
def test_post(test_client, user, content):
    ...

Upvotes: 3

Related Questions