[ 1612821 ] Double quotes in literal text in Italian/German
[docutils.git] / test / test_functional.py
blobd2dff949dc559c3138e9b9442dcf8f2615b05a69
1 #!/usr/bin/env python
3 # $Id$
4 # Author: Lea Wiemann <LeWiemann@gmail.com>
5 # Copyright: This module has been placed in the public domain.
7 """
8 Perform tests with the data in the functional/ directory.
10 Read README.txt for details on how this is done.
11 """
13 import sys
14 import os
15 import os.path
16 import shutil
17 import unittest
18 import difflib
19 import DocutilsTestSupport # must be imported before docutils
20 import docutils
21 import docutils.core
24 datadir = 'functional'
25 """The directory to store the data needed for the functional tests."""
28 def join_path(*args):
29 return '/'.join(args) or '.'
32 class FunctionalTestSuite(DocutilsTestSupport.CustomTestSuite):
34 """Test suite containing test cases for all config files."""
36 def __init__(self):
37 """Process all config files in functional/tests/."""
38 DocutilsTestSupport.CustomTestSuite.__init__(self)
39 os.chdir(DocutilsTestSupport.testroot)
40 self.clear_output_directory()
41 self.added = 0
42 os.path.walk(join_path(datadir, 'tests'), self.walker, None)
43 assert self.added, 'No functional tests found.'
45 def clear_output_directory(self):
46 files = os.listdir(os.path.join('functional', 'output'))
47 for f in files:
48 if f in ('README.txt', '.svn', 'CVS'):
49 continue # don't touch the infrastructure
50 path = os.path.join('functional', 'output', f)
51 if os.path.isdir(path):
52 shutil.rmtree(path)
53 else:
54 os.remove(path)
56 def walker(self, dummy, dirname, names):
57 """
58 Process all config files among `names` in `dirname`.
60 This is a helper function for os.path.walk. A config file is
61 a Python file (*.py) which sets several variables.
62 """
63 for name in names:
64 if name.endswith('.py') and not name.startswith('_'):
65 config_file_full_path = join_path(dirname, name)
66 self.addTestCase(FunctionalTestCase, 'test', None, None,
67 id=config_file_full_path,
68 configfile=config_file_full_path)
69 self.added += 1
72 class FunctionalTestCase(DocutilsTestSupport.CustomTestCase):
74 """Test case for one config file."""
76 def __init__(self, *args, **kwargs):
77 """Set self.configfile, pass arguments to parent __init__."""
78 self.configfile = kwargs['configfile']
79 del kwargs['configfile']
80 DocutilsTestSupport.CustomTestCase.__init__(self, *args, **kwargs)
82 def shortDescription(self):
83 return 'test_functional.py: ' + self.configfile
85 def test(self):
86 """Process self.configfile."""
87 os.chdir(DocutilsTestSupport.testroot)
88 # Keyword parameters for publish_file:
89 namespace = {}
90 # Initialize 'settings_overrides' for test settings scripts,
91 # and disable configuration files:
92 namespace['settings_overrides'] = {'_disable_config': 1}
93 # Read the variables set in the default config file and in
94 # the current config file into namespace:
95 defaultpy = open(join_path(datadir, 'tests', '_default.py')).read()
96 exec(defaultpy, namespace)
97 exec(open(self.configfile).read(), namespace)
98 # Check for required settings:
99 assert 'test_source' in namespace,\
100 "No 'test_source' supplied in " + self.configfile
101 assert 'test_destination' in namespace,\
102 "No 'test_destination' supplied in " + self.configfile
103 # Set source_path and destination_path if not given:
104 namespace.setdefault('source_path',
105 join_path(datadir, 'input',
106 namespace['test_source']))
107 # Path for actual output:
108 namespace.setdefault('destination_path',
109 join_path(datadir, 'output',
110 namespace['test_destination']))
111 # Path for expected output:
112 expected_path = join_path(datadir, 'expected',
113 namespace['test_destination'])
114 # shallow copy of namespace to minimize:
115 params = namespace.copy()
116 # remove unneeded parameters:
117 del params['test_source']
118 del params['test_destination']
119 # Delete private stuff like params['__builtins__']:
120 for key in params.keys():
121 if key.startswith('_'):
122 del params[key]
123 # Get output (automatically written to the output/ directory
124 # by publish_file):
125 output = docutils.core.publish_file(**params)
126 # Get the expected output *after* writing the actual output.
127 self.assert_(os.access(expected_path, os.R_OK),\
128 'Cannot find expected output at\n' + expected_path)
129 f = open(expected_path, 'rU')
130 expected = f.read()
131 f.close()
132 diff = ('The expected and actual output differs.\n'
133 'Please compare the expected and actual output files:\n'
134 ' diff %s %s\n'
135 'If the actual output is correct, please replace the\n'
136 'expected output and check it in to Subversion:\n'
137 ' mv %s %s\n'
138 ' svn commit -m "<comment>" %s'
139 % (expected_path, params['destination_path'],
140 params['destination_path'], expected_path, expected_path))
141 try:
142 self.assertEquals(output, expected, diff)
143 except AssertionError:
144 if hasattr(difflib, 'unified_diff'):
145 # Generate diff if unified_diff available:
146 diff = ''.join(
147 difflib.unified_diff(expected.splitlines(1),
148 output.splitlines(1),
149 expected_path,
150 params['destination_path']))
151 print >>sys.stderr, '\n%s:' % (self,)
152 print >>sys.stderr, diff
153 raise
154 # Execute optional function containing extra tests:
155 if '_test_more' in namespace:
156 namespace['_test_more'](join_path(datadir, 'expected'),
157 join_path(datadir, 'output'),
158 self, namespace)
161 def suite():
162 return FunctionalTestSuite()
165 if __name__ == '__main__':
166 unittest.main(defaultTest='suite')