diff options
Diffstat (limited to 'testing/web-platform/tests/tools/pytest/doc/en/monkeypatch.rst')
-rw-r--r-- | testing/web-platform/tests/tools/pytest/doc/en/monkeypatch.rst | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/testing/web-platform/tests/tools/pytest/doc/en/monkeypatch.rst b/testing/web-platform/tests/tools/pytest/doc/en/monkeypatch.rst new file mode 100644 index 000000000..4155a3a34 --- /dev/null +++ b/testing/web-platform/tests/tools/pytest/doc/en/monkeypatch.rst @@ -0,0 +1,82 @@ + +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`` function argument +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/ + +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 attribute on some class +------------------------------------------------------ + +If you need to patch out ``os.getcwd()`` to return an artificial +value:: + + def test_some_interaction(monkeypatch): + monkeypatch.setattr("os.getcwd", lambda: "/") + +which is equivalent to the long form:: + + def test_some_interaction(monkeypatch): + import os + monkeypatch.setattr(os, "getcwd", lambda: "/") + + + +Method reference of the monkeypatch function argument +----------------------------------------------------- + +.. 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. + |