So I had mentioned I'd be working with NUnitASP and that id'd post some comments on my experience. I used it to create a comprehensive test for a relatively complex ASP.NET WebControl. It has proved to be a tremendous help. I've gone through the code extensively to see how it works and it's quite interesting. First let me explain the details of NUnitASP...

To use NUnitASP code is written in normal NUnit test fixtures. By inheriting from NUnitASP's WebFormTestCase, your test code has access to an HttpClient object ("Browser") for requesting *and* posting back pages of an ASP.NET site. The response of the site is interpreted as XML using code from the SgmlReader project. The SgmlReader takes typical HTML (i.e. not well formed XML) as input and turns it into well formed XML as it is read by exposing it as a System.Xml.XmlReader, which in turn allows NUnitASP to provide the HTML page as an XmlDocument. Once a rendered ASP.NET page is available as an XmlDocument, the rest of NUnitASP's inner workings come together quickly.

Each ASP.NET control has a "Tester" class that mimics the equivalent ASP.NET control by having the same properties. For example the ButtonTester has a Text property that is used just like the ASP.NET's Button class, and the ListControlTester has Items, SelectItem, and SelectIndex properties and so on. Each tester can be used from your test case just like the equivalent ASP.NET control. Except that the tester is manipulating the ASP.NET control from the browser's perspective. Except instead of parsing the returned HTML and rendering it on screen like a browser, the parsed HTML is used by testers objects to find the output of named ASP.NET controls by the ASP.NET control's ID (and potentially the ID of its ASP.NET containers). This is possible because ASP.NET controls write their control name used on the server into the rendered HTML as the ID attribute of the HTML element containing it's rendered output. Once control's HTML element is found, the attributes and InnerXml of the element are up to the specific Tester implementation to interpret and provide through convenient properties as necessary.

Let's take the ASP.NET ListBox control for examle. On the server it might look like this:

<asp:listbox id="ListBox1" runat="server">
And on the client the same control renders as:
<SELECT id="ListBox1" size="4" name="ListBox1"> 
	<OPTION value="a">a</OPTION>
Since NUnitASP provides the rendered web page as an XmlDocument, our ListBox control's rendering on the client could be found using XPath of something like:
XmlElement listBoxElement = xmlDoc.GetElementById("ListBox1");
To return the item(s) rendered by the ListBox control to the browser, you could use something like:
XmlNodeList items = listBoxElement.SelectNodes("option");
To get the Item set to be selected by ASP.NET you cold enumerate the nodes in items, and find the one with a selected attribute. Or even use some xpath query. All this low level searching for elements as shown above is abstracted by a Tester class created for each of the intrinsic ASP.NET controls. So instead your test case's code would be more like:
WebForm webForm = new WebForm(Browser);
ListBoxTester listBox1 = new ListBoxTester("ListBox1", webForm);
Assert("first listbox item not selected!", listBox1.Items[0].Selected);

I needed to test a custom ASP.NET control that was significantly more complex than any of the intrinsic ASP.NET controls. So I created a custom Tester object for the control to abstract the complex xpath queries that were necessary to decipher the significant items in the rendering of the control. In the end, NUnitASP made the test cases quite compact, clear and very comprehensive. I covered my unit tests to make sure the unit tests were comprehensive and was able to make allot of progress in just a couple of days.

I only had two real problems. One was the base ControlTester object in NUnitASP had an internal constructor, so my custom Tester couldn't inherit from it and thus work with the rest of NUnitASP. Howerver, since NUnitASP is open source, I got the source out, made a quick change, recompiled and solved that one. The other obstacle was that I the web control I'm testing renders images, IFrames and even ActiveX objects that all have links back to dynamically generated content on the server. I needed to make another request for these objects based on what was rendered by the web control to verify the dynamically generated content. NUnitASP didn't have a way to do this, so I used System.NET to create a quick utility that given a TestCase containing the URL to the page currently being tested could resolve the relative links, and download these dynamic objects and make them available in the test for further validation. It all worked out quite nicely.

If you need to test any sites or controls, I highly recommend NUnitASP.

posted @ Thursday, March 18, 2004 12:30 AM


Comments on this entry:

# re: NUnitASP Tests ASP.NET

Left by Carlton Nettleton at 5/4/2004 9:21 PM

Have you had any luck with non annyomous logins with NUnitAsp?

# re: NUnitASP Tests ASP.NET

Left by Scott Willeke at 5/4/2004 11:36 PM

Sorry but I have not yet tried that. I'd love to hear more about a solution if you find one (aparently this doesn't work?).

# re: NUnitASP Tests ASP.NET

Left by Carlton Nettleton at 5/5/2004 12:13 PM

No...i have just run into a problem with browser credentials. It does not detect them correctly.

# re: NUnitASP Tests ASP.NET

Left by Carlton Nettleton at 7/19/2004 2:34 PM

FYI, the error I was making was I used something other than Basic authentication. Once you use Basic authentication, my problem was solved.

# re: NUnitASP Tests ASP.NET

Left by Scott Willeke at 7/20/2004 12:02 PM

Thanks for letting us know!

# re: NUnitASP Tests ASP.NET

Left by Chris Choate at 4/7/2005 3:02 PM

Has anyone tested 3rd party controls (Infragistics and the like) with NUnitAsp?

# re: NUnitASP Tests ASP.NET

Left by Scott Willeke at 4/7/2005 8:00 PM

Internally we actually use it to test the ActiveReports WebViewer control. This post was based on my experience doing just that. We're currently investigating using a ControlTester approach with NUnitForms for another project I'm working on now.

# RE: NUnit vs. Your Own Unit Tests

Left by Larry's WebLog at 4/13/2004 8:25 AM

# re: NUnitASP Tests ASP.NET

Left by sashi at 4/21/2004 4:11 PM

i am a newbie in using the NunitASP.

The ablove example shows how i could retrieve a value from a given LIstbox control.

i wanted to know how i could set the value of a ListBox Control to a particular value.

Thank You

# re: NUnitASP Tests ASP.NET

Left by Scott Willeke at 4/21/2004 11:37 PM

I think that the Items property of the ListBoxTester class is intentionally read-only since in practice an item cannot be added to a listbox using only the listbox. Instead, there would have to be a button or other control on the on the page that, when pushed adds a new item to the listbox. So similarly, in your tests, I would recommend you put a button the page that, when pushed would add the item you need to the listbox. This way you could use a ButtonTester to “click” the button to add the item to the listbox. If you want to be slick about it, I suppose you could make the button to do this only appear on the page if the tester sent certain special URL parameters to the page (maybe something like /mypage.aspx?testermode=true), this way the control used to add items to the listbox for testing purposes would only appear during testing. However, I think you should test the page as it is going to be used in production and therefore, if at all possible, you should not use such trickery to make your tests work.

Comments have been closed on this topic.