Really aggregate lines from XFAIL and SUCCESS comments.
[third_party/subunit] / README
1
2   subunit: extensions to python unittest to get test results from subprocesses.
3   Copyright (C) 2005  Robert Collins <robertc@robertcollins.net>
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
20 Subunit
21 -------
22
23 Subunit is attempting to extend unittest with a clean and simple api to
24 run arbitrary external test suites and return the results to standard
25 python unittest.
26
27 Subunit comes in three parts:
28  * Protocol writers (clients)
29  * Protocol readers (servers)
30  * Filters
31  
32 The reader component acts as a test suite in the language that it is written
33 for. Currently subunit only provides a Python protocol reader.
34
35 Writers are used to output test results in subunit form. Writers are typically
36 test suite runners or test suite result objects in specific languages.
37 Currently subunit provides writers for Python, C, C++, and shell.
38
39 Filters provide translation filtering capabilities and can be used to modify a
40 stream on-the-fly. Currently subunit provides a single filter - tap2subunit.
41
42 The subunit code is organised at the top level by directories, for language
43 bindings, and additionally the filters directory for filters.
44
45 Using subunit in Python
46 -----------------------
47
48 1) As a runner for external tests (potentially in other languages)
49 2) As a process boundary for unittest TestCases to prevent them fiddling with
50    in-process state (i.e. singletons).
51 3) As a wrapper around a TestCase (or Suite) to run a group of tests
52    externally.
53
54 1) As a runner for external tests
55 =================================
56 This is supported on all platforms with python 2.4.
57 For each test script you want to run, declare a ExecTestCase with one
58 or more tests whose docstring defines the script to run:
59
60 import subunit
61 import unittest
62 class TestCProgram(subunit.ExecTestCase):
63
64     def test_script_one(self):
65         """./bin/script_one"""
66
67     def test_script_two(self):
68        """./bin/script_two"""
69
70 # Yes, the test prefix on the methods matters.
71 # Then run this in whatever normal way you would run python unittests.
72 # If you don't have a specific test runner, you can run it using the
73 # default one in unittest.py:
74
75 if __name__ == '__main__':
76      unittest.main()
77
78 2) As a process boundary for unittest TestCases
79 ===============================================
80 This is currently supported only on platforms
81 that support os.fork(), which allows us to
82 transparently introduce a process boundary
83 without affecting manual test parameterisation.
84 *** TODO explain in more detail and sketch out
85 *** a solution for win32
86 Just import subunit and derive your test cases
87 from subunit.IsolatedTestCase:
88
89 import subunit
90
91 class TestFoo(subunit.IsolatedTestCase):
92
93     def test_something_globally(self):
94         SomethingGlobal.do()
95         self.assertEqual(SomethingGlobal.value(), 3)
96         # the run() method of IsolatedTestCase will intercept the
97         # test execution, fork() python to create a new process,
98         # then run the test and report the results back to the parent
99         # process.
100
101 # you run this in the normal way you run test cases.
102
103 3) As a wrapper around a TestCase to run a group of tests externally.
104 =====================================================================
105
106 import subunit
107 import unittest
108
109 class TestFoo(unittest.TestCase):
110
111     def test_foo(self):
112         ...
113
114
115 def test_suite():
116     result = subunit.IsolatedTestSuite()
117     loader = unittest.TestLoader()
118     result.addTestCase(loader.loadTestsFromName(__name__))
119     return result
120
121 # you can test the result of test_suite() as follows (or in any normal python
122 # manner.
123 runner = unittest.TextTestRunner(verbosity=2)
124 runner.run(test_suite())
125 # enjoy.
126
127
128 Some requirements:
129   The shape of the external unittest should not need to be known a-priori.
130   After the test has run, tests should still exist as discrete objects, so that
131   anything taking a reference to them doesn't get 50 copies of the same object.
132
133 Sample subunit wire contents
134 ----------------------------
135
136 test: test foo works
137 success: test foo works.
138 test: tar a file.
139 failure: tar a file. [
140 ..
141  ]..  space is eaten.
142 foo.c:34 WARNING foo is not defined.
143 ]
144 a writeln to stdout
145
146 ===========
147 .F
148 a writeln to stdout
149
150 ========================
151 FAILURE: tar a file.
152 -------------------
153 ..
154 ]..  space is eaten.
155 foo.c:34 WARNING foo is not defined.
156 ========================
157
158
159 Subunit protocol description
160 ----------------------------
161 test|testing|test:|testing: test label
162 success|success:|successful|successful: test label
163 success|success:|successful|successful: test label [
164 ...
165 ]
166 failure test label
167 failure: test label
168 failure test label [
169 ...
170 ]
171 failure: test label [
172 ...
173 ]
174 error: test label
175 error: test label [
176 ]
177 skip[:] test label
178 skip[:] test label [
179 ]
180 xfail[:] test label
181 xfail[:] test label [
182 ]
183 unexpected output on stdout -> stdout.
184 exit w/0 or last test -> error
185
186
187 TODO:
188 def run:
189     do a fork,
190       this process runs server
191       child runs client and calls self.run() with a SubprocessTestResult