3 changed files with 137 additions and 6 deletions
@ -0,0 +1,93 @@
|
||||
""" |
||||
This module is used to define shared pytest fixtures. |
||||
Because this module is placed under tests, all fixtures defined here can be used |
||||
by all test cases below tests |
||||
""" |
||||
import os |
||||
import shutil |
||||
|
||||
import pytest |
||||
|
||||
def stage_file(dirname, filename, content=None): |
||||
# we cannot use a os.path.join because we want to support |
||||
# multi-parts in the filename |
||||
if dirname.endswith('/') and filename.startswith('/'): |
||||
pathname = dirname + filename[1:] |
||||
elif filename.startswith('/') or dirname.endswith('/'): |
||||
pathname = dirname + filename |
||||
else: |
||||
pathname = dirname + '/' + filename |
||||
print('Staging file: ', pathname) |
||||
os.makedirs(os.path.dirname(pathname), exist_ok=True) |
||||
if content is None: |
||||
content = pathname |
||||
with open(pathname, 'w') as ff: |
||||
ff.write(content) |
||||
|
||||
|
||||
@pytest.fixture |
||||
def stage_fs(): |
||||
""" |
||||
This fixture can be used to stage a complete file system below a given root. |
||||
|
||||
This is a fixture factory and each test function can call stage_fs with the root of the |
||||
file system to stage and with a configuration. |
||||
The entire root_fs will be deleted when the fixture terminates unless skip_clean=True |
||||
|
||||
Example of files_config: |
||||
{ |
||||
'file1.yaml': 'any content', |
||||
'folder1': { |
||||
'file_with_arbitrary_content.yaml': None, |
||||
'empty_file.txt': '', |
||||
'nested_empty_folder: {} |
||||
} |
||||
'folder1/file2.txt': None |
||||
} |
||||
if '/tmp/pico' is passed as fs_root, this fixture will stage the following files: |
||||
|
||||
/tmp/pico/file1.yaml (containing 'any content') |
||||
/tmp/pico/folder1/file_with_arbitrary_content.yaml (containing arbitary text) |
||||
/tmp/pico/folder1/empty_file.txt (empty) |
||||
/tmp/pico/folder1/nested_empty_folder/ (empty directory) |
||||
/tmp/pico/folder1/file2.txt (any content) |
||||
|
||||
|
||||
To use this fixture, simply add "stage_fs" as argument to your test function, then |
||||
call stage_fs() with arguments described in below _stage_fs function. |
||||
Also see the unit test code (test_fixtures.py) |
||||
""" |
||||
saved_fs_root = [] |
||||
def _stage_fs(fs_root, files_config, skip_clean=False): |
||||
""" |
||||
fs_root: pathname of the root under which all all the files defined in files_config must be staged |
||||
files_config: a dict of file content reflecting the desired staged file system |
||||
skip_clean: set to True if you do not want the staged directory to be cleaned on exit (for troubleshooting only) |
||||
""" |
||||
if not saved_fs_root: |
||||
if skip_clean: |
||||
# for troubleshooting, it is possible to preserve |
||||
# the stage_fs directory after the test finishes |
||||
saved_fs_root.append(None) |
||||
else: |
||||
saved_fs_root.append(fs_root) |
||||
# remove the stage_fs root directory at start |
||||
# so we're sure we start with a clean directory |
||||
shutil.rmtree(fs_root, ignore_errors=True) |
||||
os.makedirs(fs_root, exist_ok=True) |
||||
|
||||
for file, content in files_config.items(): |
||||
if isinstance(content, dict): |
||||
# remove any "/" at start |
||||
if file[0] == '/': |
||||
file = file[1:] |
||||
new_fs_root = os.path.join(fs_root, file) |
||||
os.makedirs(new_fs_root, exist_ok=True) |
||||
_stage_fs(new_fs_root, content) |
||||
else: |
||||
stage_file(fs_root, file, content) |
||||
yield _stage_fs |
||||
if saved_fs_root: |
||||
if saved_fs_root[0]: |
||||
# remove the stage_fs directory when the fixture terminates |
||||
shutil.rmtree(saved_fs_root[0], ignore_errors=True) |
Loading…
Reference in new issue