xUnit Browser Attribute – Run Cross-Browser WatiN tests effortlessly

Recently I wanted to run a web UI test across multiple different browsers using WatiN. WatiN supports FireFox, IE and Chrome so that wasn’t a problem, however in order to test the application on difference browsers I would have to duplicate the logic multiple times. This harms readability and maintainability of your tests and is just pain wrong. As such, I created a very similar xUnit Browser Attribute, code can be found on my GitHub repository along with the binaries.

The concept is simple, have the instance of the browser created for you outside of your test and provided the instance as a argument during execution. By using attributes, you can define multiple different browsers, each one will generate a separate test. The advantage of having the tests in this fashion means that if a test one particular browser fails then you can quickly see the problem and the results form the other browsers. If they where just a single test, if one part of  test failed, you wouldn’t be able to see the results for the other part. This can make identify where the problems lies much more difficult. An example of the attribute and a test is below.

public class Example
{
    [Theory]
    [Browser("IE")]
    [Browser("FireFox")]
    [Browser("Chrome")]
    public void Should_Click_Search_On_Google_And_Return_Results_For_AspNet(Browser browser)
    {
        browser.GoTo("http://www.google.co.uk");
        browser.TextField(Find.ByName("q")).Value = "asp.net";
        browser.Button(Find.ByName("btnG")).Click();
        Assert.True(browser.ContainsText("The Official Microsoft ASP.NET Site"));
    }
}

This example is made possible by taking advantage of the xUnit Extensibility model and being able to create objects dynamically in C#. The attribute code is below, as WatiN has a clean namespace structure creating an object based off the string of the name is easy.

public class BrowserAttribute : DataAttribute
{
    public string Browser { get; set; }
    public BrowserAttribute(string browser)
    {
        Browser = browser;
    }
 
    public override IEnumerable GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
    {
        Type type = Assembly.GetAssembly(typeof(Browser)).GetType("WatiN.Core." + Browser);
        return new[] { new[] {Activator.CreateInstance(type) }};
    }
}

With this attribute, you can now quickly and easily define the browsers you want the test to run against, without having to duplicate the test itself.

GUI Automation – A waste of time? (Potentially first of many posts)

Alan Page, a Microsoft Tester, recently posted about GUI Automation and I just wanted to provide my view. Alan’s main comment was:

“For 95% of all software applications, automating the GUI is a waste of time.”

Bold statement, but one I have to agree with – to a point.

Personally, I think we should automate UI’s, however, we need to be very clear and careful about what we automate and the tools we use. The most important part of UI testing is how you structure your tests and know your aim of the tests.

Generally, there are two types of automated testing tools. The first is the ‘record and playback’ approach, using tools such as QTP (HP QuickTest Professional). These tools have been around for a long time, and from my point of view has generally given automated GUI testing a bad name.

QTP records all the users interaction with the application (Web or Desktop) and scripts it out to scripting language built on top of VBScript file for playback.

Sadly the application doesn’t support sharing of steps which means you have to repeat the same actions within each test. If this same repeated action changes, you need to change delete and recreate all of your existing tests – something which is really frustrating when you are just about to release but need to change the name of a button.  This causes a lot of waste.

The other approach is more programmatic, where you program against an object model which interacts with the SUT (System Under Test). For example, with Watin, the html ‘’ turns into Ie.Link object. I’ve spoken before about WatiN and Project White, two of the talks I suggested for DeveloperDay are based on these topics.

As mentioned in the blog posts, these frameworks allow you to interact in a more domain driven way. They allow you to write the test in a reusable way using your application terminology making them much more readable and maintainable. However, from my experience its still relatively slow to start creating the tests.  Once they are created, it fine, but identitying the GUI controls and how to interact with them can take a while.

Are these tests worth writing? Or are they just a waste?

That really depends on your aim. Both approaches will get your good test coverage. The programmatic approach will produce much more maintainable tests which results in less waste.

One approach which I have recently been thinking about is having a set of core smoke tests, created using WatinWhite, focusing on core functionality of the application. These tests are just to ensure that the happy scenario of the application works, if someone picks up the latest build will they be able to use it? Or when it launches, is the first thing a user sees an unhandled exception?

For example, with Windows Live Writer, the test would create a new post, write some text, click publish and then verify the blog was posted. If that breaks, I really want to know, I want to know as soon as possible. I guess this is the 5% of UI tests.

The rest of the GUI (95% general waste) is automated using a similar approach to an APIbusiness logic. You are still automating the UI, but you are not interacting directly with the UI, this is covered by manual test cases, exploratory testing and generally making sure the application is useable – something which you can only do manually. I want to cover this in more details in a later post, but the CompositeWPF (Prism) project from Patterns and Practices is a great start.

Together, this should provide you with confidence that the application works as you expect and want in the most maintainable way.  If you can’t test the 95% using the correct patterns, then you might need to look at using WatinWhite for more than just core functionality.

As I said, this is just one approach, which has advantages and disadvantages.

UPDATE: I think I might have been wrong with my percentages, in fact ignore the percentages. There should be a bigger ratio of tests using WhiteWatin, but they should only focus on core functionality.

My main point was that these tests shouldn’t attempt to cover all possible inputs and outputs, their aim should be to give you confidence in your application and that it will work on a given platform. In order to have this confidence, you might want more tests, which is fine as long as you are structuring your tests correctly and using frameworks such as Watin.

Technorati Tags: , ,

WatiN Integration into MbUnitGallio Reports

One of the cool items I didn’t mentioned in my announcement post is that we now have the ability to integrate screenshots from a WatiN test into the reports.

Here we have a simple test which searches for MbUnit on Google and then asserts to check that NUnit is mentioned on the page (this fails).

[Test]
public void DemoCaptureOnFailure()
{
    using (Log.BeginSection(“Go to Google, enter MbUnit as a search term and click I’m Feeling Lucky”))
    {
        ie.GoTo(“
http://www.google.com”);

        ie.TextField(Find.ByName(“q”)).TypeText(“MbUnit”);
        ie.Button(Find.ByName(“btnI”)).Click();
    }

    // Of course this is ridiculous, we’ll be on the MbUnit homepage…
    Assert.IsTrue(ie.ContainsText(“NUnit”), “Expected to find NUnit on the page.”);
}

Normally, it would be hard to find out what was actually on the webpage at that point to see why the test decided to fail. In the tear down method, there is a check if the test passed or failed, if it failed then it takes a snapshot and includes it in the report.

[TearDown]
public void DisposeBrowser()
{
    if (Context.CurrentContext.Outcome == TestOutcome.Failed)
        Snapshot(“Final screen when failure occurred.”, LogStreamNames.Failures);

    if (ie != null)
        ie.Dispose();
}

When you view the report, on the test that failed you can see that the screenshot of the webpage has been included.  This will make debugging the error a lot easier, making the tests more useful.

image 

I think this is a great feature, well done to Jeff and the team for implementing this.

Technorati Tags: ,

How to Unit Test – WatiN, MbUnit and ASP.net

Today, I am going to be looking at WatiN, which stands for Web Application Testing in .Net, and seeing how well it actually works with an ASP.net web application.

WatiN is a type of record and playback framework to allow for automating the UI testing for web applications.  It uses IE and allows you to interact with the page, for example clicking buttons and typing in text.

A simple example from their documentation shows how to search for WatiN on google and assert you got the correct results back.

[Test]
public void SearchForWatiNOnGoogle()
{
using (IE ie = new IE(“http://www.google.com”))
{
  ie.TextField(Find.ByName(“q”)).TypeText(“WatiN”);
  ie.Button(Find.ByName(“btnG”)).Click();
  Assert.IsTrue(ie.ContainsText(“WatiN”));
}
}

You can use any test framework to get started, with MbUnit you simply write the tests as normal, but in your test fixture attribute you need to set the ApartmentState to STA. ApartmentState is part of .Net which states how the thread should execute. STA means that the thread will create and enter a single threaded apartment, everything will just be kept on the single thread. 

[TestFixture(ApartmentState = ApartmentState.STA)]

If you don’t have this set, when you run your tests you will receive the following exception:

Message: The CurrentThread needs to have it’s ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer.

Type: System.Threading.ThreadStateException
Source: WatiN.Core
TargetSite: Void CheckThreadApartmentStateIsSTA()

Now we have running tests, we can start to look at testing a ‘real’ application. Below is the screenshot of the application under test (AUT).

image

Entering information would cause the page to look like this:

image

Very simple.  To test this worked correctly, we would want to simulate what the user is doing and to verify it worked the same way a person would, in this case that it displayed the search term typed into the text box.

First we need to find the text box (called searchText) by it’s name and enter a string.  We then find the button (by its value – the text displayed to the user and not the ID, the button ID is in fact Button1) and click it.  We then verify the response.

[Test]
public void WatiNSearchText_SearchWatiN_TextDisplayedOnScreen()
{
    IE ie = new IE(“
http://localhost:49992/WatiNSite/”);

    // Find the search text field and type Watin in it.
    ie.TextField(Find.ByName(“searchText”)).TypeText(“WatiN”);

    // Click the search button.
    ie.Button(Find.ByValue(“Search”)).Click();

    //Verify it contains search term.
    bool result = ie.Text.Contains(“WatiN”);
    Assert.IsTrue(result);
}

The URL points to the ASP.net development server for the solution, with a static port set.

image

That works with simply html, but what happens when ASP.net is pain with the naming. When using a master page with ASP.net, you place all of the pages content within a ContentPlaceHolder. When ASP.net renders this, to ensure naming of elements does not clash it prefixes the IDs.

Without using the placeholder, the textbox html is:

However, after using master pages it becomes:

Not great! All the elements are referred as strings, by moving to master pages all of our tests would break. WatiN will report this as:

Message: Could not find a ‘INPUT (text password textarea hidden) or TEXTAREA’ tag containing attribute name with value ‘searchText’

One solution has been provided by James Avery in his WatiN Test Pattern post.  Here, he basically says that each page in the website should have a adapter in the test code which we code against which in turn calls the page (this is not mocking the page).  It means that changes to the website, such as naming, requires only changing the adapter class to match.  Following his pattern, the test would be:

[Test]
public void WatiNSearchText_SearchWatiN_TextDisplayedOnScreen2()
{
    Default page = new Default(“
http://localhost:49992/WatiNSite/”);

    page.SearchText.TypeText(“WatiN”);

    page.SearchButton.Click();

    bool result = page.Text.Contains(“WatiN”);
    Assert.IsTrue(result);
}

Its a lot easier to read as everything is referred to as the page and you can easily imagine what is happening.  The adapter looking like this:

public class Default : IE
{
    public TextField SearchText
    {
        get { return TextField(Find.ByName(“searchText”)); }
    }

    public Button SearchButton
    {
        get { return Button(Find.ByValue(“Search”)); }
    }

    public Default(string url) : base(url)
    {

    }
}

We could even take this a step on and abstract the searching into its own method which we call in the test.

    public void SearchFor(string term)
    {
        SearchText.TypeText(term);
        SearchButton.Click();
    }

The test would then be:

[Test]
public void WatiNSearchText_SearchWatiN_TextDisplayedOnScreen3()
{
    Default page = new Default(“
http://localhost:49992/WatiNSite/”);

    page.SearchFor(“WatiN”);

    bool result = page.Text.Contains(“WatiN”);
    Assert.IsTrue(result);
}

This does solve some of the problems as it makes the tests less dependent on the application code.  However, the ASP.net naming is still getting in the way. If we add another container or the element is inside a custom control we are still going to have a problem.  The answer is RegEx!

In our adapter, I change the way we find the element to use a method RegExName. Now its Find – ByName – RegExName – ElementName.

public TextField SearchText
{
    get { return TextField(Find.ByName(RegExName(“searchText”))); }
}

Our RegExName method just takes in the elementname and return a regex which will ignore all of the ASP.net prefixes.

private Regex RegExName(string elementName)
{
    return new Regex(“.*” + elementName + “$”);
}

By using an adapter and RegEx we can abstract away from the real implementation and make our tests a lot more beneficial.  The tests are quite easy to write as long as you keep things focused. By arranging your tests as above, you should have a lot more long term success.

But having an automated test run for the UI will never replace a human tester as there are other scenarios to test for, cross browser, usability, wording which a test framework cannot test.

Technorati Tags: , , ,

WatiN and Vista

Been meaning to post this for a while now but haven’t found the time.  When trying out WatiN on my Vista machine I kept receiving the following error message:

WatiN.Core.Exceptions.TimeoutException: Timeout while ‘waiting for main document becoming available’

Turns out that WatiN and Vista don’t play nicely together and on Vista you will need to disable UAC in order for WatiN to execute correctly.

It kept me guessing for an hour so I thought I would post regarding this matter. Expect more posts on WatiN soon…

UPDATE: Or, if you don’t want to disable UAC, make sure your test runner is running as Administrator

Technorati Tags: ,,