Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / src / nas,5.n2.os.2 / lib / python / html / python / lib / organizing-tests.html
CommitLineData
86530b38
AT
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<html>
3<head>
4<link rel="STYLESHEET" href="lib.css" type='text/css' />
5<link rel="SHORTCUT ICON" href="../icons/pyfav.png" type="image/png" />
6<link rel='start' href='../index.html' title='Python Documentation Index' />
7<link rel="first" href="lib.html" title='Python Library Reference' />
8<link rel='contents' href='contents.html' title="Contents" />
9<link rel='index' href='genindex.html' title='Index' />
10<link rel='last' href='about.html' title='About this document...' />
11<link rel='help' href='about.html' title='About this document...' />
12<link rel="next" href="legacy-unit-tests.html" />
13<link rel="prev" href="node164.html" />
14<link rel="parent" href="module-unittest.html" />
15<link rel="next" href="legacy-unit-tests.html" />
16<meta name='aesop' content='information' />
17<title>5.3.2 Organizing test code </title>
18</head>
19<body>
20<DIV CLASS="navigation">
21<div id='top-navigation-panel' xml:id='top-navigation-panel'>
22<table align="center" width="100%" cellpadding="0" cellspacing="2">
23<tr>
24<td class='online-navigation'><a rel="prev" title="5.3.1 Basic example"
25 href="node164.html"><img src='../icons/previous.png'
26 border='0' height='32' alt='Previous Page' width='32' /></A></td>
27<td class='online-navigation'><a rel="parent" title="5.3 unittest "
28 href="module-unittest.html"><img src='../icons/up.png'
29 border='0' height='32' alt='Up One Level' width='32' /></A></td>
30<td class='online-navigation'><a rel="next" title="5.3.3 Re-using old test"
31 href="legacy-unit-tests.html"><img src='../icons/next.png'
32 border='0' height='32' alt='Next Page' width='32' /></A></td>
33<td align="center" width="100%">Python Library Reference</td>
34<td class='online-navigation'><a rel="contents" title="Table of Contents"
35 href="contents.html"><img src='../icons/contents.png'
36 border='0' height='32' alt='Contents' width='32' /></A></td>
37<td class='online-navigation'><a href="modindex.html" title="Module Index"><img src='../icons/modules.png'
38 border='0' height='32' alt='Module Index' width='32' /></a></td>
39<td class='online-navigation'><a rel="index" title="Index"
40 href="genindex.html"><img src='../icons/index.png'
41 border='0' height='32' alt='Index' width='32' /></A></td>
42</tr></table>
43<div class='online-navigation'>
44<b class="navlabel">Previous:</b>
45<a class="sectref" rel="prev" href="node164.html">5.3.1 Basic example</A>
46<b class="navlabel">Up:</b>
47<a class="sectref" rel="parent" href="module-unittest.html">5.3 unittest </A>
48<b class="navlabel">Next:</b>
49<a class="sectref" rel="next" href="legacy-unit-tests.html">5.3.3 Re-using old test</A>
50</div>
51<hr /></div>
52</DIV>
53<!--End of Navigation Panel-->
54
55<H2><A NAME="SECTION007320000000000000000"></A><A NAME="organizing-tests"></A>
56<BR>
575.3.2 Organizing test code
58
59</H2>
60
61<P>
62The basic building blocks of unit testing are <i class="dfn">test cases</i> --
63single scenarios that must be set up and checked for correctness. In
64PyUnit, test cases are represented by instances of the
65<tt class="class">TestCase</tt> class in the <tt class="module"><a href="module-unittest.html">unittest</a></tt> module. To make
66your own test cases you must write subclasses of <tt class="class">TestCase</tt>, or
67use <tt class="class">FunctionTestCase</tt>.
68
69<P>
70An instance of a <tt class="class">TestCase</tt>-derived class is an object that can
71completely run a single test method, together with optional set-up
72and tidy-up code.
73
74<P>
75The testing code of a <tt class="class">TestCase</tt> instance should be entirely
76self contained, such that it can be run either in isolation or in
77arbitrary combination with any number of other test cases.
78
79<P>
80The simplest test case subclass will simply override the
81<tt class="method">runTest()</tt> method in order to perform specific testing code:
82
83<P>
84<div class="verbatim"><pre>
85import unittest
86
87class DefaultWidgetSizeTestCase(unittest.TestCase):
88 def runTest(self):
89 widget = Widget("The widget")
90 self.failUnless(widget.size() == (50,50), 'incorrect default size')
91</pre></div>
92
93<P>
94Note that in order to test something, we use the one of the
95<tt class="method">assert*()</tt> or <tt class="method">fail*()</tt> methods provided by the
96<tt class="class">TestCase</tt> base class. If the test fails when the test case
97runs, an exception will be raised, and the testing framework will
98identify the test case as a <i class="dfn">failure</i>. Other exceptions that do
99not arise from checks made through the <tt class="method">assert*()</tt> and
100<tt class="method">fail*()</tt> methods are identified by the testing framework as
101dfnerrors.
102
103<P>
104The way to run a test case will be described later. For now, note
105that to construct an instance of such a test case, we call its
106constructor without arguments:
107
108<P>
109<div class="verbatim"><pre>
110testCase = DefaultWidgetSizeTestCase()
111</pre></div>
112
113<P>
114Now, such test cases can be numerous, and their set-up can be
115repetitive. In the above case, constructing a ``Widget'' in each of
116100 Widget test case subclasses would mean unsightly duplication.
117
118<P>
119Luckily, we can factor out such set-up code by implementing a method
120called <tt class="method">setUp()</tt>, which the testing framework will
121automatically call for us when we run the test:
122
123<P>
124<div class="verbatim"><pre>
125import unittest
126
127class SimpleWidgetTestCase(unittest.TestCase):
128 def setUp(self):
129 self.widget = Widget("The widget")
130
131class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
132 def runTest(self):
133 self.failUnless(self.widget.size() == (50,50),
134 'incorrect default size')
135
136class WidgetResizeTestCase(SimpleWidgetTestCase):
137 def runTest(self):
138 self.widget.resize(100,150)
139 self.failUnless(self.widget.size() == (100,150),
140 'wrong size after resize')
141</pre></div>
142
143<P>
144If the <tt class="method">setUp()</tt> method raises an exception while the test is
145running, the framework will consider the test to have suffered an
146error, and the <tt class="method">runTest()</tt> method will not be executed.
147
148<P>
149Similarly, we can provide a <tt class="method">tearDown()</tt> method that tidies up
150after the <tt class="method">runTest()</tt> method has been run:
151
152<P>
153<div class="verbatim"><pre>
154import unittest
155
156class SimpleWidgetTestCase(unittest.TestCase):
157 def setUp(self):
158 self.widget = Widget("The widget")
159
160 def tearDown(self):
161 self.widget.dispose()
162 self.widget = None
163</pre></div>
164
165<P>
166If <tt class="method">setUp()</tt> succeeded, the <tt class="method">tearDown()</tt> method will be
167run regardless of whether or not <tt class="method">runTest()</tt> succeeded.
168
169<P>
170Such a working environment for the testing code is called a
171<i class="dfn">fixture</i>.
172
173<P>
174Often, many small test cases will use the same fixture. In this case,
175we would end up subclassing <tt class="class">SimpleWidgetTestCase</tt> into many
176small one-method classes such as
177<tt class="class">DefaultWidgetSizeTestCase</tt>. This is time-consuming and
178discouraging, so in the same vein as JUnit, PyUnit provides a simpler
179mechanism:
180
181<P>
182<div class="verbatim"><pre>
183import unittest
184
185class WidgetTestCase(unittest.TestCase):
186 def setUp(self):
187 self.widget = Widget("The widget")
188
189 def tearDown(self):
190 self.widget.dispose()
191 self.widget = None
192
193 def testDefaultSize(self):
194 self.failUnless(self.widget.size() == (50,50),
195 'incorrect default size')
196
197 def testResize(self):
198 self.widget.resize(100,150)
199 self.failUnless(self.widget.size() == (100,150),
200 'wrong size after resize')
201</pre></div>
202
203<P>
204Here we have not provided a <tt class="method">runTest()</tt> method, but have
205instead provided two different test methods. Class instances will now
206each run one of the <tt class="method">test*()</tt> methods, with <code>self.widget</code>
207created and destroyed separately for each instance. When creating an
208instance we must specify the test method it is to run. We do this by
209passing the method name in the constructor:
210
211<P>
212<div class="verbatim"><pre>
213defaultSizeTestCase = WidgetTestCase("testDefaultSize")
214resizeTestCase = WidgetTestCase("testResize")
215</pre></div>
216
217<P>
218Test case instances are grouped together according to the features
219they test. PyUnit provides a mechanism for this: the <tt class="class">test
220suite</tt>, represented by the class <tt class="class">TestSuite</tt> in the
221<tt class="module"><a href="module-unittest.html">unittest</a></tt> module:
222
223<P>
224<div class="verbatim"><pre>
225widgetTestSuite = unittest.TestSuite()
226widgetTestSuite.addTest(WidgetTestCase("testDefaultSize"))
227widgetTestSuite.addTest(WidgetTestCase("testResize"))
228</pre></div>
229
230<P>
231For the ease of running tests, as we will see later, it is a good
232idea to provide in each test module a callable object that returns a
233pre-built test suite:
234
235<P>
236<div class="verbatim"><pre>
237def suite():
238 suite = unittest.TestSuite()
239 suite.addTest(WidgetTestCase("testDefaultSize"))
240 suite.addTest(WidgetTestCase("testResize"))
241 return suite
242</pre></div>
243
244<P>
245or even:
246
247<P>
248<div class="verbatim"><pre>
249class WidgetTestSuite(unittest.TestSuite):
250 def __init__(self):
251 unittest.TestSuite.__init__(self,map(WidgetTestCase,
252 ("testDefaultSize",
253 "testResize")))
254</pre></div>
255
256<P>
257(The latter is admittedly not for the faint-hearted!)
258
259<P>
260Since it is a common pattern to create a <tt class="class">TestCase</tt> subclass
261with many similarly named test functions, there is a convenience
262function called <tt class="function">makeSuite()</tt> that constructs a test suite
263that comprises all of the test cases in a test case class:
264
265<P>
266<div class="verbatim"><pre>
267suite = unittest.makeSuite(WidgetTestCase)
268</pre></div>
269
270<P>
271Note that when using the <tt class="function">makeSuite()</tt> function, the order in
272which the various test cases will be run by the test suite is the
273order determined by sorting the test function names using the
274<tt class="function">cmp()</tt> built-in function.
275
276<P>
277Often it is desirable to group suites of test cases together, so as to
278run tests for the whole system at once. This is easy, since
279<tt class="class">TestSuite</tt> instances can be added to a <tt class="class">TestSuite</tt> just
280as <tt class="class">TestCase</tt> instances can be added to a <tt class="class">TestSuite</tt>:
281
282<P>
283<div class="verbatim"><pre>
284suite1 = module1.TheTestSuite()
285suite2 = module2.TheTestSuite()
286alltests = unittest.TestSuite((suite1, suite2))
287</pre></div>
288
289<P>
290You can place the definitions of test cases and test suites in the
291same modules as the code they are to test (such as <span class="file">widget.py</span>),
292but there are several advantages to placing the test code in a
293separate module, such as <span class="file">widgettests.py</span>:
294
295<P>
296
297<UL>
298<LI>The test module can be run standalone from the command line.
299</LI>
300<LI>The test code can more easily be separated from shipped code.
301</LI>
302<LI>There is less temptation to change test code to fit the code
303 it tests without a good reason.
304</LI>
305<LI>Test code should be modified much less frequently than the
306 code it tests.
307</LI>
308<LI>Tested code can be refactored more easily.
309</LI>
310<LI>Tests for modules written in C must be in separate modules
311 anyway, so why not be consistent?
312</LI>
313<LI>If the testing strategy changes, there is no need to change
314 the source code.
315</LI>
316</UL>
317
318<P>
319
320<DIV CLASS="navigation">
321<div class='online-navigation'>
322<p></p><hr />
323<table align="center" width="100%" cellpadding="0" cellspacing="2">
324<tr>
325<td class='online-navigation'><a rel="prev" title="5.3.1 Basic example"
326 href="node164.html"><img src='../icons/previous.png'
327 border='0' height='32' alt='Previous Page' width='32' /></A></td>
328<td class='online-navigation'><a rel="parent" title="5.3 unittest "
329 href="module-unittest.html"><img src='../icons/up.png'
330 border='0' height='32' alt='Up One Level' width='32' /></A></td>
331<td class='online-navigation'><a rel="next" title="5.3.3 Re-using old test"
332 href="legacy-unit-tests.html"><img src='../icons/next.png'
333 border='0' height='32' alt='Next Page' width='32' /></A></td>
334<td align="center" width="100%">Python Library Reference</td>
335<td class='online-navigation'><a rel="contents" title="Table of Contents"
336 href="contents.html"><img src='../icons/contents.png'
337 border='0' height='32' alt='Contents' width='32' /></A></td>
338<td class='online-navigation'><a href="modindex.html" title="Module Index"><img src='../icons/modules.png'
339 border='0' height='32' alt='Module Index' width='32' /></a></td>
340<td class='online-navigation'><a rel="index" title="Index"
341 href="genindex.html"><img src='../icons/index.png'
342 border='0' height='32' alt='Index' width='32' /></A></td>
343</tr></table>
344<div class='online-navigation'>
345<b class="navlabel">Previous:</b>
346<a class="sectref" rel="prev" href="node164.html">5.3.1 Basic example</A>
347<b class="navlabel">Up:</b>
348<a class="sectref" rel="parent" href="module-unittest.html">5.3 unittest </A>
349<b class="navlabel">Next:</b>
350<a class="sectref" rel="next" href="legacy-unit-tests.html">5.3.3 Re-using old test</A>
351</div>
352</div>
353<hr />
354<span class="release-info">Release 2.4.2, documentation updated on 28 September 2005.</span>
355</DIV>
356<!--End of Navigation Panel-->
357<ADDRESS>
358See <i><a href="about.html">About this document...</a></i> for information on suggesting changes.
359</ADDRESS>
360</BODY>
361</HTML>