NUnit Quick Start

Hướng dẫn sử dụng NUnit
Post Reply
tvn
Admin
Posts: 4866
Joined: Tue 10 Aug, 2010 10:11 am
Location: HCM
Contact:

NUnit Quick Start

Post by tvn » Sun 13 May, 2012 8:27 pm

Note: This page is based on the original QuickStart.doc, found in earlier releases of NUnit. It has been pointed out that it isn't a good example of Test-Driven Development. However, we're keeping it in the docs because it does illustrate the basics of using NUnit. We'll revise or replace it in a future release.

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:

Code: Select all

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 for this class – AccountTest. The first method we will test is TransferFunds.

Code: Select all

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);
	
    }
  }
}
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.

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).

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:
  • TransferFunds : expected <250> but was <150>
and the stack trace panel right below it reported where in the test code the failure has occurred –
  • at bank.AccountTest.TransferFunds() in C:\nunit\BankSampleTests\AccountTest.cs:line 17
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:

Code: Select all

public void TransferFunds(Account destination, float amount)
{
	destination.Deposit(amount);
	Withdraw(amount);
}
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).

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:

Code: Select all

private float minimumBalance = 10.00F;
public float MinimumBalance
{
	get{ return minimumBalance;}
}
We will use an exception to indicate an overdraft:

Code: Select all

namespace bank
{
  using System;
  public class không hợp lệ : ApplicationException
  {
  }
}
Add a new test method to our AccountTest class:

Code: Select all

[Test]
[ExpectedException(typeof(không hợp lệ))]
public void TransferWithInsufficientFunds()
{
	Account source = new Account();
	source.Deposit(200.00F);
	Account destination = new Account();
	destination.Deposit(150.00F);
	source.TransferFunds(destination, 300.00F);
}
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 :
  • TransferWithInsufficentFunds : không hợp lệ was expected
Let’s fix our Account code again, modify the TransferFunds method this way:

Code: Select all

public void TransferFunds(Account destination, float amount)
{
	destination.Deposit(amount);
	if(balance-amount<minimumBalance)
		throw new không hợp lệ();
	Withdraw(amount);
}
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:

Code: Select all

[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(không hợp lệ expected)
	{
	}

	Assert.AreEqual(200.00F,source.Balance);
	Assert.AreEqual(150.00F,destination.Balance);
}
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:

Code: Select all

public void TransferFunds(Account destination, float amount)
{
	if(balance-amount<minimumBalance) 
		throw new không hợp lệ();
	destination.Deposit(amount);
	Withdraw(amount);
}
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

Code: Select all

[Test]
[Ignore("Decide how to implement transaction management")]
public void TransferWithInsufficientFundsAtomicity()
{
	// code is the same
}
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.

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:

Code: Select all

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(không hợp lệ))]
    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(không hợp lệ expected)
      {
      }

      Assert.AreEqual(200.00F,source.Balance);
      Assert.AreEqual(150.00F,destination.Balance);
    }
  }
}
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!

Nguồn Nunit.org



hoai
Fresher Tester
Posts: 25
Joined: Tue 13 Mar, 2012 9:12 am
Contact:

Re: NUnit Quick Start

Post by hoai » Thu 25 Oct, 2012 2:22 pm

ban TVN cho mình hỏi tí: NUnit với JUNit có khác nhau nhiều ko. Hay chỉ khác nhau ở ngôn ngữ thôi. JUnit dùng trong Java.NUnit dung trong C#



tvn
Admin
Posts: 4866
Joined: Tue 10 Aug, 2010 10:11 am
Location: HCM
Contact:

Re: NUnit Quick Start

Post by tvn » Thu 25 Oct, 2012 3:33 pm

Chào bạn,

Junit và Nunit dùng như nhau hết, chỉ khác là áp dụng cho loại nào thôi.
  • Junit = Jave (chữ J)
    Nunit = .net (chữ N)
    PhpUnit = php



hoai
Fresher Tester
Posts: 25
Joined: Tue 13 Mar, 2012 9:12 am
Contact:

Re: NUnit Quick Start

Post by hoai » Thu 25 Oct, 2012 4:08 pm

bạn có thể cho mình một số tài liệu về lợi ích NUnit đc ko?
mình đang làm khóa luận tốt nghiệp về NUnit. Mà cho mình hỏi NUnit chỉ kiểm thử ở mức đơn vị thôi phải ko? ko thể kiểm thử tích hợp dc ah?



tvn
Admin
Posts: 4866
Joined: Tue 10 Aug, 2010 10:11 am
Location: HCM
Contact:

Re: NUnit Quick Start

Post by tvn » Thu 25 Oct, 2012 5:10 pm

Chào bạn,

Bạn xem lại tài liệu lý thuyết một xíu nha, nó có thể áp dụng được ở nhiều mức, ví dụ như sau:
  • Ở mức đơn vị (component level): thì test các vấn đề liên quan đến cấu trúc của các (từng) hàm như câu lệnh (statement), điều kiện, rẽ nhánh, hoặc các luồng xử lý…
    Ở mức tích hợp (Integration level): thì test các vấn đề liên quan đến cấu trúc, liên kết của tất cả các hàm liên quan đến sự tích hợp, lúc đó các component/hàm được liên kết như dạng cây, mình có thể vẽ ra thành sơ đồ. Test các luồng sơ đồ đó bằng cách đứng ở component này gọi component kia,…
    Ở mức hệ thống (system level): thì tương tự integration level nhưng cao hơn.



hoai
Fresher Tester
Posts: 25
Joined: Tue 13 Mar, 2012 9:12 am
Contact:

Re: NUnit Quick Start

Post by hoai » Thu 25 Oct, 2012 9:49 pm

thank bạn TVN nhiều
mà bạn ơi cho mình hỏi bạn có tài liệu tổng quan nào về NUnit ko?



tvn
Admin
Posts: 4866
Joined: Tue 10 Aug, 2010 10:11 am
Location: HCM
Contact:

Re: NUnit Quick Start

Post by tvn » Thu 25 Oct, 2012 10:46 pm

Bạn vào đây http://www.nunit.org/ sẽ có tất cả các tài liệu bạn cần. ở trang home này bạn biết thông tin tổng quan

What Is NUnit?
  • NUnit is a unit-testing framework for all .Net languages. Initially ported from JUnit, the current production release, version 2.6, is the seventh major release of this xUnit based unit testing tool for Microsoft .NET. It is written entirely in C# and has been completely redesigned to take advantage of many .NET language features, for example custom attributes and other reflection related capabilities. NUnit brings xUnit to all .NET languages.
Để sử dụng Nunit bạn nên xem trang này http://www.nunit.org/index.php?p=getStarted&r=2.6.1

Trong đó có link tải về cài đặt, có link bài tập ví du. bạn xem trong này nha


Getting Started with NUnit
  • If you haven't already done so, go to our Download page, select a version of NUnit and download it. The Installation page contains instructions for installing on your system.

    To get started using NUnit, read the Quick Start page. This article demonstrates the development process with NUnit in the context of a C# banking application. Check the Samples page for additional examples, including some in VB.Net, J# and managed C++.
Which Test Runner to use?
  • NUnit has two different ways to run your tests. The console runner, nunit-console.exe, is the fastest to launch, but is not interactive. The gui runner, nunit.exe, is a Windows Forms application that allows you to work selectively with your tests and provides graphical feedback.



Post Reply

Return to “Hướng Dẫn Sử Dụng NUnit”