I've started using
NUnitAsp to do some tests for an ASP.NET program at work. It's a pretty neat little tool that allows you to build unit tests for your web pages. If you've ever used
JUnit or
NUnit before, this actually uses the same concept, but instead of testing a class, you write tests for your .aspx page.
How it works:The testing is done by automating actions that a web user would do, such as entering text, selecting drop downs, and clicking buttons. You can build your tests in a new DLL project that doesn't reference any of your actual code behind. Each web page can have it's associated test class. To run the tests, you load the DLL using your NUnit-Gui (you do use NUnit right?) and just run it like any other test suite. It then goes through all your test methods and shows either passes or failures.
Most of the built in
System.Web.UI.WebControls ASP.NET controls are supported, as well as some of the HTMLControls. You can manipulate all these controls programatically in your unit tests, just as you would in a web browser. You can insert text into text boxes, select drop downs, and click buttons and links, and test to see that the desired results are displayed on the next page refresh.
What you can test:Before you jump into NUnitASP, first you should know what it is and is not capabale of doing. Each test case inherits the Nunit Assertion class, so all NUnit assertion methods can be used. In addition, there are four different types of WebAssertions specific to testing ASP pages, three which are helpers for dealing with string arrays (for data grids), and AssertVisiblity. This last one is probably the most important, since it applies to every test control. You can use it to test the dynamic display of your web controls.
Also, all the properties of the test web controls are available to be tested. This includes whether they are enabled, their value, and other properties that are part of the underlying HTML code.
Other things you can test are the browser properties, such as the current URL (for form redirection), and the raw HTML if there is anything else you want to test that isn't provided in the framework.
What you can't test:The support for HTMLControls is pretty much non-existant. This includes uploading files, hidden inputs, and other still useful objects that didn't make the Microsoft's WebControl cut.
The browser also doesn't perform javascript. This can be a bit of a pain, since this means that some of your validation may not work. (But you don't need to worry about this because you are using post back validaton too, right?). So don't even bother using this to test your AJAX applications. I should emphasize that NUnitAsp is primarily for testing code behind, and not the client-side display magic.
The combination of these two don't-haves can cause trouble for many web applications. The application I was working on used javascript on the Login Form page. Basically, it was performing a hash algorithm on the password before sending it to the server because the client didn't want to use https. The algorithm also relied on hidden inputs to transport the encrypted data. In order to get this app to work with NUnitAsp, I basically had to copy the javascript encryption code into the NUnitAsp test classes, and perform the hash before assigning it to the text box. And since there is no support for hidden fields, I used a TextBox of width zero to store the encrypted value. After these changes, the automated login worked fine and I could continue writing other tests.
How it really works: Every ASP.NET control that you plop onto your web page has an ID that you can customize. NUnitAsp's browser parses the HTML from your web page, and is able to determine the controls that you placed on your page, based upon those IDs and other features.
LinkButtons are a little different. If you notice the generated HTML of your pages, you will see that when you click a link button, it actually calls the following:
javascript:__doPostBack('lnkButter',''). Well when I said before that their WebBrowser had no javascript support, I kind of lied. There is support for this command, which I believe is interpreted within (instead of actually executing the javascript). This javascript function adds the following POST arguments to the form submit:
- Request.Form["__EVENT_TARGET"] = "lnkButter"
- Request.Form["__EVENT_ARGUMENT"] = ""
The order they are added through the NUnitAsp Browser is a little different than Internet Explorer though which actually caused me a little problem when I was looking for a link name in Request.Form[0] and couldn't figure out why my test case kept on failing whereas it always worked fine in ie. In retrospect I shouldn't have been so lazy and should have used the proper key, but I reported this as a potential bug just in case.
When you should use itFrom my experience, NUnitAsp can help you most if you have a suite of tests early in the development cycle, and anticipate there to be changes in the underlying structure.
For example, the application I was working on had a dependency on underlying Business objects and Data Access objects that were generated on the database schema. Every week or so the client would request a new feature or a change to the feature which cause a change to the database schema. Once the objects were regenerated, and the UI code was modified to compile, sometimes trying to access web pages would crash because they were depending on fields that no longer existed, or more often they were not setting values that they should have been. A suite of simple NUnitAsp tests can catch these failures right away.
Another reason where NUnitAsp tests are handy is when you have a lot of dynamic display controlled by code behind. If there are multiple panels, buttons disappearing or disabling, form editing, submitting, and in general lots of actions going on, it really helps to have a set of tests for each action to ensure that the correct items are displayed before and after. I find it's always possible to forget to refresh the state of controls after performing an action, so a set of tests will help you find these and maintain sanity on complex pages.
When you shouldn't use itMore importantly, knowing when not to use NUnitAsp could save you many hours of wasted development.
As I mentioned before, there is no javascript support so if you have lots of client-side code doing calculations and other logic, you may have to replicate all this code within your unit tests. You would also have to convert the code from javascript to C# which is no easy task in itself. I would avoid testing pages with lots of javascript for this reason.
Also, if your pages are simple, then it probably isn't worth the time to build an entire unit test for the functionality. Say the page is for registration - a bunch of fields that you collect, validate, and store in a database and never touch again. This is an example where a unit test may not be necessary since there aren't any dynamic factors in play. It doesn't hurt to build one, but if you only have time to build so many tests, this is the type of page I would add last.
If your site is small, then again manually asserting functionality is probably the best option. NUnitAsp works best when there are many pages to keep track of with shared code. Making one change can often cause problems somewhere else. When pages are small or isolated, you get less value from using NUnitAsp.
Another obvious thing to mention is that you must be able to automate your web pages. If your site has some control that displays an image with text that the reader has to enter into a text box, you won't be able to run an NUnitAsp test on this (unless you only want to test failures.)
I hope I have given a good overview how you can use NUnitAsp to enhance your development process. In the next week I will give a list of tips for developing NUnitAsp, that should make it even easier to integrate into your current project.