Skip to content

Commit

Permalink
Adapted documentation
Browse files Browse the repository at this point in the history
- mentioned limitations for importing modules
- added some Patcher argument description
  • Loading branch information
mrbean-bremen committed Jan 25, 2018
1 parent 058a912 commit 82176dc
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 46 deletions.
29 changes: 25 additions & 4 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,43 @@ Introduction
Using pyfakefs, your tests operate on a fake file system in memory without touching the real disk.
The software under test requires no modification to work with pyfakefs.

Note that pyfakefs will not work with Python libraries that use C libraries to access the
file system, because it cannot patch the underlying C libraries' file access functions.

pyfakefs works with CPython 2.7, 3.3 and above, on Linux, Windows and OSX (MacOS), and with PyPy2 and PyPy3.

pyfakefs works with `PyTest <doc.pytest.org>`__ version 2.8.6 or above.

Installation
------------
pyfakefs is available on `PyPi <https://pypi.python.org/pypi/pyfakefs/>`__.
It can be installed using pip:
The latest released version can be installed form pypi:

.. code:: bash
pip install pyfakefs
The latest master can be installed form the GitHub sources:

.. code:: bash
pip install git+https://github.com/jmcgeheeiv/pyfakefs
Limitations
-----------
pyfakefs will not work with Python libraries that use C libraries to access the
file system, because it cannot patch the underlying C libraries' file access functions.

pyfakefs works out of the box only if the faked file system modules are loaded directly,
e.g. `import pathlib` works, but `from pathlib import Path` does not. See
`Additional parameters to Patcher and TestCase` in the `Usage` chapter for a way to
work around this.

pyfakefs is only tested with CPython and newest PyPy versions, other Python implementations
will probably not work.

Differences in the behavior in different Linux distributions or different MacOS or Windows versions
may not be reflected in the implementation, as well as some OS-specific low-level file
system behavior. The systems used for automatic tests in Travis.CI and AppVeyor are considered
as reference systems.

History
-------
pyfakefs.py was initially developed at Google by Mike Bland as a modest
Expand Down
2 changes: 1 addition & 1 deletion docs/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Unittest module classes
-----------------------

.. autoclass:: pyfakefs.fake_filesystem_unittest.TestCase
:members: fs, patches, setUpPyfakefs
:members: fs, setUpPyfakefs

.. autoclass:: pyfakefs.fake_filesystem_unittest.Patcher
:members: setUp, tearDown
Expand Down
65 changes: 30 additions & 35 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ There are several approaches to implementing tests using pyfakefs.

Automatically find and patch using fake_filesystem_unittest
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The first approach is to allow pyfakefs to automatically find all real file functions and modules,
If you are using the ``python unittest`` package, the easiest approach is to use test classes
derived from ``fake_filesystem_unittest.TestCase``.

This allows pyfakefs to automatically find all real file functions and modules,
and stub these out with the fake file system functions and modules.
This is the simplest approach if you are using separate unit tests.

The usage is explained in the pyfakefs wiki page
`Automatically find and patch file functions and modules <https://github.com/jmcgeheeiv/pyfakefs/wiki/Automatically-find-and-patch-file-functions-and-modules>`__
and demonstrated in files ``example.py`` and ``example_test.py``.

Patch using the PyTest plugin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you use `PyTest <https://doc.pytest.org>`__, you will be interested in the PyTest plugin in pyfakefs.
This automatically patches all file system functions and modules in a manner similar to the
`automatic find and patch approach <https://github.com/jmcgeheeiv/pyfakefs/wiki/Automatically-find-and-patch-file-functions-and-modules>`__
described above.
This automatically patches all file system functions and modules in a similar manner as desribed above.

The PyTest plugin provides the ``fs`` fixture for use in your test. For example:

Expand Down Expand Up @@ -59,42 +60,36 @@ You can also initialize ``Patcher`` manually:
patcher.tearDown() # somewhere in the cleanup code
Patch using unittest.mock (deprecated)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also use ``mock.patch()`` to patch the modules manually. This approach will
only work for the directly imported modules, therefore it is not suited for testing
larger code bases. As the other approaches are more convenient, this one is considered
deprecated.
You have to create a fake filesystem object, and afterwards fake modules based on this file system
for the modules you want to patch.
Additional parameters to Patcher and TestCase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Both ``fake_filesystem_unittest.Patcher`` and ``fake_filesystem_unittest.TestCase``
provide a few additional arguments for fine-tuning.

The following modules and functions can be patched:

* ``os`` and ``os.path`` by ``fake_filesystem.FakeOsModule``
* ``io`` by ``fake_filesystem.FakeIoModule``
* ``pathlib`` by ``fake_pathlib.FakePathlibModule``
* build-in ``open()`` by ``fake_filesystem.FakeFileOpen``
The most helpful maybe ``modules_to_reload``. This allows to pass a list of modules
that shall be reloaded, thus allowing to patch modules not imported directly.
If a module imports modules to be patched like this:

.. code:: python
import pyfakefs.fake_filesystem as fake_fs
import os as _os
from pathlib import Path
# Create a faked file system
fs = fake_fs.FakeFilesystem()
the modules ``os`` and ``pathlib.Path`` will not be patched (the only exception is
importing ``os.path`` like ``from os import path``, see also below). If adding the module
containing these imports to ``modules_to_reload``, they will be correctly patched.

# Do some setup on the faked file system
fs.create_file('/foo/bar', contents='test')
``additional_skip_names`` may be used to add modules that shall not be patched. This
is mostly used to avoid patching the Python file system modules themselves, but may be
helpful in some special situations.

# Replace some built-in file system related modules you use with faked ones
``patch_path`` is True by default, meaning that modules named `path` are patched as
``os.path``. If this clashes with another module of the same name, it can be switched
off (and imports like ``from os import path`` will not be patched).

# Assuming you are using the mock library to ... mock things
try:
from unittest.mock import patch # In Python 3, mock is built-in
except ImportError:
from mock import patch # Python 2

# Note that this fake module is based on the fake fs you just created
os = fake_fs.FakeOsModule(fs)
with patch('mymodule.os', os):
fd = os.open('/foo/bar', os.O_RDONLY)
contents = os.read(fd, 4)
Patch using unittest.mock (deprecated)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also use ``mock.patch()`` to patch the modules manually. This approach will
only work for the directly imported modules, therefore it is not suited for testing
larger code bases. As the other approaches are more convenient, this one is considered
deprecated and will not be described in detail.
17 changes: 11 additions & 6 deletions pyfakefs/fake_filesystem_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,13 @@ def __init__(self, methodName='runTest', additional_skip_names=None,
Irrespective of patch_path, module 'os.path' is still correctly faked
if imported the usual way using `import os` or `import os.path`.
modules_to_reload (experimental): A list of modules that need to be reloaded
modules_to_reload: A list of modules that need to be reloaded
to be patched dynamically; may be needed if the module
imports file system modules under an alias
Note: this is done independently of `use_dynamic_patch`
Caution: this may not work with some Python versions
or have unwanted side effects.
use_dynamic_patch: If `True`, dynamic patching
after setup is used (for example for modules loaded locally
inside of functions).
Caution: reloading modules may have unwanted side effects.
use_dynamic_patch: If `True`, dynamic patching after setup is used
(for example for modules loaded locally inside of functions).
Can be switched off if it causes unwanted side effects.
If you specify arguments `additional_skip_names` or `patch_path` here
Expand All @@ -150,6 +148,13 @@ class MyTestCase(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='runTest'):
super(MyTestCase, self).__init__(
methodName=methodName, additional_skip_names=['posixpath'])
import sut
class AnotherTestCase(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='runTest'):
super(MyTestCase, self).__init__(
methodName=methodName, modules_to_reload=[sut])
"""
super(TestCase, self).__init__(methodName)
self._stubber = Patcher(additional_skip_names=additional_skip_names,
Expand Down

0 comments on commit 82176dc

Please sign in to comment.