File: run_tests.py

package info (click to toggle)
python-css-parser 1.0.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,236 kB
  • sloc: python: 20,518; sh: 11; makefile: 7
file content (120 lines) | stat: -rwxr-xr-x 3,395 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python3
# vim:fileencoding=utf-8
# License: LGPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import importlib
import logging
import os
import sys
import unittest

self_path = os.path.abspath(__file__)
base = os.path.dirname(self_path)


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, test_ok):
    ans = unittest.TestSuite()
    added = set()
    for test in itertests(suite):
        if test_ok(test) and test not in added:
            ans.addTest(test)
            added.add(test)
    return ans


def filter_tests_by_name(suite, name):
    if not name.startswith('test_'):
        name = 'test_' + name
    if name.endswith('_'):
        def q(test):
            return test._testMethodName.startswith(name)
    else:
        def q(test):
            return test._testMethodName == name

    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 find_tests():
    suites = []
    for f in os.listdir(os.path.join(base, 'css_parser_tests')):
        n, ext = os.path.splitext(f)
        if ext == '.py' and n.startswith('test_'):
            m = importlib.import_module('css_parser_tests.' + n)
            suite = unittest.defaultTestLoader.loadTestsFromModule(m)
            suites.append(suite)
    return unittest.TestSuite(suites)


def run_tests(test_names=()):
    sys.path = [base, os.path.join(base, 'src')] + sys.path
    import css_parser
    tests = find_tests()
    suites = []
    for name in test_names:
        if name.endswith('.'):
            module_name = name[:-1]
            if not module_name.startswith('test_'):
                module_name = 'test_' + module_name
            suites.append(filter_tests_by_module(tests, module_name))
        else:
            suites.append(filter_tests_by_name(tests, name))
    tests = unittest.TestSuite(suites) if suites else tests

    r = unittest.TextTestRunner
    css_parser.log.setLevel(logging.CRITICAL)
    result = r().run(tests)

    if not result.wasSuccessful():
        raise SystemExit(1)


def main():
    import argparse
    parser = argparse.ArgumentParser(
        description='''\
Run the specified tests, or all tests if none are specified. Tests
can be specified as either the test method name (without the leading test_)
or a module name with a trailing period.
''')
    parser.add_argument(
        'test_name',
        nargs='*',
        help=(
            'Test name (either a method name or a module name with a trailing period)'
            '. Note that if the name ends with a trailing underscore all tests methods'
            ' whose names start with the specified name are run.'
        )
    )
    args = parser.parse_args()
    run_tests(args.test_name)


if __name__ == '__main__':
    main()