1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
#!/usr/bin/env python3
# $Id: test_functional.py 9518 2024-01-26 22:46:31Z milde $
# Author: Lea Wiemann <LeWiemann@gmail.com>
# Copyright: This module has been placed in the public domain.
"""
Perform tests with the data in the functional/ directory.
Please see the documentation on `functional testing`__ for details.
__ ../../docs/dev/testing.html#functional
"""
import difflib
from pathlib import Path
import shutil
import sys
import unittest
if __name__ == '__main__':
# prepend the "docutils root" to the Python library path
# so we import the local `docutils` package.
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from docutils import core, SettingsSpec
FUNCTIONAL = Path('functional')
EXPECTED = FUNCTIONAL / 'expected'
INPUT = FUNCTIONAL / 'input'
OUTPUT = FUNCTIONAL / 'output'
TESTS = FUNCTIONAL / 'tests'
NO_EXPECTED_TEMPLATE = """\
Cannot find expected output at {exp}
If the output in {out}
is correct, move it to the expected/ dir and check it in:
mv {out} {exp}
svn add {exp}
svn commit -m "<comment>" {exp}
"""
EXPECTED_OUTPUT_DIFFERS_TEMPLATE = """\
Expected and actual output differ.
{diff}
If the actual output is correct, please replace the
expected output and check it in:
mv {out} {exp}
svn add {exp}
svn commit -m "<comment>" {exp}
"""
# Default settings for functional tests.
# Override "factory defaults",
# overridden by `settings_overrides` in the individual tests.
# cf. docs/api/runtime-settings.html#settings-priority
functional_tests_settings_spec = SettingsSpec()
functional_tests_settings_spec.settings_default_overrides = {
'_disable_config': True,
'halt_level': 5,
'warning_stream': '',
'input_encoding': 'utf-8', # skip auto-detection
'embed_stylesheet': False,
'syntax_highlight': 'none' # avoid "Pygments not found" warning
}
def compare_output(output, destination_path, expected_path):
try:
expected = expected_path.read_text(encoding='utf-8')
except OSError as err:
raise OSError(NO_EXPECTED_TEMPLATE.format(exp=expected_path,
out=destination_path)
) from err
if output != expected:
diff = ''.join(difflib.unified_diff(expected.splitlines(True),
output.splitlines(True),
expected_path.as_posix(),
destination_path.as_posix()))
raise AssertionError(
EXPECTED_OUTPUT_DIFFERS_TEMPLATE.format(
diff=diff, exp=expected_path, out=destination_path)
)
class FunctionalTests(unittest.TestCase):
"""Test case for one config file."""
def setUp(self):
"""Clear output directory."""
for entry in OUTPUT.rglob('*'):
if entry.is_dir():
shutil.rmtree(entry)
elif entry.name != 'README.txt':
entry.unlink()
def test_functional(self):
"""Process test file."""
for test_file in TESTS.glob("*.py"):
with self.subTest(test_file=test_file.as_posix()):
namespace = {}
# Load variables from the current test file into the namespace
exec(test_file.read_text(encoding='utf-8'), namespace)
del namespace['__builtins__'] # clean-up
# Full source, generated output, and expected output paths
source_path = INPUT / namespace.pop('test_source')
destination_path = OUTPUT / namespace['test_destination']
expected_path = EXPECTED / namespace.pop('test_destination')
# Get output (automatically written to the output/ directory
# by publish_file):
output = core.publish_file(
**namespace,
source_path=source_path.as_posix(),
destination_path=destination_path.as_posix(),
settings_spec=functional_tests_settings_spec,
)
# Get the expected output *after* writing the actual output.
compare_output(output, destination_path, expected_path)
if __name__ == '__main__':
unittest.main()
|