Search code examples
pytestpyfakefs

Best practise for add_real_* in fakefs


I utelize in one of my test fakefs to create files, which are not available at the testsystem. Additional I need to access a config file which is available in the realfs.

So the following works:

fs.add_real_file(
    "/home/username/development/logs/config.cfg",
    target_path="/logs/config.cfg"
)

The absolute path is working but seems wrong. Nobody is able to access this file than myself without manipulating the tests. That is not intended.

Just using the relative path doesn't work either, because the fakefs is already active.

How should I handle this in general?


Solution

  • Adding files to the fake filesystem in a portable way is possible, if you can define their path relative to some other path (or if they have the same path on all systems, of course). Here are a few examples for this:

    One possibility is that you know the location of the files relative to the test itself. Here is a typical example that maps a test fixture directory into the fake filesystem (in this case the directory "fixtures" beside the tests):

    from pathlib import Path
    
    def test_using_fixture(fs):
        fixture_path = Path(__file__).parent / "fixtures"
        fs.add_real_directory(fixture_path)
        with open(fixture_path / "fixture.txt") as f:
            contents = f.read()
    

    In this case, the whole path to the fixtures in the real filesystem is mapped into the fake filesystem, creating parent directories as needed.

    Another possibility is to use the home directory as the base, which probably can be used for the original question. This could be done by:

    def test_file_in_home_dir(fs):
        log_path = Path.home() / "development" / "logs"
        fs.add_real_file(log_path / "config.cfg", target_path="/logs/config.cfg")
    

    Note that the home path is always taken from the real file system, even it does not exist in the fake filesystem. In this case, as there is a target_path, the home directory will still not be created in the fake filesystem.

    Sometimes you want to map some data file that is contained in a Python package. In this case you may use the path of that package as the base. This is similar to the usage of __file__, just for another package:

    import os
    import some_module
    
    def test_module(fs):
        module_path = some_module.__file__
        data_path = os.path.join(module_path, "data")
        fs.add_real_directory(data_path)