3 # Author: Lea Wiemann <LeWiemann@gmail.com>
4 # Copyright: This module has been placed in the public domain.
7 Perform tests with the data in the functional/ directory.
9 Please see the documentation on `functional testing`__ for details.
11 __ ../../docs/dev/testing.html#functional
15 from pathlib
import Path
20 if __name__
== '__main__':
21 # prepend the "docutils root" to the Python library path
22 # so we import the local `docutils` package.
23 sys
.path
.insert(0, str(Path(__file__
).resolve().parents
[1]))
25 from docutils
import core
, SettingsSpec
27 FUNCTIONAL
= Path('functional')
28 EXPECTED
= FUNCTIONAL
/ 'expected'
29 INPUT
= FUNCTIONAL
/ 'input'
30 OUTPUT
= FUNCTIONAL
/ 'output'
31 TESTS
= FUNCTIONAL
/ 'tests'
33 NO_EXPECTED_TEMPLATE
= """\
34 Cannot find expected output at {exp}
35 If the output in {out}
36 is correct, move it to the expected/ dir and check it in:
40 svn commit -m "<comment>" {exp}
43 EXPECTED_OUTPUT_DIFFERS_TEMPLATE
= """\
44 Expected and actual output differ.
48 If the actual output is correct, please replace the
49 expected output and check it in:
53 svn commit -m "<comment>" {exp}
56 # Default settings for functional tests.
57 # Override "factory defaults",
58 # overridden by `settings_overrides` in the individual tests.
59 # cf. docs/api/runtime-settings.html#settings-priority
60 functional_tests_settings_spec
= SettingsSpec()
61 functional_tests_settings_spec
.settings_default_overrides
= {
62 '_disable_config': True,
65 'input_encoding': 'utf-8', # skip auto-detection
66 'embed_stylesheet': False,
67 'syntax_highlight': 'none' # avoid "Pygments not found" warning
71 class FunctionalTests(unittest
.TestCase
):
73 """Test case for one config file."""
76 """Clear output directory."""
77 for entry
in OUTPUT
.rglob('*'):
80 elif entry
.name
!= 'README.txt':
83 def test_functional(self
):
84 """Process test file."""
85 for test_file
in TESTS
.glob("*.py"):
86 with self
.subTest(test_file
=test_file
.as_posix()):
88 # Load variables from the current test file into the namespace
89 exec(test_file
.read_text(encoding
='utf-8'), namespace
)
90 del namespace
['__builtins__'] # clean-up
92 # Full source, generated output, and expected output paths
93 source_path
= INPUT
/ namespace
.pop('test_source')
94 destination_path
= OUTPUT
/ namespace
['test_destination']
95 expected_path
= EXPECTED
/ namespace
.pop('test_destination')
97 # Get output (automatically written to the output/ directory
99 output
= core
.publish_file(
101 source_path
=source_path
.as_posix(),
102 destination_path
=destination_path
.as_posix(),
103 settings_spec
=functional_tests_settings_spec
,
106 # Get the expected output *after* writing the actual output.
108 expected
= expected_path
.read_text(encoding
='utf-8')
109 except OSError as err
:
110 raise OSError(NO_EXPECTED_TEMPLATE
.format(
111 exp
=expected_path
, out
=destination_path
)
114 if output
!= expected
:
115 diff
= ''.join(difflib
.unified_diff(
116 expected
.splitlines(True), output
.splitlines(True),
117 expected_path
.as_posix(), destination_path
.as_posix()))
118 raise AssertionError(
119 EXPECTED_OUTPUT_DIFFERS_TEMPLATE
.format(
120 diff
=diff
, exp
=expected_path
, out
=destination_path
)
124 if __name__
== '__main__':