# pyfakefs: a fake file system for testing Python code

> pyfakefs replaces the Python file system modules with an in-memory implementation during a test, so code under test needs no modification and never touches the real disk. It plugs into pytest as a fixture, into unittest as a test case or a patcher, and can be paused mid-test to reach the real file system again, with a documented limitation for code that reaches the file system through C libraries.

**pytest-dev/pyfakefs** — Provides a fake file system that mocks the Python file system modules.

- Repository: https://github.com/pytest-dev/pyfakefs
- Website: https://pytest-pyfakefs.readthedocs.io
- Stars: 754 · Forks: 109
- Language: Python
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/pytest-dev-pyfakefs

## What the fake file system does and does not touch

pyfakefs implements a fake file system that mocks the Python file system modules. The tests operate on a fake file system in memory without touching the real disk, and the software under test requires no modification to work with it.

That last property is the one that matters in practice. Most file system mocking in other languages requires changing the code to accept an injected file system abstraction. pyfakefs works by patching the modules themselves, so a function that calls open() with no arguments goes to the fake file system, and the code does not know.

The lifecycle is per test. A new empty in-memory file system is created at each test start, replacing the real filesystem during the test, and the README offers the analogy that it is like making a per-test temporary directory, except for an entire file system.

The topic tags place it precisely, with filesystem, mocking, pytest-plugin, python and unit-testing. The primary language is Python, the licence field says Apache-2.0, and the project is tested with current versions of Linux, Windows and macOS, which matters because the fake file system has to emulate the differences between them.

The homepage is the readthedocs site at pytest-pyfakefs.readthedocs.io, and the project is classified as Production/Stable in its package metadata.

## The four ways to invoke it

The README lists several ways to invoke pyfakefs, which reflects that the library grew out of a unittest tool and was later given a pytest front end.

The pytest route is the fs fixture, which is the way most people meet it now. The unittest route is to derive your test case from fake_filesystem_unittest.TestCase, so the patching is handled by the base class rather than by a decorator. Then there is fake_filesystem_unittest.Patcher used as a context manager, which scopes the fake file system to a block of code. And there is the fake_filesystem_unittest.patchfs decorator, applied to a single test.

The difference between the Patcher and the patchfs decorator is scope. The Patcher is a context manager, so the fake file system exists for the duration of the with block. The decorator is applied to a test function and covers the whole test.

The usage documentation is linked for the details, and the README also points at two versions of the documentation, one for the latest released version and one for the current main branch, plus the release notes and the contributing guide.

The repository is a pytest-dev project, and the pyproject.toml registers the pytest plugin through an entry point, with the entry point named fakefs. So installing the package is enough to make the fs fixture available, with no plugin configuration needed.

## The features beyond plain mocking

The README separates the automatic mocking of most file system functions from a set of additional features, and these are what make it usable for anything more complicated than a simple write and read.

The first is mapping files and directories from the real file system into the fake one, so a test can start with a fixture tree that lives on disk. That is the escape hatch for the case where the data is large or awkward to construct in code.

The second is configuration and tracking of the file system size, which lets a test assert on how much space a write consumed, or simulate a full disk.

The third is pause and resume of patching, so a test step can reach the real file system inside a test that is otherwise entirely fake. That is the mechanism for the case where the code under test shells out, or reads a fixture from the real disk.

The fourth is limited emulation of other operating systems, so a test running on Linux can behave as if it were on macOS or Windows, which is how a project keeps one set of tests for code that has platform specific path handling.

And the fifth is configuration to behave as if running as a non-root user while running under root, which is a detail that matters on a continuous integration runner running as root, where the permission semantics your code expects would otherwise differ.

Taken together, these turn the library from a mock into a small simulation environment, which is the difference between testing a file writing function and testing a configuration installer.

## The limitation that decides whether you can use it

The README states the limitation in one paragraph, and it is the first thing to check before you plan to use the library.

pyfakefs will not work with Python libraries that use C libraries to access the file system. The reason is that pyfakefs cannot patch the underlying C libraries' file access functions, so the C libraries will always access the real file system.

That is a hard boundary rather than a rough edge. Patching happens at the Python module level, so anything that crosses into C and then into the operating system's file API bypasses the fake entirely, and a test that silently reads the real disk will pass for the wrong reason.

The practical cases where this bites are familiar. A database engine that stores its files through a C library, an image or video codec in a C extension, a cryptographic library with its own file handling, a native library that reads a certificate or a key file, and anything using mmap. The README links to a documentation section on the limitations, which is where the current list of affected cases lives.

The other boundary worth noting is the opposite direction. Because the fake is in memory, a test that writes a large file will consume the memory of the test process rather than the disk, so a test that writes a gigabyte to check a progress bar will behave differently under pyfakefs than in production, and the size tracking feature exists precisely so you can notice that.

## The history, and why the ownership changed

The history section of the README is unusual and worth reading, because it explains the project structure.

pyfakefs.py was initially developed at Google by Mike Bland as a modest fake implementation of core Python modules. It was introduced to all of Google in September 2006, and at last count it was used in over 20,000 Python tests at Google.

Google released it to the public in 2011 as a Google Code project. Support for unittest and doctest was added in a fork by user jmcgeheeiv, further corrections were made in a separate fork by user shiffdane, and after the shutdown of Google Code was announced, John McGehee merged all three Google Code projects together on GitHub. In 2022 the repository was transferred to pytest-dev to ensure continuous maintenance.

That history explains the shape of the library, in particular the four invocation styles. The unittest TestCase and the Patcher and the patchfs decorator are the original API from the Google era, and the pytest fixture was added later. It also explains the packaging metadata, which lists Google and John McGehee as the authors and a Google address as the maintainer, so the project is still nominally run by the organisation where it began.

The repository layout is small and conventional, with a pyfakefs/ package directory, a docs/ directory, a pyproject.toml, a mypy.ini, a CHANGES.md, a CONTRIBUTING.md, a COPYING file, a Dockerfile and a pre-commit configuration.

## The Docker image and how the tests are run

The Dockerfile in the repository is there to run the test suite in a controlled environment, and the comments at the top say so: install Docker, clone pyfakefs, then build and run the container.

The image is based on ubuntu, and the first thing it does is fix a locale, which is a detail worth understanding rather than copying. The Ubuntu base container does not specify a locale, and the pyfakefs tests require at least the Latin1 character set, so the image installs the locales package, generates en_US.UTF-8 and sets LANG, LANGUAGE and LC_ALL accordingly.

The rest is a straightforward build. The package manager installs python3-pip, unzip and wget, a pyfakefs user is created, the main branch archive is downloaded and unpacked with wget and unzip rather than a git clone, and the ownership is handed to that user. The dependencies are then installed with pip3 using the dev and extra groups.

The final part is the run command, and it is the useful detail. The container runs the whole test suite as a module.

```
CMD ["python3", "-m", "pyfakefs.tests.all_tests"]
```

So the suite is a package with an all_tests entry point, and the container runs it directly rather than going through a test runner configuration. The image also sets PYTHONPATH to the unpacked source directory, and the working directory is the checkout.

For a project that wants to run its own tests against pyfakefs, the same Dockerfile is a good starting point, since it encodes the locale requirement that is easy to miss when the suite fails for an unrelated-looking reason.

## Where pyfakefs is the wrong choice

The first limitation is the C library boundary, already covered, and it is the one that ends the discussion for some codebases. If the code under test reads or writes files through a C extension, pyfakefs cannot help, and the test will silently exercise the real disk.

The second is the cost of the fake. Every test that uses it pays for creating an empty file system and for the patching machinery around it, and the in-memory file system means a test that writes a lot of data uses the memory of the test process. The size tracking feature is there partly so that this is visible.

The third is that pyfakefs is not a general file system emulator. The OS emulation is described as limited, and the features are the ones a test suite needs rather than the ones an application would meet. Code that behaves differently on a real network file system, on a case insensitive file system, or with hard links, is not going to be faithfully modelled.

The fourth is the alternative that often works just as well. For a function that takes a path and returns content, the standard advice is to pass a temporary directory and let the real file system do its job, and that is one line of setup rather than a fixture. pyfakefs earns its place when the test needs to assert on the file system's state, on the size, or on the calls made, or when creating a large tree in code is impractical.

The fifth is that mocking the whole file system for a whole test is a broad instrument. A test that only needs one file mocked may be better served by a narrower patch, and a broad fake tends to make the test depend on the fake's behaviour in ways that make the test brittle.

## How pyfakefs compares with tmp_path, with mock and with a container

The comparison with pytest's own tmp_path fixture is the one every user starts with, and the difference in approach is isolation rather than speed. tmp_path gives a real directory, which is fast, simple and completely faithful, and its weakness is that it does not give the test the ability to assert on what was written beyond inspecting the directory, and it does not isolate reads from the rest of the disk.

The comparison with unittest.mock is the second. A mock of the open function is fast and precise, and it is also brittle, because the test then encodes the call sequence rather than the behaviour, and any refactor of the code under test breaks the mock. pyfakefs keeps the code path real, because the code still calls open, and only the underlying storage is fake. That is why it works with code that was never written to be testable, which is the majority of code.

The third comparison is with running the test in a container or a chroot, which gives a real file system that is nevertheless isolated. The difference is that a container is a heavyweight operation per test session, and it does not give you programmatic control over the file system's contents, whereas pyfakefs lets you create files, set permissions, set sizes and assert on what happened.

The fourth is with a library that mocks the file system at a higher level, such as a library that gives you a virtual file system object you pass around. That approach is faster and more precise, and it requires the code to accept the abstraction, which is the constraint pyfakefs exists to avoid.

## Licence, project state and what to check before you adopt it

The licence field on the repository says Apache-2.0, and the package metadata records the same, with the COPYING file listed in the license-files entry. The authors are listed as Google and John McGehee, and the maintainer is mrbean-bremen, with a Google address, which is the arrangement after the transfer to pytest-dev.

The project is not archived and the last push was on 2026-10-19, so it is actively maintained, and the release history shows a steady patch line, with v6.2.0 from 2026-04-12, v6.1.6 from 2026-03-18 and v6.1.5 from 2026-03-15. The version is dynamic in the metadata, which is the setuptools_scm pattern of deriving it from the repository tags.

The supported Python versions are 3.10 through 3.14, on both CPython and PyPy, and the classifiers cover Linux, macOS and Windows. The package requires Python 3.10 or newer.

Four things to check before you adopt it.

Whether anything in your dependency chain opens files through a C library, since that is the boundary the project cannot cross and it is invisible until a test reads the real disk by accident.

Whether your tests are pytest or unittest, because the four invocation styles cover both but the ergonomics differ, and the fs fixture is the one to reach for in a pytest codebase.

The locale, which the Dockerfile goes out of its way to configure, since a test that fails on a character set rather than on a file system is a confusing failure.

And the OS emulation, if your code has platform specific path handling, because the emulation is described as limited and you should verify it against the cases you actually care about rather than assume.

## Conclusion

pyfakefs suits a test suite that writes to disk as a side effect, where the disk writes are incidental to what is being tested and the real file system is a source of flakiness. It is the wrong tool for code that reaches the file system through a C extension, because the README says the C libraries always access the real file system and cannot be patched, and the wrong choice for a test that genuinely needs to move bytes between machines or to a device. Before adopting it, check whether anything in your dependency chain opens files through a C library, since that is the boundary the project cannot cross.

## FAQ

### What does pyfakefs do?

It implements a fake file system that mocks the Python file system modules, so tests operate on an in-memory file system without touching the real disk. The software under test needs no modification, because the patching happens at the module level rather than through an injected abstraction.

### How do I use pyfakefs with pytest and with unittest?

With pytest you use the fs fixture. With unittest you derive from fake_filesystem_unittest.TestCase, or use fake_filesystem_unittest.Patcher as a context manager, or apply the fake_filesystem_unittest.patchfs decorator to a single test.

### What are the limitations of pyfakefs?

It will not work with Python libraries that use C libraries to access the file system, because pyfakefs cannot patch the underlying C libraries' file access functions and those libraries will always access the real file system.

### What extra features does pyfakefs provide beyond mocking?

Mapping files and directories from the real file system into the fake one, configuration and tracking of the file system size, pause and resume of patching so a test step can use the real file system, limited emulation of other operating systems, and configuration to behave as a non-root user while running under root.

### How do I run the pyfakefs test suite in a container?

The repository's Dockerfile builds an Ubuntu image with the locales package and an en_US.UTF-8 locale, since the tests require at least Latin1, then installs the dependencies and runs the suite with `python3 -m pyfakefs.tests.all_tests`.

### What licence does pyfakefs use?

Apache-2.0, with the terms in the COPYING file at the root of the repository, and the package metadata records the same licence with Google and John McGehee listed as the authors.

## Sources

- [License: Apache-2.0](https://github.com/pytest-dev/pyfakefs/blob/main/LICENSE)
- [Project website](https://pytest-pyfakefs.readthedocs.io)
- [pytest-dev/pyfakefs on GitHub](https://github.com/pytest-dev/pyfakefs)
- [README](https://github.com/pytest-dev/pyfakefs/blob/main/README.md)
- [Releases](https://github.com/pytest-dev/pyfakefs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pytest-dev-pyfakefs
