source: BMXNET_RPMS_dotNET_UTILITIES-BMX/branch/IHS BMX Framework/lib/NUnit/NUnit-2.5.10.11092/doc/quickStart.html@ 1146

Last change on this file since 1146 was 1146, checked in by Sam Habiel, 13 years ago

Initial Import of BMX4

File size: 12.0 KB
Line 
1<!-- saved from url=(0014)about:internet --><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
2<html>
3<!-- Standard Head Part -->
4<head>
5<title>NUnit - QuickStart</title>
6<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
7<meta http-equiv="Content-Language" content="en-US">
8<link rel="stylesheet" type="text/css" href="nunit.css">
9<link rel="shortcut icon" href="favicon.ico">
10</head>
11<!-- End Standard Head Part -->
12
13<body>
14
15<!-- Standard Header for NUnit.org -->
16<div id="header">
17 <a id="logo" href="http://www.nunit.org"><img src="img/logo.gif" alt="NUnit.org" title="NUnit.org"></a>
18 <div id="nav">
19 <a href="http://www.nunit.org">NUnit</a>
20 <a class="active" href="index.html">Documentation</a>
21 </div>
22</div>
23<!-- End of Header -->
24
25<div id="content">
26
27<style><!--
28 div.code { width: 34em }
29--></style>
30
31<h2>NUnit Quick Start</h2>
32
33<p><b>Note:</b> This page is based on the original QuickStart.doc, found in
34earlier releases of NUnit. It has been pointed out that it isn't a good
35example of Test-Driven Development. However, we're keeping it in the docs
36because it does illustrate the basics of using NUnit. We'll revise or replace
37it in a future release.</p>
38
39<p>Let’s start with a simple example. Suppose we are writing a bank application and we have a basic domain class – Account. Account supports operations to deposit, withdraw, and transfer funds. The Account class may look like this:</p>
40
41<div class="code">
42<pre>namespace bank
43{
44 public class Account
45 {
46 private float balance;
47 public void Deposit(float amount)
48 {
49 balance+=amount;
50 }
51
52 public void Withdraw(float amount)
53 {
54 balance-=amount;
55 }
56
57 public void TransferFunds(Account destination, float amount)
58 {
59 }
60
61 public float Balance
62 {
63 get{ return balance;}
64 }
65 }
66}</pre>
67</div>
68
69<p>Now let’s write a test for this class – AccountTest. The first method we will test is TransferFunds.</p>
70
71<div class="code">
72<pre>namespace bank
73{
74 using NUnit.Framework;
75
76 [TestFixture]
77 public class AccountTest
78 {
79 [Test]
80 public void TransferFunds()
81 {
82 Account source = new Account();
83 source.Deposit(200.00F);
84 Account destination = new Account();
85 destination.Deposit(150.00F);
86
87 source.TransferFunds(destination, 100.00F);
88 Assert.AreEqual(250.00F, destination.Balance);
89 Assert.AreEqual(100.00F, source.Balance);
90
91 }
92 }
93}</pre>
94</div>
95
96<p>The first thing to notice about this class is that it has a [TestFixture] attribute associated with it – this is the way to indicate that the class contains test code (this attribute can be inherited). The class has to be public and there are no restrictions on its superclass. The class also has to have a default constructor.</p>
97
98<p>The only method in the class – TransferFunds, has a [Test] attribute associated with it – this is an indication that it is a test method. Test methods have to return void and take no parameters. In our test method we do the usual initialization of the required test objects, execute the tested business method and check the state of the business objects. The Assert class defines a collection of methods used to check the post-conditions and in our example we use the AreEqual method to make sure that after the transfer both accounts have the correct balances (there are several overloadings of this method, the version that was used in this example has the following parameters : the first parameter is an expected value and the second parameter is the actual value).</p>
99
100<p>Compile and run this example. Assume that you have compiled your test code into a bank.dll. Start the NUnit Gui (the installer will have created a shortcut on your desktop and in the “Program Files” folder), after the GUI starts, select the File->Open menu item, navigate to the location of your bank.dll and select it in the “Open” dialog box. When the bank.dll is loaded you will see a test tree structure in the left panel and a collection of status panels on the right. Click the Run button, the status bar and the TransferFunds node in the test tree turn red – our test has failed. The “Errors and Failures” panel displayed the following message:
101
102<pre> TransferFunds : expected &lt;250&gt; but was &lt;150&gt;</pre>
103
104and the stack trace panel right below it reported where in the test code the failure has occurred –
105
106<pre> at bank.AccountTest.TransferFunds() in C:\nunit\BankSampleTests\AccountTest.cs:line 17</pre></p>
107
108<p>That is expected behavior; the test has failed because we have not implemented the TransferFunds method yet. Now let’s get it to work. Don’t close the GUI and go back to your IDE and fix the code, make your TransferFunds method look like this:</p>
109
110<div class="code">
111<pre>public void TransferFunds(Account destination, float amount)
112{
113 destination.Deposit(amount);
114 Withdraw(amount);
115}</pre>
116</div>
117
118
119<p>Now recompile your code and click the run button in GUI again – the status bar and the test tree turn green. (Note how the GUI has reloaded the assembly automatically for you; we will keep the GUI open all the time and continue working with our code in IDE and write more tests).</p>
120
121<p>Let’s add some error checking to our Account code. We are adding the minimum balance requirement for the account to make sure that banks continue to make their money by charging your minimal overdraft protection fee. Let’s add the minimum balance property to our Account class:</p>
122
123<div class="code">
124<pre>private float minimumBalance = 10.00F;
125public float MinimumBalance
126{
127 get{ return minimumBalance;}
128}</pre>
129</div>
130
131<p>We will use an exception to indicate an overdraft:</p>
132
133<div class="code">
134<pre>namespace bank
135{
136 using System;
137 public class InsufficientFundsException : ApplicationException
138 {
139 }
140}</pre>
141</div>
142
143<p>Add a new test method to our AccountTest class:</p>
144
145<div class="code">
146<pre>[Test]
147[ExpectedException(typeof(InsufficientFundsException))]
148public void TransferWithInsufficientFunds()
149{
150 Account source = new Account();
151 source.Deposit(200.00F);
152 Account destination = new Account();
153 destination.Deposit(150.00F);
154 source.TransferFunds(destination, 300.00F);
155}</pre>
156</div>
157
158<p>This test method in addition to [Test] attribute has an [ExpectedException] attribute associated with it – this is the way to indicate that the test code is expecting an exception of a certain type; if such an exception is not thrown during the execution – the test will fail. Compile your code and go back to the GUI. As you compiled your test code, the GUI has grayed out and collapsed the test tree as if the tests were not run yet (GUI watches for the changes made to the test assemblies and updates itself when the structure of the test tree has changed – e.g. new test is added). Click the “Run” button – we have a red status bar again. We got the following Failure :
159
160<pre> TransferWithInsufficentFunds : InsufficientFundsException was expected</pre>
161
162Let’s fix our Account code again, modify the TransferFunds method this way:</p>
163
164<div class="code">
165<pre>public void TransferFunds(Account destination, float amount)
166{
167 destination.Deposit(amount);
168 if(balance-amount&lt;minimumBalance)
169 throw new InsufficientFundsException();
170 Withdraw(amount);
171}</pre>
172</div>
173
174<p>Compile and run the tests – green bar. Success! But wait, looking at the code we’ve just written we can see that the bank may be loosing money on every unsuccessful funds Transfer operation. Let’s write a test to confirm our suspicions. Add this test method:</p>
175
176<div class="code">
177<pre>[Test]
178public void TransferWithInsufficientFundsAtomicity()
179{
180 Account source = new Account();
181 source.Deposit(200.00F);
182 Account destination = new Account();
183 destination.Deposit(150.00F);
184 try
185 {
186 source.TransferFunds(destination, 300.00F);
187 }
188 catch(InsufficientFundsException expected)
189 {
190 }
191
192 Assert.AreEqual(200.00F,source.Balance);
193 Assert.AreEqual(150.00F,destination.Balance);
194}</pre>
195</div>
196
197<p>We are testing the transactional property of our business method – all operations are successful or none. Compile and run – red bar. OK, we’ve made $300.00 out of a thin air (1999.com déjà vu?) – the source account has the correct balance of 200.00 but the destination account shows : $450.00. How do we fix this? Can we just move the minimum balance check call in front of the updates:</p>
198
199<div class="code">
200<pre>public void TransferFunds(Account destination, float amount)
201{
202 if(balance-amount&lt;minimumBalance)
203 throw new InsufficientFundsException();
204 destination.Deposit(amount);
205 Withdraw(amount);
206}</pre>
207</div>
208
209<p>What if the Withdraw() method throws another exception? Should we execute a compensating transaction in the catch block or rely on our transaction manager to restore the state of the objects? We need to answer those questions at some point, but not now; but what do we do with the failing test in the meantime – remove it? A better way is to temporarily ignore it, add the following attribute to your test method</p>
210
211<div class="code">
212<pre>[Test]
213[Ignore("Decide how to implement transaction management")]
214public void TransferWithInsufficientFundsAtomicity()
215{
216 // code is the same
217}</pre>
218</div>
219
220<p>Compile and run – yellow bar. Click on “Tests Not Run” tab and you will see bank.AccountTest.TransferWithInsufficientFundsAtomicity() in the list along with the Reason this test is ignored.</p>
221
222<p>Looking at our test code we can see that some refactoring is in order. All test methods share a common set of test objects. Let’s extract this initialization code into a setup method and reuse it in all of our tests. The refactored version of our test class looks like this:</p>
223
224<div class="code">
225<pre>namespace bank
226{
227 using System;
228 using NUnit.Framework;
229
230 [TestFixture]
231 public class AccountTest
232 {
233 Account source;
234 Account destination;
235
236 [SetUp]
237 public void Init()
238 {
239 source = new Account();
240 source.Deposit(200.00F);
241 destination = new Account();
242 destination.Deposit(150.00F);
243 }
244
245 [Test]
246 public void TransferFunds()
247 {
248 source.TransferFunds(destination, 100.00f);
249 Assert.AreEqual(250.00F, destination.Balance);
250 Assert.AreEqual(100.00F, source.Balance);
251 }
252
253 [Test]
254 [ExpectedException(typeof(InsufficientFundsException))]
255 public void TransferWithInsufficientFunds()
256 {
257 source.TransferFunds(destination, 300.00F);
258 }
259
260 [Test]
261 [Ignore("Decide how to implement transaction management")]
262 public void TransferWithInsufficientFundsAtomicity()
263 {
264 try
265 {
266 source.TransferFunds(destination, 300.00F);
267 }
268 catch(InsufficientFundsException expected)
269 {
270 }
271
272 Assert.AreEqual(200.00F,source.Balance);
273 Assert.AreEqual(150.00F,destination.Balance);
274 }
275 }
276}</pre>
277</div>
278
279<p>Note that Init method has the common initialization code, it has void return type, no parameters, and it is marked with [SetUp] attribute. Compile and run – same yellow bar!</p>
280
281</div>
282
283<!-- Submenu -->
284<div id="subnav">
285<ul>
286<li><a href="index.html">NUnit 2.5.10</a></li>
287<ul>
288<li><a href="getStarted.html">Getting&nbsp;Started</a></li>
289<ul>
290<li id="current"><a href="quickStart.html">Quick&nbsp;Start</a></li>
291<li><a href="installation.html">Installation</a></li>
292</ul>
293<li><a href="assertions.html">Assertions</a></li>
294<li><a href="constraintModel.html">Constraints</a></li>
295<li><a href="attributes.html">Attributes</a></li>
296<li><a href="runningTests.html">Running&nbsp;Tests</a></li>
297<li><a href="extensibility.html">Extensibility</a></li>
298<li><a href="releaseNotes.html">Release&nbsp;Notes</a></li>
299<li><a href="samples.html">Samples</a></li>
300<li><a href="license.html">License</a></li>
301</ul>
302</ul>
303</div>
304<!-- End of Submenu -->
305
306
307<!-- Standard Footer for NUnit.org -->
308<div id="footer">
309 Copyright &copy; 2010 Charlie Poole. All Rights Reserved.
310</div>
311<!-- End of Footer -->
312
313</body>
314</html>
Note: See TracBrowser for help on using the repository browser.