1import os
2
3from io import open
4
5
6def make_case_function(left_filename):
7    right_filename = left_filename.replace('.left.', '.right.')
8    expected_filename = left_filename.replace('.left.', '.expected.')
9
10    def test(self):
11        with open(expected_filename, 'rt', encoding='utf8') as input_file:
12            expected_xml = input_file.read()
13
14        try:
15            result_xml = self.process(left_filename, right_filename)
16        except Exception as err:
17            if u'.err' not in left_filename:
18                raise
19            result_xml = u'%s: %s' % (err.__class__.__name__, err)
20
21        self.assertEqual(expected_xml.strip(), result_xml.strip())
22
23    return test
24
25
26def generate_filebased_cases(data_dir, test_class, suffix='xml', ignore=()):
27    for left_filename in os.listdir(data_dir):
28        if not left_filename.endswith('.left.' + suffix):
29            continue
30        if left_filename in ignore:
31            continue
32
33        left_filename = os.path.join(data_dir, left_filename)
34        test_function = make_case_function(left_filename)
35        function_name = os.path.split(left_filename)[-1].replace('.', '-')
36        test_name = 'test_' + function_name
37        setattr(test_class, test_name, test_function)
38
39
40def compare_elements(left, right):
41    path = left.getroottree().getpath(left)
42    assert left.text == right.text, "Texts differ: %s" % path
43    assert left.tail == right.tail, "Tails differ: %s" % path
44    assert left.attrib == right.attrib, "Attributes differ: %s" % path
45    # We intentionally do NOT compare namespaces, they are allowed to differ
46    assert len(left) == len(right), "Children differ: %s" % path
47    for l, r in zip(left.getchildren(), right.getchildren()):
48        compare_elements(l, r)
49