Automatically find and patch file functions and modules

The fake_filesystem_unittest module automatically finds all real file functions and modules, and stubs them out with the fake file system functions and modules. The pyfakefs source code contains files that demonstrate this usage model:

  • example.py is the software under test. In production, it uses the real file system.

  • example_test.py tests example.py. During testing, the pyfakefs fake file system is used by example_test.py and example.py alike.

Note

This example uses the Python unittest module for testing, but the functionality is similar if using the fs fixture in pytest, the patchfs decorator, or the Patcher class.

Software Under Test

example.py contains a few functions that manipulate files. For instance:

def create_file(path):
    """Create the specified file and add some content to it.  Use the open()
    built in function.

    For example, the following file operations occur in the fake file system.
    In the real file system, we would not even have permission to write /test:

    >>> os.path.isdir('/test')
    False
    >>> os.mkdir('/test')
    >>> os.path.isdir('/test')
    True
    >>> os.path.exists('/test/file.txt')
    False
    >>> create_file('/test/file.txt')
    >>> os.path.exists('/test/file.txt')
    True
    >>> with open('/test/file.txt') as f:
    ...     f.readlines()
    ["This is test file '/test/file.txt'.\\n", 'It was created using the open() function.\\n']
    """
    with open(path, "w") as f:
        f.write("This is test file '{}'.\n".format(path))
        f.write("It was created using the open() function.\n")

No functional code in example.py even hints at a fake file system. In production, create_file() invokes the real file functions open() and write().

Unit Tests and Doctests

example_test.py contains unit tests for example.py. example.py contains the doctests, as you can see above.

The module fake_filesystem_unittest contains code that finds all real file functions and modules, and stubs these out with the fake file system functions and modules:

import os
import unittest
from pyfakefs import fake_filesystem_unittest

# The module under test is example:
import example

Doctests

example_test.py defines load_tests(), which runs the doctests in example.py:

def load_tests(loader, tests, ignore):
    """Load the pyfakefs/example.py doctest tests into unittest."""
    return fake_filesystem_unittest.load_doctests(loader, tests, ignore, example)

Everything, including all imported modules and the test, is stubbed out with the fake filesystem. Thus you can use familiar file functions like os.mkdir() as part of your test fixture and they too will operate on the fake file system.

Unit Test Class

Next comes the unittest test class. This class is derived from fake_filesystem_unittest.TestCase, which is in turn derived from unittest.TestClass:

class TestExample(fake_filesystem_unittest.TestCase):
    def setUp(self):
        self.setUpPyfakefs()

    def tearDown(self):
        # It is no longer necessary to add self.tearDownPyfakefs()
        pass

    def test_create_file(self):
        """Test example.create_file()"""
        # The os module has been replaced with the fake os module so all of the
        # following occurs in the fake filesystem.
        self.assertFalse(os.path.isdir("/test"))
        os.mkdir("/test")
        self.assertTrue(os.path.isdir("/test"))

        self.assertFalse(os.path.exists("/test/file.txt"))
        example.create_file("/test/file.txt")
        self.assertTrue(os.path.exists("/test/file.txt"))

    ...

Just add self.setUpPyfakefs() in setUp(). You need add nothing to tearDown(). Write your tests as usual. From self.setUpPyfakefs() to the end of your tearDown() method, all file operations will use the fake file system.