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