1.. _auto_patch:
2
3Automatically find and patch file functions and modules
4=======================================================
5The ``fake_filesystem_unittest`` module automatically finds all real file
6functions and modules, and stubs them out with the fake file system functions and modules.
7The pyfakefs source code contains files that demonstrate this usage model:
8
9- ``example.py`` is the software under test. In production, it uses the
10  real file system.
11- ``example_test.py`` tests ``example.py``. During testing, the pyfakefs fake
12  file system is used by ``example_test.py`` and ``example.py`` alike.
13
14.. note:: This example uses the Python ``unittest`` module for testing, but the
15  functionality is similar if using the ``fs`` fixture in ``pytest``,
16  the ``patchfs`` decorator, or the ``Patcher`` class.
17
18
19Software Under Test
20-------------------
21``example.py`` contains a few functions that manipulate files.  For instance:
22
23.. code:: python
24
25    def create_file(path):
26        """Create the specified file and add some content to it.  Use the open()
27        built in function.
28
29        For example, the following file operations occur in the fake file system.
30        In the real file system, we would not even have permission to write /test:
31
32        >>> os.path.isdir('/test')
33        False
34        >>> os.mkdir('/test')
35        >>> os.path.isdir('/test')
36        True
37        >>> os.path.exists('/test/file.txt')
38        False
39        >>> create_file('/test/file.txt')
40        >>> os.path.exists('/test/file.txt')
41        True
42        >>> with open('/test/file.txt') as f:
43        ...     f.readlines()
44        ["This is test file '/test/file.txt'.\\n", 'It was created using the open() function.\\n']
45        """
46        with open(path, "w") as f:
47            f.write("This is test file '{}'.\n".format(path))
48            f.write("It was created using the open() function.\n")
49
50No functional code in ``example.py`` even hints at a fake file system. In
51production, ``create_file()`` invokes the real file functions ``open()`` and
52``write()``.
53
54Unit Tests and Doctests
55-----------------------
56``example_test.py`` contains unit tests for ``example.py``. ``example.py``
57contains the doctests, as you can see above.
58
59The module ``fake_filesystem_unittest`` contains code that finds all real file
60functions and modules, and stubs these out with the fake file system functions
61and modules:
62
63.. code:: python
64
65    import os
66    import unittest
67    from pyfakefs import fake_filesystem_unittest
68
69    # The module under test is example:
70    import example
71
72Doctests
73~~~~~~~~
74``example_test.py`` defines ``load_tests()``, which runs the doctests in
75``example.py``:
76
77.. code:: python
78
79    def load_tests(loader, tests, ignore):
80        """Load the pyfakefs/example.py doctest tests into unittest."""
81        return fake_filesystem_unittest.load_doctests(loader, tests, ignore, example)
82
83
84Everything, including all imported modules and the test, is stubbed out
85with the fake filesystem. Thus you can use familiar file functions like
86``os.mkdir()`` as part of your test fixture and they too will operate on the
87fake file system.
88
89Unit Test Class
90~~~~~~~~~~~~~~~
91Next comes the ``unittest`` test class.  This class is derived from
92``fake_filesystem_unittest.TestCase``, which is in turn derived from
93``unittest.TestClass``:
94
95.. code:: python
96
97    class TestExample(fake_filesystem_unittest.TestCase):
98        def setUp(self):
99            self.setUpPyfakefs()
100
101        def tearDown(self):
102            # It is no longer necessary to add self.tearDownPyfakefs()
103            pass
104
105        def test_create_file(self):
106            """Test example.create_file()"""
107            # The os module has been replaced with the fake os module so all of the
108            # following occurs in the fake filesystem.
109            self.assertFalse(os.path.isdir("/test"))
110            os.mkdir("/test")
111            self.assertTrue(os.path.isdir("/test"))
112
113            self.assertFalse(os.path.exists("/test/file.txt"))
114            example.create_file("/test/file.txt")
115            self.assertTrue(os.path.exists("/test/file.txt"))
116
117        ...
118
119
120Just add ``self.setUpPyfakefs()`` in ``setUp()``. You need add nothing to
121``tearDown()``.  Write your tests as usual.  From ``self.setUpPyfakefs()`` to
122the end of your ``tearDown()`` method, all file operations will use the fake
123file system.
124