The Subunit Python test runner ``python -m subunit.run`` can now report the
[third_party/subunit] / runtests.py
1 #!/usr/bin/env python
2 # -*- Mode: python -*-
3 #
4 # Copyright (C) 2004 Canonical.com
5 #       Author:      Robert Collins <robert.collins@canonical.com>
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
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
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 #
21
22 import unittest
23 from subunit.tests.TestUtil import TestVisitor, TestSuite
24 import subunit
25 import sys
26 import os
27 import shutil
28 import logging
29
30 class ParameterisableTextTestRunner(unittest.TextTestRunner):
31     """I am a TextTestRunner whose result class is
32     parameterisable without further subclassing"""
33     def __init__(self, **args):
34         unittest.TextTestRunner.__init__(self, **args)
35         self._resultFactory=None
36     def resultFactory(self, *args):
37         """set or retrieve the result factory"""
38         if args:
39             self._resultFactory=args[0]
40             return self
41         if self._resultFactory is None:
42             self._resultFactory=unittest._TextTestResult
43         return self._resultFactory
44
45     def _makeResult(self):
46         return self.resultFactory()(self.stream, self.descriptions, self.verbosity)
47
48
49 class EarlyStoppingTextTestResult(unittest._TextTestResult):
50     """I am a TextTestResult that can optionally stop at the first failure
51     or error"""
52
53     def addError(self, test, err):
54         unittest._TextTestResult.addError(self, test, err)
55         if self.stopOnError():
56             self.stop()
57
58     def addFailure(self, test, err):
59         unittest._TextTestResult.addError(self, test, err)
60         if self.stopOnFailure():
61             self.stop()
62
63     def stopOnError(self, *args):
64         """should this result indicate an abort when an error occurs?
65         TODO parameterise this"""
66         return True
67
68     def stopOnFailure(self, *args):
69         """should this result indicate an abort when a failure error occurs?
70         TODO parameterise this"""
71         return True
72
73
74 def earlyStopFactory(*args, **kwargs):
75     """return a an early stopping text test result"""
76     result=EarlyStoppingTextTestResult(*args, **kwargs)
77     return result
78
79
80 class ShellTests(subunit.ExecTestCase):
81
82     def test_sourcing(self):
83         """./shell/tests/test_source_library.sh"""
84
85     def test_functions(self):
86         """./shell/tests/test_function_output.sh"""
87
88
89 def test_suite():
90     result = TestSuite()
91     result.addTest(subunit.test_suite())
92     result.addTest(ShellTests('test_sourcing'))
93     result.addTest(ShellTests('test_functions'))
94     return result
95
96
97 class filteringVisitor(TestVisitor):
98     """I accrue all the testCases I visit that pass a regexp filter on id
99     into my suite
100     """
101
102     def __init__(self, filter):
103         import re
104         TestVisitor.__init__(self)
105         self._suite=None
106         self.filter=re.compile(filter)
107
108     def suite(self):
109         """answer the suite we are building"""
110         if self._suite is None:
111             self._suite=TestSuite()
112         return self._suite
113
114     def visitCase(self, aCase):
115         if self.filter.match(aCase.id()):
116             self.suite().addTest(aCase)
117
118
119 def main(argv):
120     """To parameterise what tests are run, run this script like so:
121     python test_all.py REGEX
122     i.e.
123     python test_all.py .*Protocol.*
124     to run all tests with Protocol in their id."""
125     if len(argv) > 1:
126         pattern = argv[1]
127     else:
128         pattern = ".*"
129     visitor = filteringVisitor(pattern)
130     test_suite().visit(visitor)
131     runner = ParameterisableTextTestRunner(verbosity=2)
132     runner.resultFactory(unittest._TextTestResult)
133     if not runner.run(visitor.suite()).wasSuccessful():
134         return 1
135     return 0
136
137 if __name__ == '__main__':
138     sys.exit(main(sys.argv))