1 |
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
2 |
<html> |
3 |
<head> |
4 |
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
5 |
<meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; I; SunOS 5.7 sun4u) [Netscape]"> |
6 |
<meta name="CREATED" content="20010209;11071700"> |
7 |
<meta name="CHANGEDBY" content="Rice Ed"> |
8 |
<meta name="CHANGED" content="20010209;11352500"> |
9 |
<meta name="Template" content="C:\Program Files\MSOffice\Office\html.dot"> |
10 |
<title>CppUnit Cookbook</title> |
11 |
<style> |
12 |
<!-- |
13 |
A:link { color: #0000ff } |
14 |
A:visited { color: #800080 } |
15 |
--> |
16 |
</style> |
17 |
</head> |
18 |
<body link="#0000FF" vlink="#800080"> |
19 |
|
20 |
<h1> |
21 |
<b><font color="#3366FF"><font size=+2>UnitTest Cookbook</font></font></b></h1> |
22 |
<font color="#330000">The UnitTest library is derived from CppUnitTest |
23 |
library developed by Michael Feathers. This has been</font> |
24 |
<br><font color="#330000">modified to better suit the requirements of PGS |
25 |
and the PGS development environment. Please read the</font> <a href="license.html">license</a> |
26 |
agreement. |
27 |
<p><font color="#330000">It is easiest to describe the UnitTest library |
28 |
by way of an example. An incomplete UnitTest was provided for the <i>Range |
29 |
</i>class. The description for the <i>Range</i> class is shown below.</font> |
30 |
<p> <a href="Range.html">Range Class</a> |
31 |
<p>In order to provide a unit test for the <i>Range</i> class the |
32 |
<i>RangeTestCase</i> |
33 |
class was developed. This inherits from the |
34 |
<i>TestCase</i> class which |
35 |
is part of the UnitTest library. Within this class 4 methods are |
36 |
provided for testing various components of the <i>Range</i> class. The |
37 |
four methods are |
38 |
<br> testEquality |
39 |
<br> testWithin |
40 |
<br> testRangeException |
41 |
<br> testOverlap |
42 |
<br>These methods are bundled together into a suite. The facility provided |
43 |
by the TestUnit library is the <i>TestSuite</i> class. All of the |
44 |
tests within this suite are run within a <i>TestRunner</i> object. |
45 |
<p><font color="#3366FF">Code for RangeTest.h</font> |
46 |
<p>#if !defined RANGETEST_H |
47 |
<br>#define RANGETEST_H |
48 |
<p>#include "AlienNamespace.h" |
49 |
<p>#include "TestCase.h" |
50 |
<br>#include "TestSuite.h" |
51 |
<br>#include "TestCaller.h" |
52 |
<br>#include "Range.h" |
53 |
<p>BEGIN_NAMESPACE_ALIEN |
54 |
<p>class RangeTestCase : public TestCase |
55 |
<br>{ |
56 |
<br> private: |
57 |
<br> // |
58 |
<br> // Two integer ranges created by setUp method. They are destructed |
59 |
in the |
60 |
<br> // tearDown method. All of the tests use these ranges. |
61 |
<br> Range<int> *r1,*r2; |
62 |
<br> protected: |
63 |
<br> // |
64 |
<br> // The following methods are for testing various methods of |
65 |
the Range class |
66 |
<br> // |
67 |
<br> // Method to test whether operator==() method is working |
68 |
<br> void testEquality(); |
69 |
<br> // |
70 |
<br> // Method to test whether within() method is working |
71 |
<br> void testWithin(); |
72 |
<br> // |
73 |
<br> // Method to test whether a RangeException is contructed and |
74 |
thrown correctly |
75 |
<br> void testRangeException(); |
76 |
<br> // |
77 |
<br> // Method to test whether the overlap method works |
78 |
<br> void testOverlap(); |
79 |
<p> public: |
80 |
<br> RangeTestCase (string name) : TestCase (name) {} |
81 |
<br> ~RangeTestCase() {} |
82 |
<br> // |
83 |
<br> // Virtual methods of TestCase. These are provided to ensure |
84 |
the objects |
85 |
<br> // being used in the tests are in a known state. |
86 |
<br> // setUp is called before each test method is called |
87 |
<br> void setUp(); |
88 |
<br> // |
89 |
<br> // tearDown is called after each test method is called. |
90 |
<br> void tearDown(); |
91 |
<br> // |
92 |
<br> // return the suite of tests to perform |
93 |
<br> static Test* suite (); |
94 |
<br>}; |
95 |
<p>END_NAMESPACE_ALIEN |
96 |
<p>#endif |
97 |
<br> |
98 |
<p><font color="#3366FF">Code for RangeTest.C</font> |
99 |
<p>#include "RangeTest.h" |
100 |
<p>void RangeTestCase::setUp() { |
101 |
<br> // |
102 |
<br> // create fresh objects for this test |
103 |
<br> r1=new Range<int>(1,5); |
104 |
<br> r2=new Range<int>(1,7); |
105 |
<br>} |
106 |
<p>void RangeTestCase::tearDown() { |
107 |
<br> // |
108 |
<br> // destroy the objects from the last test |
109 |
<br> delete r1; |
110 |
<br> delete r2; |
111 |
<br>} |
112 |
<p>void RangeTestCase::testEquality() { |
113 |
<br> // |
114 |
<br> // check whether the operator==() method returns r1 as equal |
115 |
to itself. |
116 |
<br> // This should return true if the method is working correctly |
117 |
<br> // If false is returned the test will stop and a failure is |
118 |
reported |
119 |
<br> assert((*r1)==(*r1)); |
120 |
<br> // |
121 |
<br> // This should return true as r1 does not equal r2. |
122 |
<br> assert(!(*r1)==(*r2)); |
123 |
<br>} |
124 |
<p>void RangeTestCase::testWithin() { |
125 |
<br> // |
126 |
<br> // test whether the minimum and maximum value for the |
127 |
range are within |
128 |
<br> // the range. Both should return true. |
129 |
<br> assert((*r1).within((*r1).getMin())); |
130 |
<br> assert((*r1).within((*r1).getMax())); |
131 |
<br>} |
132 |
<p>void RangeTestCase::testRangeException() { |
133 |
<br> try { |
134 |
<br> // |
135 |
<br> // This call should throw an exception as the range |
136 |
is invalid |
137 |
<br> (*r1).setRange(3,1); |
138 |
<br> // |
139 |
<br> // if the test gets here the exception has failed |
140 |
<br> assert(false); |
141 |
<br> } |
142 |
<br> catch (RangeException &e) { |
143 |
<br> } |
144 |
<br>} |
145 |
<br>void RangeTestCase::testOverlap() { |
146 |
<br> // |
147 |
<br> // Test whether r1 overlaps r2. Should return true. |
148 |
<br> assert((*r1).overlap((*r2))); |
149 |
<br>} |
150 |
<br> |
151 |
<p>Test* RangeTestCase::suite () |
152 |
<br>{ |
153 |
<br> // |
154 |
<br> // create the suite of tests to perform. |
155 |
<br> TestSuite *testSuite = new TestSuite ("RangeTestCase"); |
156 |
<p> testSuite->addTest (new TestCaller <RangeTestCase> ("testEquality",&RangeTestCase::testEquality)); |
157 |
<br> testSuite->addTest (new TestCaller <RangeTestCase> ("testWithin",&RangeTestCase::testWithin)); |
158 |
<br> testSuite->addTest (new TestCaller <RangeTestCase> ("testRangeException",&RangeTestCase::testRangeException)); |
159 |
<br> testSuite->addTest (new TestCaller <RangeTestCase> ("testOverlap",&RangeTestCase::testOverlap)); |
160 |
<br> return testSuite; |
161 |
<br>} |
162 |
<br> |
163 |
<p><font color="#3366FF">Code for rangeTest.C (main)</font> |
164 |
<p><font color="#330000">#include "RangeTest.h"</font> |
165 |
<br><font color="#330000">#include "TestRunner.h"</font> |
166 |
<p><font color="#330000">main(int argc, char **argv) {</font> |
167 |
<br><font color="#330000"> //</font> |
168 |
<br><font color="#330000"> // object which runs all of the tests</font> |
169 |
<br><font color="#330000"> TestRunner runner;</font> |
170 |
<br><font color="#330000"> //</font> |
171 |
<br><font color="#330000"> // add the RangeTestCase suite of tests |
172 |
to the runner</font> |
173 |
<br><font color="#330000"> runner.addTest ("RangeTestCase", RangeTestCase::suite |
174 |
());</font> |
175 |
<br><font color="#330000"> //</font> |
176 |
<br><font color="#330000"> // add the RangeTestCase suite of tests |
177 |
to the runner to demonstrate</font> |
178 |
<br><font color="#330000"> // behaviour with multiple suites</font> |
179 |
<br><font color="#330000"> runner.addTest ("R2Test",RangeTestCase::suite |
180 |
());</font> |
181 |
<br><font color="#330000"> //</font> |
182 |
<br><font color="#330000"> // actually run the unit tests.</font> |
183 |
<br><font color="#330000"> runner.run (argc, argv);</font> |
184 |
<p><font color="#330000"> return 0;</font> |
185 |
<br><font color="#330000">}</font> |
186 |
<br> |
187 |
<p><font color="#3366FF"><font size=+2>Example Output</font></font> |
188 |
<p>run rangeTest |
189 |
<p><font color="#3366FF">Output as it should be</font> |
190 |
<p>Suite: RangeTestCase |
191 |
<br> Test: testEquality Ok |
192 |
<br> Test: testWithin Ok |
193 |
<br> Test: testRangeException Ok |
194 |
<br> Test: testOverlap Ok |
195 |
<p>OK (4 tests) |
196 |
<p>Suite: R2Test |
197 |
<br> Test: testEquality Ok |
198 |
<br> Test: testWithin Ok |
199 |
<br> Test: testRangeException Ok |
200 |
<br> Test: testOverlap Ok |
201 |
<p>OK (4 tests) |
202 |
<p><font color="#3366FF">Output with some of the tests deliberately made |
203 |
to fail.</font> |
204 |
<br><font color="#3366FF">Note: There is one failure and one error generated.</font> |
205 |
<p>Suite: RangeTestCase |
206 |
<br> Test: testEquality Failure |
207 |
<br> Test: testWithin Error |
208 |
<br> Test: testRangeException Ok |
209 |
<br> Test: testOverlap Ok |
210 |
<p>!!!FAILURES!!! |
211 |
<br>Test Results: |
212 |
<br>Run: 4 Failures: 1 Errors: 1 |
213 |
<br>There was 1 error: |
214 |
<br>1) testWithin line: -1 <unknown> "RangeException: Deliberate exception |
215 |
from testWithin" |
216 |
<br>There was 1 failure: |
217 |
<br>1) testEquality line: 22 RangeTest.C "!((*r1)==(*r1))" |
218 |
<p>Suite: R2Test |
219 |
<br> Test: testEquality Failure |
220 |
<br> Test: testWithin Error |
221 |
<br> Test: testRangeException Ok |
222 |
<br> Test: testOverlap Ok |
223 |
<p>!!!FAILURES!!! |
224 |
<br>Test Results: |
225 |
<br>Run: 4 Failures: 1 Errors: 1 |
226 |
<br>There was 1 error: |
227 |
<br>1) testWithin line: -1 <unknown> "RangeException: Deliberate exception |
228 |
from testWithin" |
229 |
<br>There was 1 failure: |
230 |
<br>1) testEquality line: 22 RangeTest.C "!((*r1)==(*r1))" |
231 |
<p><font color="#3366FF"><font size=+2>Building</font></font> |
232 |
<p><font color="#330000">In order to build an executable linked with the |
233 |
UnitTest library use the Perth standard makefile with the option</font> |
234 |
<br><font color="#330000"> DOUNITTEST = YES</font> |
235 |
<br> |
236 |
<br> |
237 |
<p><font color="#3366FF"><font size=+2>Run-time options</font></font> |
238 |
<p><font color="#330000"><font size=+0>You can specify the test suites |
239 |
that you want to run in a test by using arguments on the command line -</font></font> |
240 |
<p><font color="#330000"><font size=+0>TestExeName [suite=suite1[,suite2...]] |
241 |
[suite=suitea[,suiteb...]]</font></font> |
242 |
<p><font color="#330000"><font size=+0>where suite1, suite2, suitea and |
243 |
suiteb are the names of suites you want to run - suites can be repeated.</font></font> |
244 |
<br> |
245 |
<br> |
246 |
<br> |
247 |
<p><font color="#330000"><font size=+0>For example, in the range test above |
248 |
which has two suites (RangeTestCase and R2Test). The test executable is |
249 |
called RangeTest. You could use</font></font> |
250 |
<p><font color="#330000"><font size=+0>RangeTest</font></font> |
251 |
<p><font color="#330000"><font size=+0>to run both suites, or</font></font> |
252 |
<p><font color="#330000"><font size=+0>RangeTest suite=R2Test</font></font> |
253 |
<p><font color="#330000"><font size=+0>to just run the R2Test suite, or</font></font> |
254 |
<p><font color="#330000"><font size=+0>RangeTest suite=R2Test,R2Test,RangeTestCase |
255 |
suite=RangeTestCase suite=R2Test,R2Test</font></font> |
256 |
<p><font color="#330000"><font size=+0>to run R2Test, followed by R2Test |
257 |
, followed by RangeTestCase, followed by RangeTestCase, followed by two |
258 |
more R2Test runs.</font></font> |
259 |
<br> |
260 |
<br> |
261 |
<br> |
262 |
<p><font color="#3366FF"><font size=+2>Run-time options</font></font> |
263 |
<p><font color="#330000"><font size=+0>Run-time arguments can be passed |
264 |
through to the individual tests. In a test case, you can call the getArgs |
265 |
function to obtain a const vector<string>& to a vector that contains |
266 |
the command line arguments - note that all the suite=... arguments will |
267 |
have been stripped out. If the system being run provides the name of the |
268 |
executable as the first argument to the main function, then this will be |
269 |
available to you as the first string in the argument vector (in whatever |
270 |
format the system provides it).</font></font> |
271 |
<p><font color="#330000"><font size=+0>For example in the testRangeException |
272 |
function, the run time arguments could be obtained by changing the code |
273 |
to the following -</font></font> |
274 |
<p><font color="#330000"><font size=+0>void RangeTestCase::testRangeException() |
275 |
{</font></font> |
276 |
<br><b><font color="#330000"><font size=+0>const vector<string>& |
277 |
args = getArgs();</font></font></b> |
278 |
<br><font color="#330000"><font size=+0>if(args.size()>0) {</font></font> |
279 |
<br><font color="#330000"><font size=+0>cout << "exe name is " << |
280 |
args[0] << endl;</font></font> |
281 |
<br><font color="#330000"><font size=+0>}</font></font> |
282 |
<br><font color="#330000"><font size=+0> try {</font></font> |
283 |
<br><font color="#330000"><font size=+0> //</font></font> |
284 |
<br><font color="#330000"><font size=+0> // This call |
285 |
should throw an exception as the range is invalid</font></font> |
286 |
<br><font color="#330000"><font size=+0> (*r1).setRange(3,1);</font></font> |
287 |
<br><font color="#330000"><font size=+0> //</font></font> |
288 |
<br><font color="#330000"><font size=+0> // if the test |
289 |
gets here the exception has failed</font></font> |
290 |
<br><font color="#330000"><font size=+0> assert(false);</font></font> |
291 |
<br><font color="#330000"><font size=+0> }</font></font> |
292 |
<br><font color="#330000"><font size=+0> catch (RangeException &e) |
293 |
{</font></font> |
294 |
<br><font color="#330000"><font size=+0> }</font></font> |
295 |
<br><font color="#330000"><font size=+0>}</font></font> |
296 |
<br> |
297 |
<br> |
298 |
</body> |
299 |
</html> |