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
Finding Stuff in SQL Server Database DDL
 You'd have thought that nothing would be easier than using SQL Server Management Studio (SSMS) for... Read more...

Mission Critical: SQL Server 2008 Performance Tuning Task List
 In which Buck Woody imagines how the US military would have tackled DBA checklists for... Read more...

Simple Query tuning with STATISTICS IO and Execution plans
 A great deal can be gleaned from the use of the STATISTICS IO and the execution plan, when you are... Read more...

Switching rows and columns in SQL
 When they use SQL Server, one the commoner questions that Ms Access programmers ask is 'Where's the... Read more...

Writing Efficient SQL: Set-Based Speed Phreakery
 Phil Factor's SQL Speed Phreak challenge is an event where coders battle to produce the fastest code to... Read more...