Update MANIFEST.in template and tests

- Now MANIFEST.in includes package data inclusions
    and exclusions
  - Clean test subpackage
  - Test factory moved to a separated module
  - Add a factory argument for checking with lxml
  - SchemaObserver moved to a separated module
  - Test factory now can creates tests for XMLSchema11 class
This commit is contained in:
Davide Brunato 2018-12-27 19:20:04 +01:00
parent 310052c5f6
commit ca47623dba
9 changed files with 350 additions and 224 deletions

View File

@ -1,2 +1,14 @@
# Include the license file
include MANIFEST.in
include LICENSE
include README.rst
include CHANGELOG.rst
include setup.py
include setup.cfg
include requirements-dev.txt
include tox.ini
include doc/*
recursive-include xmlschema *
recursive-exclude xmlschema/tests/extra* *
global-exclude *.py[cod]

View File

@ -1,4 +1,4 @@
[wheel]
[bdist_wheel]
universal = 1
[metadata]

View File

@ -9,7 +9,7 @@
#
# @author Davide Brunato <brunato@sissa.it>
#
from setuptools import setup
from setuptools import setup, find_packages
with open("README.rst") as readme:
long_description = readme.read()
@ -20,7 +20,6 @@ setup(
install_requires=['elementpath>=1.1.0', 'defusedxml>=0.5'],
packages=['xmlschema'],
include_package_data=True,
exclude_package_date={'xmlschema': ['tests/extra-*']},
author='Davide Brunato',
author_email='brunato@sissa.it',
url='https://github.com/brunato/xmlschema',

View File

@ -9,21 +9,14 @@
# @author Davide Brunato <brunato@sissa.it>
#
"""
Tests subpackage imports and methods for unittest scripts of the 'xmlschema' package.
Tests subpackage module: common definitions for unittest scripts of the 'xmlschema' package.
"""
import unittest
import re
import os
import sys
import glob
import fileinput
import argparse
import logging
from functools import wraps
import xmlschema
from xmlschema import XMLSchema, XMLSchema10
from xmlschema.validators import XMLSchema11
from xmlschema import XMLSchema
from xmlschema.compat import urlopen, URLError
from xmlschema.exceptions import XMLSchemaValueError
from xmlschema.etree import (
@ -34,7 +27,8 @@ from xmlschema.qnames import XSD_SCHEMA
from xmlschema.helpers import get_namespace
from xmlschema.namespaces import XSD_NAMESPACE
logger = logging.getLogger('xmlschema.tests')
from .schema_observers import SchemaObserver
from .test_factory import tests_factory
def has_network_access(*locations):
@ -49,8 +43,7 @@ def has_network_access(*locations):
SKIP_REMOTE_TESTS = not has_network_access('http://www.sissa.it', 'http://www.w3.org/', 'http://dublincore.org/')
PROTECTED_PREFIX_PATTERN = re.compile("ns\d:")
PROTECTED_PREFIX_PATTERN = re.compile(r'ns\d:')
def print_test_header():
@ -58,190 +51,6 @@ def print_test_header():
print("*" * len(header) + '\n' + header + '\n' + "*" * len(header))
def get_testfiles(test_dir):
# Checks arguments and defines the testfiles lists to use
if '-x' not in sys.argv and '--extra' not in sys.argv:
testfiles = glob.glob(os.path.join(test_dir, 'cases/testfiles'))
else:
testfiles = glob.glob(os.path.join(test_dir, '*/testfiles'))
try:
sys.argv.remove('-x')
except ValueError:
sys.argv.remove('--extra')
return testfiles
class SchemaObserver(object):
components = []
@classmethod
def observe_builder(cls, builder):
if isinstance(builder, type):
class BuilderProxy(builder):
def __init__(self, *args, **kwargs):
super(BuilderProxy, self).__init__(*args, **kwargs)
cls.components.append(self)
BuilderProxy.__name__ = builder.__name__
return BuilderProxy
elif callable(builder):
@wraps(builder)
def builder_proxy(*args, **kwargs):
result = builder(*args, **kwargs)
cls.components.append(result)
return result
return builder_proxy
@classmethod
def clear(cls):
del cls.components[:]
class ObservedXMLSchema10(XMLSchema10):
BUILDERS = {
k: SchemaObserver.observe_builder(getattr(XMLSchema10.BUILDERS, k))
for k in getattr(XMLSchema10.BUILDERS, '_fields')
}
def get_test_args(args_line):
try:
args_line, _ = args_line.split('#', 1)
except ValueError:
pass
return re.split(r'(?<!\\) ', args_line.strip())
def xsd_version_number(value):
if value not in ('1.0', '1.1'):
msg = "%r is not an XSD version." % value
raise argparse.ArgumentTypeError(msg)
return value
def defuse_data(value):
if value not in ('always', 'remote', 'never'):
msg = "%r is not a valid value." % value
raise argparse.ArgumentTypeError(msg)
return value
def get_args_parser():
parser = argparse.ArgumentParser(add_help=True)
parser.usage = "TEST_FILE [OPTIONS]\nTry 'TEST_FILE --help' for more information."
parser.add_argument('filename', metavar='TEST_FILE', type=str, help="Test filename (relative path).")
parser.add_argument(
'-L', dest='locations', nargs=2, type=str, default=None, action='append',
metavar="URI-URL", help="Schema location hint overrides."
)
parser.add_argument(
'--version', dest='version', metavar='VERSION', type=xsd_version_number, default='1.0',
help="XSD schema version to use for the test case (default is 1.0)."
)
parser.add_argument(
'--errors', type=int, default=0, metavar='NUM', help="Number of errors expected (default=0)."
)
parser.add_argument(
'--warnings', type=int, default=0, metavar='NUM', help="Number of warnings expected (default=0)."
)
parser.add_argument(
'--inspect', action="store_true", default=False, help="Inspect using an observed custom schema class."
)
parser.add_argument(
'--defuse', metavar='(always, remote, never)', type=defuse_data, default='remote',
help="Define when to use the defused XML data loaders."
)
parser.add_argument(
'--timeout', type=int, default=300, metavar='SEC', help="Timeout for fetching resources (default=300)."
)
parser.add_argument(
'--defaults', action="store_true", default=False,
help="Test data uses default or fixed values (skip strict encoding checks).",
)
parser.add_argument(
'--skip', action="store_true", default=False,
help="Skip strict encoding checks (for cases where test data uses default or "
"fixed values or some test data are skipped by wildcards processContents)."
)
parser.add_argument(
'--debug', action="store_true", default=False,
help="Activate the debug mode (only the cases with --debug are executed).",
)
return parser
test_line_parser = get_args_parser()
def tests_factory(test_class_builder, testfiles, suffix="xml"):
test_classes = {}
test_num = 0
debug_mode = False
line_buffer = []
for line in fileinput.input(testfiles):
line = line.strip()
if not line or line[0] == '#':
if not line_buffer:
continue
else:
raise SyntaxError("Empty continuation at line %d!" % fileinput.filelineno())
elif '#' in line:
line = line.split('#', 1)[0].rstrip()
# Process line continuations
if line[-1] == '\\':
line_buffer.append(line[:-1].strip())
continue
elif line_buffer:
line_buffer.append(line)
line = ' '.join(line_buffer)
del line_buffer[:]
test_args = test_line_parser.parse_args(get_test_args(line))
if test_args.locations is not None:
test_args.locations = {k.strip('\'"'): v for k, v in test_args.locations}
test_file = os.path.join(os.path.dirname(fileinput.filename()), test_args.filename)
if os.path.isdir(test_file):
logger.debug("Skip %s: is a directory.", test_file)
continue
elif os.path.splitext(test_file)[1].lower() != '.%s' % suffix:
logger.debug("Skip %s: wrong suffix.", test_file)
continue
elif not os.path.isfile(test_file):
logger.error("Skip %s: is not a file.", test_file)
continue
test_num += 1
# Debug mode activation
if debug_mode:
if not test_args.debug:
continue
elif test_args.debug:
debug_mode = True
logger.debug("Debug mode activated: discard previous %r test classes.", len(test_classes))
test_classes.clear()
if test_args.inspect:
test_class = test_class_builder(test_file, test_args, test_num, ObservedXMLSchema10)
else:
test_class = test_class_builder(test_file, test_args, test_num)
test_classes[test_class.__name__] = test_class
logger.debug("Add XSD 1.0 test class %r.", test_class.__name__)
# test_class = test_class_builder(test_file, test_args, test_num, XMLSchema11)
# test_classes[test_class.__name__] = test_class
# logger.debug("Add XSD 1.1 test class for %r.", test_class.__name__)
if line_buffer:
raise ValueError("Not completed line continuation at the end!")
return test_classes
class XMLSchemaTestCase(unittest.TestCase):
"""
XMLSchema TestCase class.

View File

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
#
# Copyright (c), 2016-2018, SISSA (International School for Advanced Studies).
# All rights reserved.
# This file is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present
# distribution, or http://opensource.org/licenses/MIT.
#
# @author Davide Brunato <brunato@sissa.it>
#
"""
Observers for XMLSchema classes.
"""
from functools import wraps
from xmlschema.validators import XMLSchema10, XMLSchema11
class SchemaObserver(object):
"""
Observer that registers created components. Run the 'clear' method after each usage.
"""
components = []
@classmethod
def observed_builder(cls, builder):
if isinstance(builder, type):
class BuilderProxy(builder):
def __init__(self, *args, **kwargs):
super(BuilderProxy, self).__init__(*args, **kwargs)
cls.components.append(self)
BuilderProxy.__name__ = builder.__name__
return BuilderProxy
elif callable(builder):
@wraps(builder)
def builder_proxy(*args, **kwargs):
result = builder(*args, **kwargs)
cls.components.append(result)
return result
return builder_proxy
@classmethod
def clear(cls):
del cls.components[:]
class ObservedXMLSchema10(XMLSchema10):
BUILDERS = {
k: SchemaObserver.observed_builder(getattr(XMLSchema10.BUILDERS, k))
for k in getattr(XMLSchema10.BUILDERS, '_fields')
}
class ObservedXMLSchema11(XMLSchema11):
BUILDERS = {
k: SchemaObserver.observed_builder(getattr(XMLSchema11.BUILDERS, k))
for k in getattr(XMLSchema11.BUILDERS, '_fields')
}

View File

@ -25,7 +25,7 @@ if __name__ == '__main__':
sys.path.insert(0, pkg_base_dir)
import xmlschema
from xmlschema.tests import tests_factory, print_test_header, get_testfiles
from xmlschema.tests import print_test_header, tests_factory
from xmlschema.tests.test_helpers import TestHelpers
from xmlschema.tests.test_meta import TestXsd10BuiltinTypes, TestGlobalMaps
from xmlschema.tests.test_regex import TestCodePoints, TestUnicodeSubset, TestUnicodeCategories, TestPatterns
@ -39,8 +39,6 @@ if __name__ == '__main__':
from xmlschema.tests.test_package import TestPackaging
print_test_header()
testfiles = get_testfiles(os.path.dirname(os.path.abspath(__file__)))
globals().update(tests_factory(make_schema_test_class, testfiles, 'xsd'))
globals().update(tests_factory(make_validator_test_class, testfiles, 'xml'))
globals().update(tests_factory(make_schema_test_class, 'xsd'))
globals().update(tests_factory(make_validator_test_class, 'xml'))
unittest.main()

View File

@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
#
# Copyright (c), 2016-2018, SISSA (International School for Advanced Studies).
# All rights reserved.
# This file is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present
# distribution, or http://opensource.org/licenses/MIT.
#
# @author Davide Brunato <brunato@sissa.it>
#
"""
Test factory for creating test cases from lists of paths to XSD or XML files.
The list of cases can be defined within files named "testfiles". These are text files
that contain a list of relative paths to XSD or XML files, that are used to dinamically
build a set of test classes. Each path is followed by a list of options that defines a
custom setting for each test.
"""
import sys
import re
import os
import glob
import fileinput
import argparse
import logging
from xmlschema.validators import XMLSchema10, XMLSchema11
from .schema_observers import ObservedXMLSchema10, ObservedXMLSchema11
logger = logging.getLogger(__file__)
TEST_FACTORY_OPTIONS = {
'extra_files': '-x' in sys.argv or '--extra' in sys.argv, # Include extra test cases
'check_with_lxml': '-l' in sys.argv or '--lxml' in sys.argv, # Check with lxml.etree.XMLSchema (for XSD 1.0)
}
"""Command line options for test factory."""
sys.argv = [a for a in sys.argv if a not in {'-x', '--extra', '-l', '--lxml'}] # Clean sys.argv for unittest
def get_test_args(args_line):
"""Returns the list of arguments from provided text line."""
try:
args_line, _ = args_line.split('#', 1) # Strip optional ending comment
except ValueError:
pass
return re.split(r'(?<!\\) ', args_line.strip())
def create_test_line_args_parser():
"""Creates an arguments parser for uncommented on not blank "testfiles" lines."""
def xsd_version_number(value):
if value not in ('1.0', '1.1'):
msg = "%r is not an XSD version." % value
raise argparse.ArgumentTypeError(msg)
return value
def defuse_data(value):
if value not in ('always', 'remote', 'never'):
msg = "%r is not a valid value." % value
raise argparse.ArgumentTypeError(msg)
return value
parser = argparse.ArgumentParser(add_help=True)
parser.usage = "TEST_FILE [OPTIONS]\nTry 'TEST_FILE --help' for more information."
parser.add_argument('filename', metavar='TEST_FILE', type=str, help="Test filename (relative path).")
parser.add_argument(
'-L', dest='locations', nargs=2, type=str, default=None, action='append',
metavar="URI-URL", help="Schema location hint overrides."
)
parser.add_argument(
'--version', dest='version', metavar='VERSION', type=xsd_version_number, default='1.0',
help="XSD schema version to use for the test case (default is 1.0)."
)
parser.add_argument(
'--errors', type=int, default=0, metavar='NUM', help="Number of errors expected (default=0)."
)
parser.add_argument(
'--warnings', type=int, default=0, metavar='NUM', help="Number of warnings expected (default=0)."
)
parser.add_argument(
'--inspect', action="store_true", default=False, help="Inspect using an observed custom schema class."
)
parser.add_argument(
'--defuse', metavar='(always, remote, never)', type=defuse_data, default='remote',
help="Define when to use the defused XML data loaders."
)
parser.add_argument(
'--timeout', type=int, default=300, metavar='SEC', help="Timeout for fetching resources (default=300)."
)
parser.add_argument(
'--defaults', action="store_true", default=False,
help="Test data uses default or fixed values (skip strict encoding checks).",
)
parser.add_argument(
'--skip', action="store_true", default=False,
help="Skip strict encoding checks (for cases where test data uses default or "
"fixed values or some test data are skipped by wildcards processContents)."
)
parser.add_argument(
'--debug', action="store_true", default=False,
help="Activate the debug mode (only the cases with --debug are executed).",
)
return parser
test_line_parser = create_test_line_args_parser()
def tests_factory(test_class_builder, suffix='xml'):
"""
Factory function for file based schema/validation cases.
:param test_class_builder: the test class builder function.
:param suffix: the suffix ('xml' or 'xsd') to consider for cases.
:return: a list of test classes.
"""
test_dir = os.path.dirname(os.path.abspath(__file__))
test_classes = {}
test_num = 0
debug_mode = False
line_buffer = []
if TEST_FACTORY_OPTIONS['extra_files']:
testfiles = glob.glob(os.path.join(test_dir, '*/testfiles'))
else:
testfiles = glob.glob(os.path.join(test_dir, 'cases/testfiles'))
for line in fileinput.input(testfiles):
line = line.strip()
if not line or line[0] == '#':
if not line_buffer:
continue
else:
raise SyntaxError("Empty continuation at line %d!" % fileinput.filelineno())
elif '#' in line:
line = line.split('#', 1)[0].rstrip()
# Process line continuations
if line[-1] == '\\':
line_buffer.append(line[:-1].strip())
continue
elif line_buffer:
line_buffer.append(line)
line = ' '.join(line_buffer)
del line_buffer[:]
test_args = test_line_parser.parse_args(get_test_args(line))
if test_args.locations is not None:
test_args.locations = {k.strip('\'"'): v for k, v in test_args.locations}
test_file = os.path.join(os.path.dirname(fileinput.filename()), test_args.filename)
if os.path.isdir(test_file):
logger.debug("Skip %s: is a directory.", test_file)
continue
elif os.path.splitext(test_file)[1].lower() != '.%s' % suffix:
logger.debug("Skip %s: wrong suffix.", test_file)
continue
elif not os.path.isfile(test_file):
logger.error("Skip %s: is not a file.", test_file)
continue
test_num += 1
# Debug mode activation
if debug_mode:
if not test_args.debug:
continue
elif test_args.debug:
debug_mode = True
logger.debug("Debug mode activated: discard previous %r test classes.", len(test_classes))
test_classes.clear()
if test_args.version == '1.0':
schema_class = ObservedXMLSchema10 if test_args.inspect else XMLSchema10
check_with_lxml = TEST_FACTORY_OPTIONS['check_with_lxml']
else:
schema_class = ObservedXMLSchema11 if test_args.inspect else XMLSchema11
check_with_lxml = False
test_class = test_class_builder(test_file, test_args, test_num, schema_class, check_with_lxml)
test_classes[test_class.__name__] = test_class
logger.debug("Add XSD %s test class %r.", test_args.version, test_class.__name__)
if line_buffer:
raise ValueError("Not completed line continuation at the end!")
return test_classes

View File

@ -12,18 +12,14 @@
"""
This module runs tests concerning the building of XSD schemas with the 'xmlschema' package.
"""
from __future__ import print_function, unicode_literals
import unittest
import os
import sys
import pickle
import time
import warnings
try:
# noinspection PyPackageRequirements
import lxml.etree as _lxml_etree
except ImportError:
_lxml_etree = None
try:
import xmlschema
except ImportError:
@ -37,7 +33,9 @@ from xmlschema import XMLSchemaBase, XMLSchema, XMLSchemaParseError, XMLSchemaVa
from xmlschema.compat import PY3, unicode_type
from xmlschema.qnames import XSD_LIST, XSD_UNION
from xmlschema.tests import SKIP_REMOTE_TESTS, SchemaObserver, XMLSchemaTestCase
from xmlschema.etree import lxml_etree
from xmlschema.etree import defused_etree
from xmlschema.xpath import ElementPathContext
from xmlschema.validators import XsdValidator, XMLSchema11
@ -475,8 +473,17 @@ class TestXMLSchema11(TestXMLSchema10):
# self.assertTrue(schema.types['RestrictedDateTimeType'].is_valid('2000-01-01T12:00:00'))
def make_schema_test_class(test_file, test_args, test_num=0, schema_class=None):
def make_schema_test_class(test_file, test_args, test_num=0, schema_class=None, check_with_lxml=True):
"""
Creates a schema test class.
:param test_file: the schema test file path.
:param test_args: line arguments for test case.
:param test_num: a positive integer number associated with the test case.
:param schema_class: the schema class to use.
:param check_with_lxml: if `True` compare with lxml XMLSchema class, reporting anomalies. \
Works only for XSD 1.0 tests.
"""
xsd_file = test_file
if schema_class is None:
schema_class = XMLSchema
@ -528,6 +535,7 @@ def make_schema_test_class(test_file, test_args, test_num=0, schema_class=None):
return errors_
start_time = time.time()
if expected_warnings > 0:
with warnings.catch_warnings(record=True) as ctx:
warnings.simplefilter("always")
@ -536,7 +544,31 @@ def make_schema_test_class(test_file, test_args, test_num=0, schema_class=None):
else:
errors = check_schema()
# Checks errors completeness
# Check with lxml.etree.XMLSchema class
if check_with_lxml and lxml_etree is not None:
schema_time = time.time() - start_time
start_time = time.time()
lxs = lxml_etree.parse(xsd_file)
try:
lxml_etree.XMLSchema(lxs.getroot())
except lxml_etree.XMLSchemaParseError as err:
if not errors:
print("\nSchema error with lxml.etree.XMLSchema for file {!r} ({}): {}".format(
rel_path, class_name, unicode_type(err)
))
else:
if errors:
print("\nUnrecognized errors with lxml.etree.XMLSchema for file {!r} ({}): {}".format(
rel_path, class_name, '\n++++++\n'.join([unicode_type(e) for e in errors])
))
lxml_schema_time = time.time() - start_time
if lxml_schema_time >= schema_time:
print(
"\nSlower lxml.etree.XMLSchema ({:.3f}s VS {:.3f}s) with file {!r} ({})".format(
lxml_schema_time, schema_time, rel_path, class_name
))
# Check errors completeness
for e in errors:
error_string = unicode_type(e)
self.assertTrue(e.path, "Missing path for: %s" % error_string)
@ -558,16 +590,15 @@ def make_schema_test_class(test_file, test_args, test_num=0, schema_class=None):
rel_path = os.path.relpath(test_file)
class_name = 'Test{}_{:03}'.format(schema_class.__name__, test_num)
return type(
class_name, (XMLSchemaTestCase,),
{'test_schema_{0:03}_{1}'.format(test_num, rel_path): test_schema}
)
class_name, (XMLSchemaTestCase,), {
'test_schema_{0:03}_{1}'.format(test_num, rel_path): test_schema
})
if __name__ == '__main__':
from xmlschema.tests import print_test_header, get_testfiles, tests_factory
from xmlschema.tests import print_test_header, tests_factory
print_test_header()
testfiles = get_testfiles(os.path.dirname(os.path.abspath(__file__)))
schema_tests = tests_factory(make_schema_test_class, testfiles, suffix='xsd')
schema_tests = tests_factory(make_schema_test_class, 'xsd')
globals().update(schema_tests)
unittest.main()

View File

@ -40,7 +40,7 @@ from xmlschema.resources import fetch_namespaces
from xmlschema.tests import XMLSchemaTestCase
from xmlschema.etree import (
etree_element, etree_tostring, is_etree_element, etree_fromstring, etree_parse,
etree_elements_assert_equal, lxml_etree_parse, lxml_etree_element
etree_elements_assert_equal, lxml_etree, lxml_etree_parse, lxml_etree_element
)
from xmlschema.qnames import XSI_TYPE
from xmlschema.helpers import local_name
@ -291,7 +291,19 @@ def iter_nested_items(items, dict_class=dict, list_class=list):
yield items
def make_validator_test_class(test_file, test_args, test_num=0, schema_class=XMLSchema):
def make_validator_test_class(test_file, test_args, test_num=0, schema_class=None, check_with_lxml=False):
"""
Creates a validator test class.
:param test_file: the XML test file path.
:param test_args: line arguments for test case.
:param test_num: a positive integer number associated with the test case.
:param schema_class: the schema class to use.
:param check_with_lxml: if `True` compare with lxml XMLSchema class, reporting anomalies. \
Works only for XSD 1.0 tests.
"""
if schema_class is None:
schema_class = XMLSchema
# Extract schema test arguments
expected_errors = test_args.errors
@ -317,6 +329,8 @@ def make_validator_test_class(test_file, test_args, test_num=0, schema_class=XML
# Builds schema instance using 'lax' validation mode to accepts also schemas with not crashing errors.
source, _locations = xmlschema.fetch_schema_locations(xml_file, locations)
cls.schema = schema_class(source, validation='lax', locations=_locations, defuse=defuse)
if check_with_lxml and lxml_etree is not None:
cls.lxml_schema = lxml_etree.parse(source)
cls.errors = []
cls.chunks = []
@ -543,6 +557,19 @@ def make_validator_test_class(test_file, test_args, test_num=0, schema_class=XML
self.assertEqual(len(list(self.schema.iter_errors(xml_file))), expected_errors,
msg_template % "wrong number of errors (%d expected)" % expected_errors)
def check_lxml_validation(self):
try:
schema = lxml_etree.XMLSchema(self.lxml_schema.getroot())
except lxml_etree.XMLSchemaParseError:
print("\nSkip lxml.etree.XMLSchema validation test for {!r} ({})".
format(rel_path, TestValidator.__name__, ))
else:
xml_tree = lxml_etree_parse(xml_file)
if self.errors:
self.assertFalse(schema.validate(xml_tree))
else:
self.assertTrue(schema.validate(xml_tree))
def test_decoding_and_encoding(self):
self.check_decoding_with_element_tree()
@ -557,6 +584,8 @@ def make_validator_test_class(test_file, test_args, test_num=0, schema_class=XML
self.check_iter_errors()
self.check_validate_and_is_valid_api()
if check_with_lxml and lxml_etree is not None:
self.check_lxml_validation()
TestValidator.__name__ = TestValidator.__qualname__ = 'TestValidator{0:03}'.format(test_num)
return TestValidator
@ -1067,10 +1096,9 @@ class TestEncoding(XMLSchemaTestCase):
if __name__ == '__main__':
from xmlschema.tests import print_test_header, tests_factory, get_testfiles
from xmlschema.tests import print_test_header, tests_factory
print_test_header()
testfiles = get_testfiles(os.path.dirname(os.path.abspath(__file__)))
decoder_tests = tests_factory(make_validator_test_class, testfiles, 'xml')
decoder_tests = tests_factory(make_validator_test_class, 'xml')
globals().update(decoder_tests)
unittest.main()