Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / testing

Automated UI tests with Watin in ASP NET MVC

4.83/5 (5 votes)
28 Aug 2010CPOL5 min read 44.7K   854  
How to create automated browser tests in ASP NET MVC using Watin

Introduction

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.

App.Config

Next, we set up our app.config for Watin.

Add this section to the configSections node in configuration:

XML
<sectionGroup name="NUnit">
    <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>

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.

XML
<NUnit>
<TestRunner>
    <!-- Valid values are STA or MTA (Others are ignored) -->
    <add key="ApartmentState" value="STA" />
</TestRunner>
</NUnit>

Finally, since our root URL may change based on the environment (such as the integration server), add this key to the appSettings node:

XML
<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 MakeNewIeInstanceVisible to 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 true:

C#
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):

C#
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:

C#
browser.WaitForComplete();

In the 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:

C#
if (browser != null)
{
    browser.ForceClose();
}

Our UI Tests

In our TestAccount class, we are going to create a smoke test that verifies that we can:

  1. reach the login page and
  2. 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”.

C#
[Test]
public void CorrectlyGetsToLoginPage() 
{ 
     browser.GoTo(rootURL + "Account/LogOn");
     browser.WaitForComplete();
     Assert.IsTrue(browser.Title == "Log On");
     Assert.IsTrue(browser.Text.Contains("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.

C#
browser.GoTo(rootURL + "Account/LogOn");
browser.WaitForComplete();
browser.TextField(Find.ById("username")).TypeText("robert.corvus");
browser.TextField(Find.ById("password")).TypeText("secretpw"); 

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

C#
browser.Button(Find.ByValue("Log On")).ClickNoWait(); 
browser.WaitForComplete();

Finally, we verify we went to the right page and that it has the name of the user we logged in as.

C#
Assert.AreEqual(rootURL, browser.Url);
Assert.IsTrue(browser.Text.Contains("Welcome robert.corvus!"));

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:

  1. 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".
  2. 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.

History

  • 28th August, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)