Selenium 2 in .NET framework
I’m not Dave but you might have met me at one of the London Selenium meets. My name is Zac and I have several years of automated testing experience with Selenium RC in Java and C# and am now intending to be one of the early adopters of Selenium 2 using the .NET version.
Selenium 2 and .NET are up to alpha4 already but thorough examples of code on the internet are a bit thin on the ground so far compared to the Java equivalent. In my time using Selenium RC and now Selenium 2 I have built up a framework to support it.
I consider it to be an intermediate-level framework for using Selenium 2, NUnit and the Page Object model together so some advanced users might find it a bit basic. You may have even seen some of these concepts as snippets on testing blogs around the place. But overall it offers a framework from which to develop an easily maintainable suite of tests using the Page Object model (which is now considered to be the best practice for Selenium 2). If you already have a suite of Selenium tests in flat files that is spiralling in size and you are looking to make it more durable and more efficient then this could suit you.
With this blog post I intend to step through and get you started with this framework.
The Visual Studio solution
Exactly as we did with a Selenium RC project in Visual Studio, we need to create a new ‘Class Library’ solution to work with. To get the same naming layout I have, in the Name field type “Selenium2” and in the Solution Name field type “Automated Test Suite”.
The solution now needs references to both Selenium 2 and NUnit before we get started so if you haven’t already downloaded them then scurry off and do that now.
Unzip the NUnit and Selenium 2 folders into your solution directory and add the references to the files from inside VS so it looks like the screenshot. Even though Selenium 2 is called Selenium 2, the reference files you need are confusingly prefixed with WebDriver (WebDriver.common, etc)! But they definitely are the ones you’re after.
The class titled Selenium2TestBase.cs is used to setup and deliver the Selenium 2 driver to the test.
It’s a good chance to set up your driver with any profile extensions or configuration changes like bumping up the default timeout.
Page Object GoogleHome.cs
The Page Object class contains all of the driver actions on that page as methods. The aim is to keep each method concise and true to their purpose and cut down on duplicated code. The Selenium2 driver is passed in from the test when the class is instantiated. I have used static page objects that do not return the driver. Alternatively you can use the technique covered here. Also, here’s a Selenium RC example.
To keep this example simple I have created only one Page Object but a typical application will have several. I have also stored the Object’s Xpath locators as private readonly strings inside the Page Object in order to keep it simple and concise but if you have a large amount of them to juggle you may want to use a separate static class.
This SetupFixture class (denoted by the NUnit tag [SetUpFixture]) runs before the tests themselves. I mainly use this feature to configure Common variables that are specific to this project. There is more information about how these are managed further on in the post.
Finally, the test itself!
Now that we have the page actions (in Page Objects) and driver management abstracted (split up) into their own classes we can actually write the test!
The TestFixture which contains the test keeps the familiar NUnit TestFixtureSetUp and TestFixtureTearDown that you would have used in Selenium RC to setup and teardown the browser, meaning that a new browser will be built for each test. Note that my example inherits Selenium2TestBase, but you could easily instantiate the class if you prefer.
The test itself uses the GoogleHome Page Object to do a basic search. The details of the search are not important - I will presume that you know how to write a test already.
But don’t despair, we’ll post more advanced uses of Selenium 2 in tests on the SeleniumExamples blog as we use it more and more!
Getting around an NUnit limitation
One thing that bothers me about NUnit is that I can’t change the browser or test environment from the NUnit GUI without having to rebuild the project. I guess this is not a requirement for a unit test. Perhaps we’re pushing the boundaries using NUnit for cross browser functional testing.
However we can use a simple config file to call in variables, commonly the browser, environment or whitelabel details of a site. In the XML config example below I have key value pairs for both the browser and the base URL for the test environment (ie dev, stage, live).
NUnit can be a bit sensitive to the config file’s directory location. You can see from the Solution Explorer screenshot that it is placed in the top folder and named “Automated Test Suite.config”. The settings in NUnit > Project > Edit… must reflect the config file’s location and name.
When you update the config file between tests you will need to reload the project in the GUI (Ctrl-P) to use the config changes.
The Common classes
You may have noticed that the project references two ‘Common’ classes in various places.
In the (static) Common class I store variables that are shared across the whole Selenium2 namespace. For example here the TimeSpan value for timeouts is kept and I can reference it from elsewhere. This way the driver and any custom methods I have written will all use the same timeout value from the Common class.
In other cases I might include the Common variables as part of the expected criteria in assertions which cuts down on hard coded criteria.
Often you will find yourself writing tedious bits of code over and over again. By adding an extension to IWebDriver you can call methods in the same manner, keeping the code clean and readable.
With this solution it is quite easy to set up tests for numerous web apps within the solution.
Add a new folder at the same level as the Google folder in my example and add the Page Objects and tests inside it. Follow the same structure as the Google example and both applications can share the Selenium2TestBase, WebDriverExtensions, config and Common classes that you have already written.
Cutting down on duplicated code will save you tons of time in both writing and maintaining your tests!