Click here to monitor SSC

Adventures in Web Testing

Test Engineer at Red Gate Software Ltd.

Combining xUnit.net and Selenium

Published Tuesday, September 01, 2009 11:17 AM

There has been a fair amount of discussion about how to improve our test automation here in the Web Team at Red Gate. One of the avenues that we are keen to go down is browser automation.

In the browser automation arena, the two big players for .NET web applications are WATIN (Web Application Testing In .Net) and Selenium. In a recent blog post, Ben Hall describes an xUnit attribute that allows you to run WATIN tests across multiple browsers, simply by providing the desired browser as an argument to your test method.

I took Ben’s code for a test drive, and really liked how concise the resulting tests were. However, there are well-documented advantages to using Selenium as your browser automation framework, so I decided to have a go at re-writing Ben’s [Browser] attribute to target Selenium instead.

Writing your own xUnit attribute is deliberately quite straightforward. Each attribute’s abstract base class is public, allowing you to easily write your own implementation. In this case we’re interested in the DataAttribute class.

The DataAttribute class only contains one abstract method that needs overriding, namely:

public abstract IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes);

So our implementation needs to return an object[] containing the selenium browser object to pass into our test:

public class BrowserAttribute : DataAttribute
{
 
private ISelenium Browser { get; set; }

 
public BrowserAttribute(string browser)
 
{
   
string url = "http://www.google.co.uk";

   
switch (browser)
   
{
     
case "Internet Explorer 7":
     
Browser = new DefaultSelenium("localhost", 4444, "*iexplore", url);
     
Browser.Start();
     
break;
     
case "Firefox 3.5":
     
Browser = new DefaultSelenium("localhost", 4444, "*firefox", url);
     
Browser.Start();
     
break;
     
case "Google Chrome":
     
Browser = new DefaultSelenium("localhost", 4444, "*googlechrome", url);
     
Browser.Start();
     
break;
     
case "Opera":
     
Browser = new DefaultSelenium("localhost", 4444, "*opera", url);
     
Browser.Start();
     
break;
   
}
  }

 
public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest,
Type[] parameterTypes)
 
{
   
return new[] { Browser };
 
}
}

The above implementation is enough to allow us to write nice clean tests, like this (note that I pass the iSelenium parameter into the Browser object purely for post test clean up purposes, which I won’t worry about showing here):

[Theory]
[Browser("Internet Explorer 7")]
[Browser("Firefox 3.5")]
[Browser("Google Chrome")]
[Browser("Opera")]
public void Google_For_SimpleTalk(ISelenium iSelenium)
{
    Browser = iSelenium;

    Browser.Open("/");
    Browser.Type("q", "Simple Talk");
    Browser.Click("btnG");

    Browser.WaitForPageToLoad("5000");

    Assert.True(Browser.IsTextPresent("www.simple-talk.com"));
}

This version of the Selenium [Browser] attribute is obviously not very robust, as it has the URL of the Google homepage hard-coded. Moreover, it is currently only able to take advantage of the browser versions currently installed on my local machine. Whilst these versions are the most popular amongst the visitors to our sites, they are by no means the only ones. Another drawback is that, in its current form, the attribute causes all the requested browser instances to be created before any of the executions of a test case occur.

Once I had this basic version up and running, my next task was to extend it to address these issues, so that we can begin to utilise it in our production test environment. In my next post I’ll go through how I did that!

Comments

 

Melvyn.Harbour said:

Looks like being a good series of articles. Obviously I have a slight 'inside-track', but I'm particularly looking forward to the follow-up articles on using different machines across a network to perform the different browser tests.
September 2, 2009 7:42 AM
 

Adventures in Web Testing said:

In yesterday's post I talked about an xUnit [Browser] attribute that wraps Selenium, taking care of setting...
September 2, 2009 10:52 AM
You need to sign in to comment on this blog
<September 2009>
SuMoTuWeThFrSa
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
Automated Script-generation with Powershell and SMO
 In the first of a series of articles on automating the process of building, modifying and copying SQL... Read more...

Converting String Data to XML and XML to String Data
 We all appreciate that, in general, XML documents or fragments are held in strings as text markup. In... Read more...

Geek of the Week: Don Syme
 With the arrival of F# 3.0 Microsoft announced a wide range of improvements such as type providers that... Read more...

How to Document and Configure SQL Server Instance Settings
 Occasionally, when you install identical databases on two different SQL Server instances, they will... Read more...

What's the Point of Using VARCHAR(n) Anymore?
 The arrival of the (MAX) data types in SQL Server 2005 were one of the most popular feature for the... Read more...