In this article, I have explained how we can use WaTiN for test automation by writing a small wrapper utility over the core WaTiN functionalities. WaTiN stands for “Web Application Testing in .NET”, and is derived from WaTiR which is “Web Application Testing in Ruby”. The WaTiN libraries can be downloaded from WatiN Libraries.
One of the issues faced while writing an Automation Test Suite is locating the controls and then checking the functionality. It is accentuated by the fact that our test fails because the automated test is unable to find a particular control in the application, in-spite of the fact that the developer has added it. A good way to tackle this issue is by writing a small wrapper class over the WaTiN library and using this class in the automated tests.
I have used WaTiN in conjunction with NUnit, and there’s already an article for this - NUNIT and WatiN.
Using the Code
The wrapper utility is mainly a set of four classes along with a small Strings project. One of the classes is
ConfigurationReader; I am using it so that I can specify the website URL, database connection string, user name, password etc., in the app.config. This way, we can modify the app.config for use in any application and need not modify the source code if the same application is deployed at different web servers.
public static class ConfigurationReader
#region Public Methods
public static string getHomePageUrl()
return getConfigurationValue( "WebSiteUrl" );
public static string getConnectionString()
return getConfigurationValue( "ConnectionString" );
Then, we have an
Enumerators class. This class basically has a list of controls that have been used in the application and have to be automated or have some functionality associated with them.
public class Enumerators
public enum ControlType
Now we have the
UseDialogOnce class; this is a third-party code I found on the internet. Basically, this class helps on handling pop-up dialogs and closing them as specified. Here is the link: UseDialogOnce.
Now, the core
Utilities class. This class is the heart of the wrapper solution I am proposing. In this class, we have methods which act as wrapper methods over the core WaTiN methods, and help in locating the controls by ID, Custom etc., as WaTiN allows us to. The advantage of this class is that I check if the control exists before returning the object to the actual test we have written, thereby giving the exact message as to what was not found. Also, in this class, there are multiple overloads to locate the specified control inside a browser instance, or a dialog page, or a table, or an
IFrame, and so on. There can be more overloads as required.
The first method of significance is
NavigateToHomePage. This method can be called from the test classes we write, passing a reference to the existing browser instance. Other than that, it also checks if the browser instance exists or not; if not, it creates a new instance and navigates to the home page of the application. The home page URL can be taken from the app.config, as I mentioned earlier.
public static void NavigateToHomePage( ref IE ieBrowser )
if ( ieBrowser == null )
ieBrowser = new IE();
ieBrowser.ShowWindow( NativeMethods.WindowShowStyle.Maximize );
ieBrowser.GoTo( ConfigurationReader.getHomePageUrl() );
Another major method of this class is
FindControlInBrowserById. Similar to this method, there are other methods like
SelectControlInBrowserByID etc., I won’t be going into the details of each method. Below is the
public static object FindControlInBrowserByID( IE ie, string strID,
Enumerators.ControlType ctrl )
if ( ctrl == Enumerators.ControlType.Span )
Span sp = ie.Span( Find.ById( strID ) );
Assert.IsTrue( sp.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.Link )
Link lnk = ie.Link( Find.ById( strID ) );
Assert.IsTrue( lnk.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.Frame )
Frame iFrame = ie.Frame( Find.ById( strID ) );
else if ( ctrl == Enumerators.ControlType.Image )
Image img = ie.Image( Find.ById( strID ) );
Assert.IsTrue( img.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.TableCell )
TableCell tCell = ie.TableCell( Find.ById( strID ) );
Assert.IsTrue( tCell.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.Table )
Table tbl = ie.Table( Find.ById( strID ) );
Assert.IsTrue( tbl.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.TableRow )
TableRow row = ie.TableRow( Find.ById( strID ) );
Assert.IsTrue( row.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.CheckBox )
CheckBox chk = ie.CheckBox( Find.ById( strID ) );
Assert.IsTrue( chk.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.Button )
Button btn = ie.Button( Find.ById( strID ) );
Assert.IsTrue( btn.Exists, "Could not Find: " + strID );
else if ( ctrl == Enumerators.ControlType.TextField )
TextField txt = ie.TextField( Find.ById( strID ) );
Assert.IsTrue( txt.Exists, "Could not Find: " + strID );
On the same lines, there are methods like
AddTextInTextBox etc. The
ClickLink method clicks a link in the browse, or table, or dialog page as specified.
SelectControlInBrowserById is useful for controls which have an action associated with them and we need to perform that action to proceed to the next step in the test.
AddTextInTextBox, as the name suggests, adds the specified text in the textbox control specified by the ID.
Finally, how to use this wrapper we have written. It's pretty easy to do that; below is a sample code of a simple create record test:
public class JailRecordTest
public void SetUp()
[Description( "Verify the Title of the HomePage" )]
public void Verify_HomePage_PageTitle()
Assert.AreEqual( AppStrings.HomePageTitle, ie.Title );
[Description( "Create a New Instance of Jail Record" )]
public void Create_New_JailRecordTest()
Frame appFrame =
( Frame )Utilities.FindControlInBrowserByCustom( ie, "name",
AppStrings.AppFrame, Enumerators.ControlType.Frame );
Table menuBarTable =
( Table )Utilities.FindControlInFrameByID( appFrame,
AppStrings.AppMenuBar, Enumerators.ControlType.Table );
Image newButtonImage =
( Image )Utilities.FindControlInTableByID( menuBarTable,
ie = IE.AttachToIE( Find.ByTitle( JailRecordStrings.NewJailRecordPageTitle ) );
Utilities.AddTextInTextBox( ref ie,
JailRecordStrings.NewJailRecordJailIdTxtBox, "Demo Record" );
Table jailRecordMenuBar =
( Table )Utilities.FindControlInBrowserByID( ie,
JailRecordStrings.NewJailRecordMenuBar, Enumerators.ControlType.Table );
Image saveAndCloseButtonImage =
( Image )Utilities.FindControlInTableByID( jailRecordMenuBar,
ie = IE.AttachToIE( Find.ByTitle( AppStrings.HomePageTitle ) );
#region Private Methods
private void StartProcess()
Utilities.NavigateToHomePage( ref ie );
public void TearDown()
This test was written for automating a CRM like web application, so we had to locate the frame first, then the control, primarily to improve the performance of the test. So first, we find the frame, then the control inside it, and finally, we have a
MenuBar which has a “New” button. We find the button and click it. After clicking it, a new browser window is opened, hence the
IE.AttachToIE method is used. In the new browser window, we enter the required data and then find the “Save” button as we had found the “New” button, and save the record. The verification part, if the record has been created, can be done quite easily, by looking up for the record name in the grid shown on the main page (CRM specific – that’s why I have removed that portion from the code). Now, if you analyze the code, if we had used only WaTiN instead of the wrapper utility, we would have ended up with approximately 100 lines of code in the Test method, and it would have been very confusing as to where we are locating the actual controls and then checking their functionalities. With this wrapper, the Test method is reduced to less than half of that, and the best part is that, the utility can be used across the entire web application.
I hope this Wrapper utility helps my fellow Test Automation developers, and is useful in automating complex web applications. Any suggestions or improvements, I can be contacted anytime. Thank you.
Points of Interest
As I did mention earlier, finding a web control in a web application is one of the toughest parts for a Test Automation Developer. The only way to ensure that your automated test runs alright is to make sure that the developers always provide an ID for the web control they are using in the web application. I had a really tough time convincing developers to make it a practice.
Also, we were using Telerik and Rad Controls in our applications extensively. Automating them was a very big issue, as it's difficult to find the way they are rendered (even with the IE Developer Tool). I could discuss that in another article, if required.
The WaTiN DLL I have used in this project is 18.104.22.16800; as of now, the latest release is 2.0 Beta 1. I will be upgrading the project to use that soon.