Make monkeypatch invocation-scoped
This commit is contained in:
parent
4f2bf965cb
commit
05f3422d7c
|
@ -10,7 +10,7 @@ import pytest
|
|||
RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@pytest.fixture(scope='invocation')
|
||||
def monkeypatch(request):
|
||||
"""The returned ``monkeypatch`` fixture provides these
|
||||
helper methods to modify objects, dictionaries or os.environ::
|
||||
|
@ -25,9 +25,11 @@ def monkeypatch(request):
|
|||
monkeypatch.chdir(path)
|
||||
|
||||
All modifications will be undone after the requesting
|
||||
test function has finished. The ``raising``
|
||||
test function or fixture has finished. The ``raising``
|
||||
parameter determines if a KeyError or AttributeError
|
||||
will be raised if the set/deletion operation has no target.
|
||||
|
||||
This fixture is ``invocation``-scoped.
|
||||
"""
|
||||
mpatch = MonkeyPatch()
|
||||
request.addfinalizer(mpatch.undo)
|
||||
|
@ -97,7 +99,8 @@ notset = Notset()
|
|||
|
||||
|
||||
class MonkeyPatch:
|
||||
""" Object keeping a record of setattr/item/env/syspath changes. """
|
||||
""" Object returned by the ``monkeypatch`` fixture keeping a record of setattr/item/env/syspath changes.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._setattr = []
|
||||
|
|
|
@ -9,9 +9,6 @@ Invocation-scoped fixtures
|
|||
This feature is experimental, so if decided that it brings too much problems
|
||||
or considered too complicated it might be removed in pytest ``3.1``.
|
||||
|
||||
``tmpdir`` and ``monkeypatch`` might become ``invocation`` scoped
|
||||
fixtures in the future if decided to keep invocation-scoped fixtures.
|
||||
|
||||
Fixtures can be defined with ``invocation`` scope, meaning that the fixture
|
||||
can be requested by fixtures from any scope, but when they do they assume
|
||||
the same scope as the fixture requesting it.
|
||||
|
|
|
@ -6,7 +6,7 @@ Monkeypatching/mocking modules and environments
|
|||
|
||||
Sometimes tests need to invoke functionality which depends
|
||||
on global settings or which invokes code which cannot be easily
|
||||
tested such as network access. The ``monkeypatch`` function argument
|
||||
tested such as network access. The ``monkeypatch`` fixture
|
||||
helps you to safely set/delete an attribute, dictionary item or
|
||||
environment variable or to modify ``sys.path`` for importing.
|
||||
See the `monkeypatch blog post`_ for some introduction material
|
||||
|
@ -14,6 +14,9 @@ and a discussion of its motivation.
|
|||
|
||||
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||
|
||||
As of pytest-3.0, the ``monkeypatch`` fixture is :ref:`invocation-scoped <invocation_scoped_fixture>`
|
||||
meaning it can be requested from fixtures of any scope.
|
||||
|
||||
Simple example: monkeypatching functions
|
||||
---------------------------------------------------
|
||||
|
||||
|
@ -53,27 +56,31 @@ This autouse fixture will be executed for each test function and it
|
|||
will delete the method ``request.session.Session.request``
|
||||
so that any attempts within tests to create http requests will fail.
|
||||
|
||||
example: setting an attribute on some class
|
||||
------------------------------------------------------
|
||||
example: setting an environment variable for the test session
|
||||
-------------------------------------------------------------
|
||||
|
||||
If you need to patch out ``os.getcwd()`` to return an artificial
|
||||
value::
|
||||
If you would like for an environment variable to be
|
||||
configured for the entire test session, you can add this to your
|
||||
top-level ``conftest.py`` file:
|
||||
|
||||
def test_some_interaction(monkeypatch):
|
||||
monkeypatch.setattr("os.getcwd", lambda: "/")
|
||||
.. code-block:: python
|
||||
|
||||
which is equivalent to the long form::
|
||||
# content of conftest.py
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
def enable_debugging(monkeypatch):
|
||||
monkeypatch.setenv("DEBUGGING_VERBOSITY", "4")
|
||||
|
||||
def test_some_interaction(monkeypatch):
|
||||
import os
|
||||
monkeypatch.setattr(os, "getcwd", lambda: "/")
|
||||
This auto-use fixture will set the ``DEBUGGING_VERBOSITY`` environment variable for
|
||||
the entire test session.
|
||||
|
||||
Note that the ability to use a ``monkeypatch`` fixture from a ``session``-scoped
|
||||
fixture was added in pytest-3.0.
|
||||
|
||||
|
||||
Method reference of the monkeypatch fixture
|
||||
-------------------------------------------
|
||||
|
||||
Method reference of the monkeypatch function argument
|
||||
-----------------------------------------------------
|
||||
|
||||
.. autoclass:: monkeypatch
|
||||
.. autoclass:: MonkeyPatch
|
||||
:members: setattr, replace, delattr, setitem, delitem, setenv, delenv, syspath_prepend, chdir, undo
|
||||
|
||||
``monkeypatch.setattr/delattr/delitem/delenv()`` all
|
||||
|
|
|
@ -329,3 +329,35 @@ def test_issue1338_name_resolving():
|
|||
monkeypatch.delattr('requests.sessions.Session.request')
|
||||
finally:
|
||||
monkeypatch.undo()
|
||||
|
||||
|
||||
def test_invocation_scoped_monkeypatch(testdir):
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def stamp_sys(monkeypatch):
|
||||
monkeypatch.setattr(sys, 'module_stamped', True, raising=False)
|
||||
""")
|
||||
testdir.makepyfile(test_inv_mokeypatch_1="""
|
||||
import sys
|
||||
|
||||
def test_stamp_1(monkeypatch, stamp_sys):
|
||||
assert sys.module_stamped
|
||||
monkeypatch.setattr(sys, 'function_stamped', True, raising=False)
|
||||
assert sys.function_stamped
|
||||
|
||||
def test_stamp_2(monkeypatch):
|
||||
assert sys.module_stamped
|
||||
assert not hasattr(sys, 'function_stamped')
|
||||
""")
|
||||
testdir.makepyfile(test_inv_mokeypatch_2="""
|
||||
import sys
|
||||
|
||||
def test_no_stamps():
|
||||
assert not hasattr(sys, 'module_stamped')
|
||||
assert not hasattr(sys, 'function_stamped')
|
||||
""")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*3 passed*'])
|
||||
|
|
Loading…
Reference in New Issue