Have you ever successfully built your project and had all your unit tests run green only to find out your app blows up as soon as you try to login? Wouldn’t it be great to have a “smoke test” that automatically verifies that the user can actually get to the web app and login? Using the free open-source Watin (pronounced “watt inn”) in your test project, you can automatically test how a user interacts with your web app, including logins, page loads, button clicks, and form submits, using a real browser. Furthermore, Watin uses the ID or text of the HTML elements on the page to fill in textboxes, click buttons, and so on, which means you can change the location of elements on your page without having to update your UI tests.
Here’s how you do it.
Watin and NUnit
First, add nunit.framework.dll, WatiN.Core.dll, and Interop.SHDocVw.dll to your Assemblies folder and reference them in your test project. You can download the current version of Watin from here and NUnit from here.
You don’t need Resharper to run NUnit tests, but it’s nice. You can download a trial version of Resharper from here.
Next, we set up our app.config for Watin.
Add this section to the
configSections node in configuration:
<section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
Then, since the Internet Explorer browser instance needs to run in single thread mode, add this section after the
configSections node within the configuration node.
<add key="ApartmentState" value="STA" />
Finally, since our root URL may change based on the environment (such as the integration server), add this key to the
<add key="RootURL" value="http://localhost/1423/"/>
Our Base Test
Next, we create a
BaseUITest which holds our Internet Explorer instance that is used by all the tests to actually open a browser and hit our web app. We don’t want browsers popping up all over the place while we’re trying to work while the tests are running, so we need to set
false right before we open our browser instance. This will hide all instances of our test browser while the tests are running. If you want to see a phantom user opening browser windows and filling out forms (which is pretty cool to watch), comment out this line or set it to
Settings.Instance.MakeNewIeInstanceVisible = false;
Our individual tests will use the same browser session and navigate to different pages using a single browser instance. In our tests, we want to start out by hitting our login page (and probably want to also log in if the rest of your website requires a log in to proceed):
browser = new IE(rootURL + "Account/LogOn");
Finally, you should always wait for the page or action to complete, or you may get errors during runtime:
TestFixtureTearDown, we close any open browser instances (even if they are hidden). Note: This will close any Internet Explorer browsers you’re working in on your desktop, but Internet Explorer will allow you to restore those sessions as soon as you reopen your browser:
if (browser != null)
Our UI Tests
TestAccount class, we are going to create a smoke test that verifies that we can:
- reach the login page and
- actually log in.
First, we create the
TestAccount class which extends our
BaseUITest. We create a method decorated with the Test tag called
CorrectlyGetsToLoginPage which simply goes to the login page, waits for the page to load, then verifies that the page contains the phrase “Log On” and is titled “Log On”.
public void CorrectlyGetsToLoginPage()
browser.GoTo(rootURL + "Account/LogOn");
Assert.IsTrue(browser.Title == "Log On");
Next, we create the
CorrectlyLogsIn test method which first goes to the login page, waits for the page to load, finds the username and password textboxes and populates them with the appropriate values. Notice that the test finds the textboxes by the ID of the HTML element, which means your UI designer can keep changing the UI as much as they want and you will never need to update the test with a new element location as with other test products.
browser.GoTo(rootURL + "Account/LogOn");
Then, we find the submit button and click it. Notice that in this case, we find the submit button by value (i.e., the text of the input element) because we don’t happen to have an ID set on that control. Be aware that there are issues with the Internet Explorer instance, so we want to use the
WaitForComplete methods instead of the simple
Click method (watch out for sample code on the internet that uses Click, you may see errors with it at runtime).
Finally, we verify we went to the right page and that it has the name of the user we logged in as.
Running the Tests
The only gotcha I ran into that I wasn’t able to resolve easily in our environment is that the Watin tests need to run in the NUnit app as “Interact with desktop” and with a user logged in. This means Watin tests run fine when running with Resharper’s Run Unit Tests on your desktop, but they won’t run on Cruise Control if runs as a service under a specific user. Unless you want to change how your Cruise Control runs, you can do one of two things:
- You can mark your Watin tests with the Ignore tag, which means they will be skipped with normal tests, but can be run manually with the Resharper plugin for Visual Studio by right clicking on them and hitting "Run Selected Tests".
- You can move your Watin tests into a separate test project (as we did in this demo) which is not called by your Cruise Control build project. This way Cruise Control never calls your Watin tests, but your Watin tests will always run when you use Resharper’s "Run All Tests In Solution" on your desktop.
If you fire up your ASP.NET Development Server and run your unit tests, you should see all UI tests green.
- 28th August, 2010: Initial post