~ctf/checkbox/bug811177

1 by David Murphy
Initial release
1
#!/usr/bin/env python
226 by Marc Tardif
Updated copyright information.
2
#
306 by Marc Tardif
Renamed hwtest to checkbox.
3
# This file is part of Checkbox.
226 by Marc Tardif
Updated copyright information.
4
#
471 by Marc Tardif
Fixed source headers in accordance with Canonical licensing policy.
5
# Copyright 2008 Canonical Ltd.
6
#
306 by Marc Tardif
Renamed hwtest to checkbox.
7
# Checkbox is free software: you can redistribute it and/or modify
226 by Marc Tardif
Updated copyright information.
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
306 by Marc Tardif
Renamed hwtest to checkbox.
12
# Checkbox is distributed in the hope that it will be useful,
226 by Marc Tardif
Updated copyright information.
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
306 by Marc Tardif
Renamed hwtest to checkbox.
18
# along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
226 by Marc Tardif
Updated copyright information.
19
#
1 by David Murphy
Initial release
20
import optparse
21
22
import os
23
import sys
395 by Marc Tardif
Using posixpath instead of os.path.
24
import posixpath
1 by David Murphy
Initial release
25
395 by Marc Tardif
Using posixpath instead of os.path.
26
lib_dir = posixpath.abspath(posixpath.dirname(__file__))
1 by David Murphy
Initial release
27
sys.path.insert(0, lib_dir)
28
46.1.7 by Marc Tardif
Moved tests to better location.
29
30
def find_tests(testpaths=()):
31
    """Find all test paths, or test paths contained in the provided sequence.
32
33
    @param testpaths: If provided, only tests in the given sequence will
34
                      be considered.  If not provided, all tests are
35
                      considered.
36
    @return: (unittests, doctests) tuple, with lists of unittests and
37
             doctests found, respectively.
38
    """
395 by Marc Tardif
Using posixpath instead of os.path.
39
    topdir = posixpath.abspath(posixpath.dirname(__file__))
46.1.7 by Marc Tardif
Moved tests to better location.
40
    testpaths = set(testpaths)
41
    unittests = []
42
    doctests = []
43
    for root, dirnames, filenames in os.walk(topdir):
44
        for filename in filenames:
395 by Marc Tardif
Using posixpath instead of os.path.
45
            filepath = posixpath.join(root, filename)
46.1.7 by Marc Tardif
Moved tests to better location.
46
            relpath = filepath[len(topdir)+1:]
47
48
            if (filename == "__init__.py"
49
               or filename.endswith(".pyc")
50
               or "/tests/" not in relpath):
51
                # Skip non-tests.
52
                continue
53
54
            if testpaths:
55
                # Skip any tests not in testpaths.
56
                for testpath in testpaths:
57
                    if relpath.startswith(testpath):
58
                        break
59
                else:
60
                    continue
61
62
            if filename.endswith(".py"):
63
                unittests.append(relpath)
64
            elif filename.endswith(".txt"):
65
                doctests.append(relpath)
66
67
    return unittests, doctests
68
69
def parse_sys_argv():
70
    """Extract any arguments not starting with '-' from sys.argv."""
71
    testpaths = []
72
    for i in range(len(sys.argv)-1,0,-1):
73
        arg = sys.argv[i]
74
        if not arg.startswith("-"):
75
            testpaths.append(arg)
76
            del sys.argv[i]
77
    return testpaths
1 by David Murphy
Initial release
78
414 by Marc Tardif
Added subunit to the test suite.
79
def test_with_subunit(options):
80
    import unittest
81
    import subunit
82
83
    runner = unittest.TextTestRunner()
84
    if options.verbose:
85
        runner.verbosity = 2
86
87
    result = subunit.IsolatedTestSuite()
88
    loader = unittest.TestLoader()
89
    unittests, doctests = find_tests(options.args)
90
91
    if unittests:
92
        for relpath in unittests:
93
            modpath = relpath.replace('/', '.')[:-3]
94
            module = __import__(modpath, None, None, [""])
95
            tests = loader.loadTestsFromModule(module)
96
            result.addTests(tests)
97
98
        runner.run(result)
99
100
    return 0
101
102
def test_with_unittest(options):
1 by David Murphy
Initial release
103
    import unittest
104
    import doctest
105
106
    runner = unittest.TextTestRunner()
414 by Marc Tardif
Added subunit to the test suite.
107
    if options.verbose:
1 by David Murphy
Initial release
108
        runner.verbosity = 2
227 by Marc Tardif
Removed pesky trailing spaces.
109
1 by David Murphy
Initial release
110
    loader = unittest.TestLoader()
414 by Marc Tardif
Added subunit to the test suite.
111
    unittests, doctests = find_tests(options.args)
1 by David Murphy
Initial release
112
113
    class Summary:
114
        def __init__(self):
115
            self.total_failures = 0
116
            self.total_errors = 0
117
            self.total_tests = 0
118
        def __call__(self, tests, failures, errors):
119
            self.total_tests += tests
120
            self.total_failures += failures
121
            self.total_errors += errors
122
            print "(tests=%d, failures=%d, errors=%d)" % \
123
                  (tests, failures, errors)
124
125
    unittest_summary = Summary()
126
    doctest_summary = Summary()
127
128
    if unittests:
129
        print "Running unittests..."
130
        for relpath in unittests:
131
            print "[%s]" % relpath
132
            modpath = relpath.replace('/', '.')[:-3]
133
            module = __import__(modpath, None, None, [""])
134
            test = loader.loadTestsFromModule(module)
135
            result = runner.run(test)
136
            unittest_summary(test.countTestCases(),
137
                             len(result.failures), len(result.errors))
138
            print
139
140
    if doctests:
141
        print "Running doctests..."
46.1.7 by Marc Tardif
Moved tests to better location.
142
        doctest_flags = doctest.ELLIPSIS
1 by David Murphy
Initial release
143
        for relpath in doctests:
144
            print "[%s]" % relpath
145
            failures, total = doctest.testfile(relpath,
146
                                               optionflags=doctest_flags)
147
            doctest_summary(total, failures, 0)
148
            print
149
150
    print "Total test cases: %d" % unittest_summary.total_tests
151
    print "Total doctests: %d" % doctest_summary.total_tests
152
    print "Total failures: %d" % (unittest_summary.total_failures +
153
                                  doctest_summary.total_failures)
154
    print "Total errors: %d" % (unittest_summary.total_errors +
155
                                doctest_summary.total_errors)
156
157
    failed = bool(unittest_summary.total_failures or
158
                  unittest_summary.total_errors or
159
                  doctest_summary.total_failures or
160
                  doctest_summary.total_errors)
161
414 by Marc Tardif
Added subunit to the test suite.
162
    return failed
1 by David Murphy
Initial release
163
164
if __name__ == "__main__":
414 by Marc Tardif
Added subunit to the test suite.
165
    usage = "test [options] [<test filename>, ...]"
166
167
    parser = optparse.OptionParser(usage=usage)
168
    parser.add_option('--verbose', action='store_true')
169
    opts, args = parser.parse_args()
170
    opts.args = args
171
172
    runner = os.environ.get("CHECKBOX_TEST_RUNNER", "unittest")
1 by David Murphy
Initial release
173
    runner_func = globals().get("test_with_%s" % runner.replace(".", "_"))
174
    if not runner_func:
175
        sys.exit("Test runner not found: %s" % runner)
414 by Marc Tardif
Added subunit to the test suite.
176
177
    sys.exit(runner_func(opts))
1 by David Murphy
Initial release
178
179
# vim:ts=4:sw=4:et