Nunit document translation starts

Source: Internet
Author: User
Http://www.cnblogs.com/tingfeng/articles/640289.html

Excerpt
Nunit Quick Start

Note:This page is based on the quickstart.doc file in the earlier nunit version. It is considered not a good example of test-driven development. But we keep it in the document. It explains the basic knowledge of using nunit. We will rewrite or replace it in future versions.

Let's start with a simple example. Suppose we are writing an empty application.ProgramWhich contains an account class. The account provides the deposit, withdraw, and transfer funds operations. The account class may be similar to the followingCode:

 
Namespace bank {public class account {private float balance; Public void deposit (float amount) {balance + = amount;} public void withdraw (float amount) {balance-= amount ;} public void transferfunds (Account destination, float amount) {} public float balance {get {return balance ;}}}}

Now let's write a test class accounttest class for this. The first method we want to test is transferfunds.

Namespace bank {using nunit. framework; [testfixture] public class accounttest {[test] public void transferfunds () {account source = new account (); source. deposit (200.00f); Account destination = new account (); destination. deposit (150.00f); source. transferfunds (destination, 100.00f); assert. areequal (250.00f, destination. balance); assert. areequal (100.00f, source. balance );}}}

First, we noticed that there is a [testfixture] Attribute before the class definition. this property indicates that the class contains the test code (this property can be inherited ). the class to be tested must be public, and there is no superclass restriction. finally, he must have a default constructor.

The only method in the class, transferfunds, has a header Text of the [test] attribute, which indicates that it is a test method. the test method must be to return a null value. No parameter table exists. in the test example, the test object is normally initialized, the Service for testing is executed, and the status of the Business Object is verified. the assert class defines a set of methods used to test post-conditions. In the above example, we used the areequal method to confirm whether the balance between the two accounts is correct after transferfunds is executed (areequal has some overload functions, here we use the following parameters: the first parameter is the expected value, and the second parameter is the actual value ).

Compile and run this routine. suppose you compile the project into a bank. DLL file. run nunit gui (the Installation Wizard will create a shortcut in the desktop and program files Directories). After starting the GUI, click File> Open menu to open your bank. DLL file. bank. after the DLL is loaded, we will see a tree test structure in the panel on the left, and a State set will appear in the panel on the right. click the run button. The progress bar and the transferfunds node in the tree structure become red, indicating that the test failed. the following message is displayed in the [errors] and [failures] panels:

 
Transferfunds: Expected <250> but was <150>

In addition, there is a stack trace panel under the message, which points out the location of the Error Test code.

 
At bank. accounttest. transferfunds () in c: \ nunit \ banksampletests \ accounttest. CS: Line 17

 

This is expected because the transferfunds method has not yet been implemented, leading to a test failure. You do not have to close the GUI and return to the IDE to correct the transferfunds method according to the following code:

 
Public void transferfunds (Account destination, float amount) {destination. Deposit (amount); withdraw (amount );}

Now re-compile the code and run the GUI again. Both the status bar and the test tree are green. (as long as you keep the GUI open, you can modify and compile the code in the IDE at will, and the GUI will automatically reload the DLL.

We can add more error test code to the account. we will add a minimum account balance requirement to determine whether to pay a fee less than the minimum account balance to the bank. first, we add a minimumbalance attribute to the account class:

 
Private float minimumbalance = 10.00f; public float minimumbalance {get {return minimumbalance ;}}

An exception is used to indicate that the balance is lower than the minimum balance:

 
Namespace bank {using system; public class insufficientfundsexception: applicationexception {}}

Add a new method to the accounttest class:

 
[Test] [expectedexception (typeof (insufficientfundsexception)] public void transferwithinsufficientfunds () {account source = new account (); source. deposit (200.00f); Account destination = new account (); destination. deposit (150.00f); source. transferfunds (destination, 300.00f );}

The [expectedexception] attribute after the [test] attribute of this method indicates that we expect an exception of the determined type in the following test. If this exception does not occur, the test fails. compile the code and return to the GUI. when you re-compile the code, the GUI will gray the test tree and collapse all the branches, just like before the test is run (the GUI monitors all DLL changes and reflects them in a timely manner ). the red status bar appears again when you click the run button. the following error is returned:

Transferwithinsufficentfunds: insufficientfundsexception was expected

Next let's modify the transferfunds method:

 

 
Public void transferfunds (Account destination, float amount) {destination. Deposit (amount); If (balance-amount <minimumbalance) throw new insufficientfundsexception (); withdraw (amount );}

After compilation, the green status bar for running the test appears. succeeded! But wait a moment. Take a closer look at our code and we will find that the bank will lose a sum of money every time the transfer operation fails. Let's write a test to confirm this suspicion. Add this test method:

 
[Test] public void transferwithinsufficientfundsatomicity () {account source = new account (); source. deposit (200.00f); Account destination = new account (); destination. deposit (150.00f); try {source. transferfunds (destination, 300.00f);} catch (insufficientfundsexception expected) {} assert. areequal (200.00f, source. balance); assert. areequal (150.00f, destination. balance );}

The tests to be carried out below will all succeed. compilation, execution, and red status bars. okay. We have evaporated $300.00 (has we had this experience ?) The source account balance of 150.00 is correct, but the destination account shows: $450.00. How to fix it? We only need to check the minimum balance at the beginning:

 
Public void transferfunds (Account destination, float amount) {If (balance-amount <minimumbalance) throw new insufficientfundsexception (); destination. Deposit (amount); withdraw (amount );}

What happens if another exception is thrown by the withdraw () method? Shocould 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 and add the following attributes in the Method

 
[Test] [ignore ("decide how to implement Transaction Management")] public void transferwithinsufficientfundsatomicity () {// code is the same}

After compilation and execution, a yellow status bar appears. Click the [tests not run] label and you will see bank. accounttest. transferwithinsufficientfundsatomicity () in the list along with the reason this test is ignored.

Looking at our code, we can find that reconstruction is needed in some places. all test methods share a group of objects. let's extract the code and put it in a setup method so that it can be reused in all methods. the tested code after reconstruction is as follows:

Namespace bank {using system; using nunit. framework; [testfixture] public class accounttest {account source; Account destination; [setup] public void Init () {source = new account (); source. deposit (200.00f); Destination = new account (); destination. deposit (150.00f);} [test] public void transferfunds () {source. transferfunds (destination, 100.00f); assert. areequal (250.00f, destination. balance); assert. areequal (100.00f, source. balance);} [test] [expectedexception (typeof (insufficientfundsexception)] public void transferwithinsufficientfunds () {source. transferfunds (destination, 300.00f);} [test] [ignore ("decide how to implement Transaction Management")] public void transferwithinsufficientfundsatomicity () {try {source. transferfunds (destination, 300.00f);} catch (insufficientfundsexception expected) {} assert. areequal (200.00f, source. balance); assert. areequal (150.00f, destination. balance );}}}

Note that the init method has a common initialization code. It does not return values and has no parameters. He uses the [setup] attribute to identify. Compile and run same yellow bar!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.