1 |
jgs |
82 |
<!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> |