90 lines
3.3 KiB
ReStructuredText
90 lines
3.3 KiB
ReStructuredText
|
|
Monkeypatching/mocking modules and environments
|
|
================================================================
|
|
|
|
.. currentmodule:: _pytest.monkeypatch
|
|
|
|
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`` 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
|
|
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
|
|
---------------------------------------------------
|
|
|
|
If you want to pretend that ``os.expanduser`` returns a certain
|
|
directory, you can use the :py:meth:`monkeypatch.setattr` method to
|
|
patch this function before calling into a function which uses it::
|
|
|
|
# content of test_module.py
|
|
import os.path
|
|
def getssh(): # pseudo application code
|
|
return os.path.join(os.path.expanduser("~admin"), '.ssh')
|
|
|
|
def test_mytest(monkeypatch):
|
|
def mockreturn(path):
|
|
return '/abc'
|
|
monkeypatch.setattr(os.path, 'expanduser', mockreturn)
|
|
x = getssh()
|
|
assert x == '/abc/.ssh'
|
|
|
|
Here our test function monkeypatches ``os.path.expanduser`` and
|
|
then calls into an function that calls it. After the test function
|
|
finishes the ``os.path.expanduser`` modification will be undone.
|
|
|
|
example: preventing "requests" from remote operations
|
|
------------------------------------------------------
|
|
|
|
If you want to prevent the "requests" library from performing http
|
|
requests in all your tests, you can do::
|
|
|
|
# content of conftest.py
|
|
import pytest
|
|
@pytest.fixture(autouse=True)
|
|
def no_requests(monkeypatch):
|
|
monkeypatch.delattr("requests.sessions.Session.request")
|
|
|
|
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 environment variable for the test session
|
|
-------------------------------------------------------------
|
|
|
|
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:
|
|
|
|
.. code-block:: python
|
|
|
|
# content of conftest.py
|
|
@pytest.fixture(scope='session', autouse=True)
|
|
def enable_debugging(monkeypatch):
|
|
monkeypatch.setenv("DEBUGGING_VERBOSITY", "4")
|
|
|
|
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
|
|
-------------------------------------------
|
|
|
|
.. autoclass:: MonkeyPatch
|
|
:members: setattr, replace, delattr, setitem, delitem, setenv, delenv, syspath_prepend, chdir, undo
|
|
|
|
``monkeypatch.setattr/delattr/delitem/delenv()`` all
|
|
by default raise an Exception if the target does not exist.
|
|
Pass ``raising=False`` if you want to skip this check.
|
|
|