diff --git a/setup/test.py b/setup/test.py index dbd018f7ba..c760de78dc 100644 --- a/setup/test.py +++ b/setup/test.py @@ -60,26 +60,6 @@ def find_tests(which_tests=None): tests = unittest.TestSuite(ans) return tests -def itertests(suite): - stack = [suite] - while stack: - suite = stack.pop() - for test in suite: - if isinstance(test, unittest.TestSuite): - stack.append(test) - continue - if test.__class__.__name__ == 'ModuleImportFailure': - raise Exception('Failed to import a test module: %s' % test) - yield test - -def filter_tests(suite, *names): - names = {x if x.startswith('test_') else 'test_' + x for x in names} - tests = [] - for test in itertests(suite): - if test._testMethodName in names: - tests.append(test) - return unittest.TestSuite(tests) - class Test(Command): def add_options(self, parser): @@ -92,8 +72,8 @@ class Test(Command): ' can be run by specifying the name "something".') def run(self, opts): - r = unittest.TextTestRunner + from calibre.utils.run_tests import run_cli, filter_tests_by_name tests = find_tests(which_tests=frozenset(opts.test_module)) if opts.test_name: - tests = filter_tests(tests, *opts.test_name) - r(verbosity=opts.test_verbosity).run(tests) + tests = filter_tests_by_name(tests, *opts.test_name) + run_cli(tests, verbosity=opts.test_verbosity) diff --git a/src/calibre/db/tests/main.py b/src/calibre/db/tests/main.py index ad45222038..77aa621a57 100644 --- a/src/calibre/db/tests/main.py +++ b/src/calibre/db/tests/main.py @@ -7,102 +7,16 @@ __license__ = 'GPL v3' __copyright__ = '2013, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import unittest, os, argparse, time, functools, importlib - - -def no_endl(f): - @functools.wraps(f) - def func(*args, **kwargs): - self = f.__self__ - orig = self.stream.writeln - self.stream.writeln = self.stream.write - try: - return f(*args, **kwargs) - finally: - self.stream.writeln = orig - return func - -class TestResult(unittest.TextTestResult): - - def __init__(self, *args, **kwargs): - super(TestResult, self).__init__(*args, **kwargs) - self.start_time = {} - for x in ('Success', 'Error', 'Failure', 'Skip', 'ExpectedFailure', 'UnexpectedSuccess'): - x = 'add' + x - setattr(self, x, no_endl(getattr(self, x))) - self.times = {} - - def startTest(self, test): - self.start_time[test] = time.time() - return super(TestResult, self).startTest(test) - - def stopTest(self, test): - orig = self.stream.writeln - self.stream.writeln = self.stream.write - super(TestResult, self).stopTest(test) - elapsed = time.time() - elapsed -= self.start_time.get(test, elapsed) - self.times[test] = elapsed - self.stream.writeln = orig - self.stream.writeln(' [%.1g s]' % elapsed) - - def stopTestRun(self): - super(TestResult, self).stopTestRun() - if self.wasSuccessful(): - tests = sorted(self.times, key=self.times.get, reverse=True) - slowest = ['%s [%g s]' % (t.id(), self.times[t]) for t in tests[:3]] - if len(slowest) > 1: - self.stream.writeln('\nSlowest tests: %s' % ' '.join(slowest)) +import os +from calibre.utils.run_tests import find_tests_in_dir, run_tests def find_tests(): base = os.path.dirname(os.path.abspath(__file__)) - suits = [] - for x in os.listdir(base): - if x.endswith('.py') and x != 'main.py': - m = importlib.import_module('calibre.db.tests.' + x.partition('.')[0]) - suits.append(unittest.defaultTestLoader.loadTestsFromModule(m)) - return unittest.TestSuite(suits) - -def run_tests(find_tests=find_tests): - parser = argparse.ArgumentParser() - parser.add_argument('name', nargs='?', default=None, - help='The name of the test to run, for e.g. writing.WritingTest.many_many_basic or .many_many_basic for a shortcut') - args = parser.parse_args() - if args.name and args.name.startswith('.'): - tests = find_tests() - q = args.name[1:] - if not q.startswith('test_'): - q = 'test_' + q - ans = None - try: - for suite in tests: - for test in suite._tests: - if test.__class__.__name__ == 'ModuleImportFailure': - raise Exception('Failed to import a test module: %s' % test) - for s in test: - if s._testMethodName == q: - ans = s - raise StopIteration() - except StopIteration: - pass - if ans is None: - print ('No test named %s found' % args.name) - raise SystemExit(1) - tests = ans - else: - tests = unittest.defaultTestLoader.loadTestsFromName(args.name) if args.name else find_tests() - r = unittest.TextTestRunner - r.resultclass = TestResult - r(verbosity=4).run(tests) + return find_tests_in_dir(base) if __name__ == '__main__': try: import init_calibre # noqa except ImportError: pass - from calibre.utils.config_base import reset_tweaks_to_default - from calibre.ebooks.metadata.book.base import reset_field_metadata - reset_tweaks_to_default() - reset_field_metadata() - run_tests() - + run_tests(find_tests) diff --git a/src/calibre/ebooks/oeb/polish/tests/main.py b/src/calibre/ebooks/oeb/polish/tests/main.py index baf50959d4..62d841a9e0 100644 --- a/src/calibre/ebooks/oeb/polish/tests/main.py +++ b/src/calibre/ebooks/oeb/polish/tests/main.py @@ -6,25 +6,16 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2013, Kovid Goyal ' - -import os, unittest, importlib +import os +from calibre.utils.run_tests import find_tests_in_dir, run_tests def find_tests(): base = os.path.dirname(os.path.abspath(__file__)) - suits = [] - for x in os.listdir(base): - if x.endswith('.py') and x != 'main.py': - m = importlib.import_module('calibre.ebooks.oeb.polish.tests.' + x.partition('.')[0]) - suits.append(unittest.defaultTestLoader.loadTestsFromModule(m)) - return unittest.TestSuite(suits) + return find_tests_in_dir(base) if __name__ == '__main__': try: import init_calibre # noqa except ImportError: pass - - from calibre.db.tests.main import run_tests - run_tests(find_tests=find_tests) - - + run_tests(find_tests) diff --git a/src/calibre/srv/tests/main.py b/src/calibre/srv/tests/main.py index 59644ce589..f0be245ae4 100644 --- a/src/calibre/srv/tests/main.py +++ b/src/calibre/srv/tests/main.py @@ -6,101 +6,16 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2015, Kovid Goyal ' -import unittest, os, argparse, time, functools, importlib - - -def no_endl(f): - @functools.wraps(f) - def func(*args, **kwargs): - self = f.__self__ - orig = self.stream.writeln - self.stream.writeln = self.stream.write - try: - return f(*args, **kwargs) - finally: - self.stream.writeln = orig - return func - -class TestResult(unittest.TextTestResult): - - def __init__(self, *args, **kwargs): - super(TestResult, self).__init__(*args, **kwargs) - self.start_time = {} - for x in ('Success', 'Error', 'Failure', 'Skip', 'ExpectedFailure', 'UnexpectedSuccess'): - x = 'add' + x - setattr(self, x, no_endl(getattr(self, x))) - self.times = {} - - def startTest(self, test): - self.start_time[test] = time.time() - return super(TestResult, self).startTest(test) - - def stopTest(self, test): - orig = self.stream.writeln - self.stream.writeln = self.stream.write - super(TestResult, self).stopTest(test) - elapsed = time.time() - elapsed -= self.start_time.get(test, elapsed) - self.times[test] = elapsed - self.stream.writeln = orig - self.stream.writeln(' [%.1g s]' % elapsed) - - def stopTestRun(self): - super(TestResult, self).stopTestRun() - if self.wasSuccessful(): - tests = sorted(self.times, key=self.times.get, reverse=True) - slowest = ['%s [%g s]' % (t.id(), self.times[t]) for t in tests[:3]] - if len(slowest) > 1: - self.stream.writeln('\nSlowest tests: %s' % ' '.join(slowest)) +import os +from calibre.utils.run_tests import find_tests_in_dir, run_tests def find_tests(): base = os.path.dirname(os.path.abspath(__file__)) - suits = [] - for x in os.listdir(base): - if x.endswith('.py') and x != 'main.py': - m = importlib.import_module('calibre.srv.tests.' + x.partition('.')[0]) - suits.append(unittest.defaultTestLoader.loadTestsFromModule(m)) - return unittest.TestSuite(suits) - -def run_tests(find_tests=find_tests): - parser = argparse.ArgumentParser() - parser.add_argument('name', nargs='?', default=None, - help='The name of the test to run, for e.g. writing.WritingTest.many_many_basic or .many_many_basic for a shortcut') - args = parser.parse_args() - if args.name and args.name.startswith('.'): - tests = find_tests() - q = args.name[1:] - if not q.startswith('test_'): - q = 'test_' + q - ans = None - try: - for suite in tests: - for test in suite._tests: - if test.__class__.__name__ == 'ModuleImportFailure': - raise Exception('Failed to import a test module: %s' % test) - for s in test: - if s._testMethodName == q: - ans = s - raise StopIteration() - except StopIteration: - pass - if ans is None: - print ('No test named %s found' % args.name) - raise SystemExit(1) - tests = ans - else: - tests = unittest.defaultTestLoader.loadTestsFromName(args.name) if args.name else find_tests() - r = unittest.TextTestRunner - r.resultclass = TestResult - r(verbosity=4).run(tests) + return find_tests_in_dir(base) if __name__ == '__main__': try: import init_calibre # noqa except ImportError: pass - from calibre.utils.config_base import reset_tweaks_to_default - from calibre.ebooks.metadata.book.base import reset_field_metadata - reset_tweaks_to_default() - reset_field_metadata() - run_tests() + run_tests(find_tests) diff --git a/src/calibre/utils/run_tests.py b/src/calibre/utils/run_tests.py new file mode 100644 index 0000000000..e4b9a073e4 --- /dev/null +++ b/src/calibre/utils/run_tests.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2016, Kovid Goyal + +from __future__ import (unicode_literals, division, absolute_import, + print_function) +import unittest, functools, time, os, importlib + +def no_endl(f): + @functools.wraps(f) + def func(*args, **kwargs): + self = f.__self__ + orig = self.stream.writeln + self.stream.writeln = self.stream.write + try: + return f(*args, **kwargs) + finally: + self.stream.writeln = orig + return func + +class TestResult(unittest.TextTestResult): + + def __init__(self, *args, **kwargs): + super(TestResult, self).__init__(*args, **kwargs) + self.start_time = {} + for x in ('Success', 'Error', 'Failure', 'Skip', 'ExpectedFailure', 'UnexpectedSuccess'): + x = 'add' + x + setattr(self, x, no_endl(getattr(self, x))) + self.times = {} + + def startTest(self, test): + self.start_time[test] = time.time() + return super(TestResult, self).startTest(test) + + def stopTest(self, test): + orig = self.stream.writeln + self.stream.writeln = self.stream.write + super(TestResult, self).stopTest(test) + elapsed = time.time() + elapsed -= self.start_time.get(test, elapsed) + self.times[test] = elapsed + self.stream.writeln = orig + self.stream.writeln(' [%.1g s]' % elapsed) + + def stopTestRun(self): + super(TestResult, self).stopTestRun() + if self.wasSuccessful(): + tests = sorted(self.times, key=self.times.get, reverse=True) + slowest = ['%s [%g s]' % (t.id(), self.times[t]) for t in tests[:3]] + if len(slowest) > 1: + self.stream.writeln('\nSlowest tests: %s' % ' '.join(slowest)) + +def find_tests_in_dir(path, excludes=('main.py',)): + d = os.path.dirname + base = d(d(d(os.path.abspath(__file__)))) + package = os.path.relpath(path, base).replace(os.sep, '/').replace('/', '.') + suits = [] + for x in os.listdir(path): + if x.endswith('.py') and x not in excludes: + m = importlib.import_module(package + '.' + x.partition('.')[0]) + suits.append(unittest.defaultTestLoader.loadTestsFromModule(m)) + return unittest.TestSuite(suits) + +def itertests(suite): + stack = [suite] + while stack: + suite = stack.pop() + for test in suite: + if isinstance(test, unittest.TestSuite): + stack.append(test) + continue + if test.__class__.__name__ == 'ModuleImportFailure': + raise Exception('Failed to import a test module: %s' % test) + yield test + +def init_env(): + from calibre.utils.config_base import reset_tweaks_to_default + from calibre.ebooks.metadata.book.base import reset_field_metadata + reset_tweaks_to_default() + reset_field_metadata() + +def filter_tests(suite, test_ok): + ans = unittest.TestSuite() + for test in itertests(suite): + if test_ok(test): + ans.addTest(test) + return ans + +def filter_tests_by_name(suite, *names): + names = {x if x.startswith('test_') else 'test_' + x for x in names} + + def q(test): + return test._testMethodName in names + return filter_tests(suite, q) + +def filter_tests_by_module(suite, *names): + names = frozenset(names) + def q(test): + m = test.__class__.__module__.rpartition('.')[-1] + return m in names + return filter_tests(suite, q) + +def run_tests(find_tests, verbosity=4, result_class=TestResult): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('name', nargs='?', default=None, + help='The name of the test to run, for e.g. writing.WritingTest.many_many_basic or .many_many_basic for a shortcut') + args = parser.parse_args() + tests = find_tests() + if args.name: + if args.name.startswith('.'): + tests = filter_tests_by_name(tests, args.name[1:]) + else: + tests = filter_tests_by_module(tests, args.name) + if not tests._tests: + raise SystemExit('No test named %s found' % args.name) + run_cli(tests, verbosity, result_class) + +def run_cli(suite, verbosity=4, result_class=TestResult): + r = unittest.TextTestRunner + r.resultclass = result_class or unittest.TestResult + init_env() + r(verbosity=verbosity).run(suite)