Cyker
Cyker

Reputation: 10984

pytest: fixtures as function arguments

As its document says, pytest accepts fixtures as function arguments. However, this somewhat contradicts the convention in almost all languages that parameter names shouldn't affect a function's behavior. For example:

This works:

import pytest

@pytest.fixture()
def name():
    return 'foo'

def test_me(name):
    assert name == 'foo'

But this doesn't:

import pytest

@pytest.fixture()
def name():
    return 'foo'

def test_me(nam):
    assert nam == 'foo'

I think there must be some introspection here which requires testing function parameters to be valid fixtures. Am I correct on this?


Besides fixtures, there are other magic parameter names that confused me. One of them is request:

import pytest

@pytest.fixture(params=['foo', 'bar'])
def name(request):
    return request.param

def test_me(name):
    assert name == 'foo'

Without reading its doc, it might seem you can rename request to another name such as req:

import pytest

@pytest.fixture(params=['foo', 'bar'])
def name(req):
    return req.param

def test_me(name):
    assert name == 'foo'

But then running the test will complain fixture req not found. It further confused me because the listed available fixtures didn't include request. I'm not sure it's proper to call request a fixture here, but the error message is contradicting itself:

E fixture 'req' not found

> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, name, pytestconfig, record_xml_attribute, record_xml_property, recwarn, tmpdir, tmpdir_factory, worker_id

> use 'pytest --fixtures [testpath]' for help on them.

So how many magic names like this I must take care of when using pytest to not get into a pitfall?

Upvotes: 4

Views: 3703

Answers (1)

AKX
AKX

Reputation: 169338

Yup, Py.test injects a little bit of argument-name introspection magic to keep your test cases concise.

Aside from any fixtures you have available (as you found out with pytest --fixtures), I do think request is the only additional magic parameter (unless, of course, you use, say, @pytest.mark.parametrize('foo', (...)), in which case foo is a magic parameter for that marked test case or fixture, etc.).

As an aside, I think it's best not to think about Py.test test_ functions as regular old functions anyway, as they're not directly called as such by Py.test.

Upvotes: 5

Related Questions