kloudbuster/tests/conftest.py

94 lines
3.5 KiB
Python

"""
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)