NUnitAsp
ASP.NET unit testing

Quick Start Guide

This guide contains a brief description of NUnitAsp and how to use it. It assumes that you're familiar with NUnit, ASP.NET, and unit testing. It also assumes that you're comfortable with a high-level explanation and can look up the API details for yourself. If you prefer a more detailed explanation, see the NUnitAsp Tutorial instead.

The examples in this guide are written in C#. NUnitAsp will work with other .NET languages, but we don't provide examples for them. If you would like us to include examples for your favorite language, we welcome contributions.

About NUnitAsp

NUnitAsp is a class library for use within your NUnit tests. It provides NUnit with the ability to download, parse, and manipulate ASP.NET web pages.

With NUnitASP, your tests don't need to know how ASP.NET renders controls into HTML. Instead, you can rely on the NUnitASP library to do this for you, keeping your test code simple and clean. For example, your tests don't need to know that a DataGrid control renders as an HTML table. You can rely on NUnitASP to handle the details. This gives you the freedom to focus on functionality questions, like whether the DataGrid holds the expected values.

When you use NUnitAsp, you'll create NUnit test fixtures and test cases as normal. Each test case will consist of three parts. The first part sets up the test by instantiating "Tester" objects that know how to parse ASP.NET. The second part loads the page from the web server, and the third part performs the test by using and making assertions about the testers.

[Test]
public void TestExample()
{
   // First, instantiate "Tester" objects:
   LabelTester label = new LabelTester("textLabel");
   LinkButtonTester link = new LinkButtonTester("linkButton");

   // Second, visit the page being tested:
   Browser.GetPage("http://localhost/example/example.aspx");

   // Third, use tester objects to test the page:
   Assert.AreEqual("Not clicked.", label.Text);
   link.Click();
   Assert.AreEqual("Clicked once.", label.Text);
   link.Click();
   Assert.AreEqual("Clicked twice.", label.Text);
}

NUnitAdapter.cs

New in NUnitAsp 2.0 is the ability to work with any version of any test framework. This comes at the cost of making NUnitAsp a little more difficult to use.

To maintain NUnitAsp's traditional ease-of-use, we've created an adapter file for use with NUnit. The adapter file, NUnitAdapter.cs, must be copied into your test project. It's located in the "bin" directory of the NUnitAsp download. NUnitAsp.cs provides the WebFormTestCase base class that all NUnitAsp test fixtures extend.

You don't have to use NUnitAdapter.cs, but if you don't, you'll need to provide your own implementation of WebFormTestCase.

An NUnitAsp Test Fixture

Every NUnitAsp test fixture follows the following basic pattern. NUnit will automatically find the tests when you load their DLL. Replace the parts that are highlighted.

using System;
using NUnit.Framework;
using NUnit.Extensions.Asp;
using NUnit.Extensions.Asp.AspTester;

namespace example.namespace
{
  [TestFixture]
  public class ExampleTestFixture : WebFormTestCase
  {
    [Test]
    public void TestExample()
    {
      // Your test here
    }

    [Test]
    public void TestExample2()
    {
      // Your second test here
    }

    // etc...

  }
}

About WebFormTestCase and Browser (HttpClient)

NUnitAsp test fixtures extend WebFormTestCase. It performs necessary setup and teardown and provides the Browser property.

The Browser object represents the NUnitAsp web browser. You'll use it to load your page in order to start testing it. Browser is important, but in most of your tests, you'll use it for just one thing:

Browser.GetPage("http://localhost/example/example.aspx");

The Browser property on WebFormTestCase is what you'll typically use, but the object itself is an instance of HttpClient, an NUnitAsp class. You might find yourself using HttpClient's other capabilities occasionally. HttpClient's CurrentPageText property can be particularly useful. Use it to help debug: dump the text of the current page to the console, and then look at NUnit's "Standard Out" tab to see what the problem is.

Console.WriteLine(Browser.CurrentPageText);

About WebAssert

Your tests will mostly use the built-in assertions of your testing framework. If you use NUnit, for example, you'll use NUnit's Assert class.

NUnitAsp's WebAssert class provides extra assertions for common scenarios. See the API documentation for more information.

About Tester Objects

Tester objects form the core of NUnitAsp. Each instantiated tester object represents exactly one ASP.NET control in your web page. With a tester object, you can manipulate the ASP.NET control as if you were actually receiving an .aspx page (rather than some badly mangled HTML).

AssertEquals("Not clicked.", label.Text);
link.Click();
AssertEquals("Clicked once.", label.Text);
link.Click();
AssertEquals("Clicked twice.", label.Text);

In the above example, both "label" and "link" are testers. "Label" is an instance of a the LabelTester tester and "link" is an instance of the LinkButtonTester. As you can see from the example, the tester allows you to directly manipulate the underlying controls. You can read the text from the label and you can click the link button.

In order to use a tester object, you must first instantiate it.

LabelTester label = new LabelTester("textLabel");
LinkButtonTester link = new LabelTester("textLabel");

The parameter is the ID of the control. You specified the ID in your ASP.NET code.

For information about which controls are supported, see the API documentation. Testers for web controls are in the AspTester namespace and testers for HTML controls are in the HtmlTester namespace.

User Controls, Data Grids, and Other Control Nesting

If you have complex web site, you'll often have controls nested within other controls. If you do, pass the tester for the containing control as the second parameter of the constructor.

For example, if you're testing a link button that's in a user control, you'll need a UserControlTester. When you construct the LinkButtonTester, pass in the UserControlTester as the container:

// Example: Link button in a user control
UserControlTester control = new UserControlTester("control");
LinkButtonTester button = new LinkButtonTester("button", control);

button.Click();

Data grids are another example of control nesting. They're even trickier than user controls, because the controls aren't nested directly in the data grid; they're nested in a row of the data grid. You have to tell NUnitAsp that the control is in a row that's in the data grid:

// Example: Checkbox in row 3 of a data grid
DataGridTester grid = new DataGridTester("grid");
DataGridTester.Row row3 = new DataGridTester.Row(3, grid);
CheckBoxTester checkbox = new CheckBoxTester("checkbox", row3);

checkbox.Checked = true;

The above code can be compressed a bit:

// Example: Checkbox in row 3 of a data grid (alternate style)
DataGridTester grid = new DataGridTester("grid");
CheckBoxTester checkbox = new CheckBoxTester("checkbox", grid.GetRow(2)); // '2' is not a typo; this style is zero-based

checkbox.Checked = true;

SetUp And TearDown

A standard feature of NUnit is the ability to perform pre-test and post-test actions with the [SetUp] and [TearDown] attributes. Those actions work a little bit differently than normal in NUnitAsp. This is a flaw in NUnitAsp that we intend to fix some day.

In NUnitAsp, the [SetUp] and [TearDown] attributes are already used by WebFormTestCase. Using them again in a your own test fixture will cause NUnit to ignore the code in WebFormTestCase. This prevents important set-up code from running. Fortunately for your sanity, NUnitAsp will throw an exception explaining the problem if you accidently use one of these inappropriately.

Because [SetUp] and [TearDown] are not available, NUnitAsp uses the old NUnit 1.x approach of overriding SetUp() and TearDown() methods instead.

// Don't do this:
[SetUp]
public void MySetUp() {
  // set-up code here
}

[TearDown]
public void MyTearDown() {
  // tear-down code here
}


// Do this instead:
protected override void SetUp() {
  // set-up code here
}

protected override void TearDown() {
  // tear-down code here
}

Conclusion

NUnitAsp is meant to make it easy for you to test your ASP.NET applications. The basic structure of each test is to instantiate tester objects, get a web page with the Browser object, and then manipulate and assert the page by using the testers.

As you work, remember NUnitAsp's primary "gotcha:" override SetUp() and TearDown() instead of using the [SetUp] and [TearDown] attributes.

We welcome your feedback on NUnitAsp. Please send email to the NUnitAsp mailing list.

by Jim Shore. Last updated for v2.0.