diff --git a/AUTHORS b/AUTHORS index 40b455ff1..04b87359d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -64,6 +64,7 @@ Matt Williams Michael Aquilina Michael Birtwell Michael Droettboom +Mike Lundy Nicolas Delaby Pieter Mulder Piotr Banaszkiewicz diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cc46f145f..0d6150533 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,13 +7,16 @@ namespace in which your doctests run. Thanks `@milliams`_ for the complete PR (`#1428`_). +* New ``name`` argument to ``pytest.fixture`` mark, which allows a custom name + for a fixture (to solve the funcarg-shadowing-fixture problem). + Thanks `@novas0x2a`_ for the complete PR (`#1444`_). + * New ``approx()`` function for easily comparing floating-point numbers in tests. Thanks `@kalekundert`_ for the complete PR (`#1441`_). * - **Changes** * @@ -23,12 +26,13 @@ * .. _@milliams: https://github.com/milliams +.. _@novas0x2a: https://github.com/novas0x2a .. _@kalekundert: https://github.com/kalekundert .. _#1428: https://github.com/pytest-dev/pytest/pull/1428 +.. _#1444: https://github.com/pytest-dev/pytest/pull/1444 .. _#1441: https://github.com/pytest-dev/pytest/pull/1441 - 2.9.1.dev1 ========== diff --git a/_pytest/python.py b/_pytest/python.py index 812a2e870..2e6c8d87e 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -116,12 +116,13 @@ def safe_getattr(object, name, default): class FixtureFunctionMarker: def __init__(self, scope, params, - autouse=False, yieldctx=False, ids=None): + autouse=False, yieldctx=False, ids=None, name=None): self.scope = scope self.params = params self.autouse = autouse self.yieldctx = yieldctx self.ids = ids + self.name = name def __call__(self, function): if isclass(function): @@ -131,7 +132,7 @@ class FixtureFunctionMarker: return function -def fixture(scope="function", params=None, autouse=False, ids=None): +def fixture(scope="function", params=None, autouse=False, ids=None, name=None): """ (return a) decorator to mark a fixture factory function. This decorator can be used (with or or without parameters) to define @@ -157,14 +158,21 @@ def fixture(scope="function", params=None, autouse=False, ids=None): so that they are part of the test id. If no ids are provided they will be generated automatically from the params. + :arg name: the name of the fixture. This defaults to the name of the + decorated function. If a fixture is used in the same module in + which it is defined, the function name of the fixture will be + shadowed by the function arg that requests the fixture; one way + to resolve this is to name the decorated function + ``fixture_`` and then use + ``@pytest.fixture(name='')``. """ if callable(scope) and params is None and autouse == False: # direct decoration return FixtureFunctionMarker( - "function", params, autouse)(scope) + "function", params, autouse, name=name)(scope) if params is not None and not isinstance(params, (list, tuple)): params = list(params) - return FixtureFunctionMarker(scope, params, autouse, ids=ids) + return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name) def yield_fixture(scope="function", params=None, autouse=False, ids=None): """ (return a) decorator to mark a yield-fixture factory function @@ -2242,6 +2250,8 @@ class FixtureManager: # fixture attribute continue else: + if marker.name: + name = marker.name assert not name.startswith(self._argprefix) fixturedef = FixtureDef(self, nodeid, name, obj, marker.scope, marker.params, diff --git a/testing/python/fixture.py b/testing/python/fixture.py index 506d8426e..eb8f9f34b 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -2691,3 +2691,14 @@ class TestContextManagerFixtureFuncs: *def arg1* """) + def test_custom_name(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.fixture(name='meow') + def arg1(): + return 'mew' + def test_1(meow): + print(meow) + """) + result = testdir.runpytest("-s") + result.stdout.fnmatch_lines("*mew*")