I recently started playing around with WatiN (Web Application Testing in .Net) and WatiN Test Recorder.  While these are cool tools that can greatly improve the testing process, I found that there isn’t a lot of information out there to help get started.  I have put together a brief tutorial on some of the basics.  I hope it helps.  I’m including code samples in this post, plus you can download the entire VS Solution and a short video below.


WatiN, pronounced “What-in”, is a library that allows you to create tests for web applications.  It is based in WatiR which was created for Ruby.  Basically, you can test your web pages just like any other classes.  In my case, I’ll use NUnit to control the actual tests but they are written with WatiN.  The tests run in the browser via a class named “IE”.  That immediately points out one of the downsides to WatiN — it only works with Internet Explorer.  But the tests run in a real browser so it is very accurate.


Here’s a quick code sample:
            IE ie = new IE(“http://localhost/somewebsite/default.aspx”);
            ie.Link(Find.ById(“LinkButton1″)).Click();


If you run that in a test, the browser will actually open, navigate to the default page, find the LinkButton and click it.  Seems pretty simple right?  It isn’t too complicated but you’ll have to get used to the WatiN classes and methods.  The fact is, the tests are a pain to write.  That’s where WatiN Test Recorder comes in.  All you have to do is start the recorder and the tool will begin to record your actions in the browser (there is a browser built into WatiN Test Recorder) and translate your actions into code.  If you click LinkButton1, the recorder outputs “ie.Link(Find.ById(“LinkButton1″)).Click();” for you!  This is a big help but it is not exactly perfect.  I have found that it doesn’t get the code right and some tweaking is needed.  I’m starting to get the hang of it so the changes to the code are getting easier. 


Sample Code and Downloads:

Download my VS 2005 solution:  WatiNDemo.zip  167KB
Download my Video of WatiN Test Recorder in action:  WatiNTestRecorderDemo.avi (Right click and “save target as”)  2.22MB


I created a simple data entry web application with 2 pages that pretends to register users to a web site for outdoor enthusiasts.  The first page lists the registered users, the second page is a form to register:


image image


I want to make sure my data entry page works, so I fire up WatiN Test Recorder.  The video (see the link above) shows what happens in the recorder as I step through the page  and enter the data into the web form.  Here is the code that the recorder generated for me, with line numbers added here for reference:

          1   IE ie = new IE(“http://localhost:49573/RegisteredList.aspx”);
2 ie.Link(Find.ById(“LinkButton1″)).Click();
3 ie.TextField(Find.ById(“txtFirst”)).Click();
4 ie.TextField(Find.ById(“txtLast”)).Click();
5 ie.TextField(Find.ById(“txtLast”)).TypeText(“andy”);
6 ie.TextField(Find.ById(“txtEmail”)).TypeText(“schwam”);
7 ie.TextField(Find.ById(“txtEmail”)).Click();
8 ie.TextField(Find.ById(“txtEmail”)).TypeText(“andy@email.com”);
9 ie.RadioButton(Find.ByName(“rdoSendInfo_0″) && Find.ByValue(“yes”)).Checked = true;
10 ie.TableCell(Find.ByCustom(“innertext”, ” Choose New Jersey Pennsylvania”)).Click();
11 ie.SelectList(Find.ById(“ddlState”)).SelectByValue(“Pennsylvania”);
12 ie.SelectList(Find.ById(“ddlCounty”)).Click();
13 ie.SelectList(Find.ById(“lstHobbies”)).Click();
14 ie.SelectList(Find.ById(“lstHobbies”)).Click();
15 ie.SelectList(Find.ById(“lstHobbies”)).Click();
16 ie.SelectList(Find.ById(“lstHobbies”)).Click();
17 ie.Button(Find.ById(“btnSubmit”)).Click();
18 ie.Link(Find.ByUrl(“javascript:__doPostBack(‘GridView1′,’Select$0′)”)).Click();
19 ie.Link(Find.ById(“LinkButton1″)).Click();

Fixing the Generated Code:




  • Line 1 and 2 are good:  Open Internet Explorer and navigate to my page.


  • Line 3, 4, 7, and 10 are not really needed but it won’t cause any trouble.  The clicks seem to be irrelevant.

  • Line 5 and 6 are just wrong.  I put the text “andy” in the textbox named txtFirst, and “schwam” in txtLast.  I can easily fix them:  

    • ie.TextField(Find.ById(“txtFirst”)).TypeText(“andy”);
    • ie.TextField(Find.ById(“txtLast”)).TypeText(“schwam”);

  • Line 9 throws this exception if you let it run: “WatiN.Core.Exceptions.ElementNotFoundException: Could not find a ‘INPUT (radio)’ tag containing attribute name with value ‘rdoSendInfo_0′”.  It should be Find.ById, not Find.ByName.  This works instead:

    • ie.RadioButton(Find.ById(“rdoSendInfo_0″)).Checked = true;

  • Line 11 is good
  • Line 12.  Notice no county is selected. Try this:

    • ie.SelectList(Find.ById(“ddlCounty”)).SelectByValue(“Delaware”);

  • Lines 13, 14, 15, and 16 are just clicks but nothing is selected.  Try this:

    • ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Hiking”);
    • ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Camping”);
    • ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Mountain Biking”);
    • ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Kayaking”);

  • Line 18 is correct but worth mentioning.  This selects the first row in the grid which causes the application to display the users detail in the grid.

That doesn’t seem to good for a first shot!  But even with all of the mistakes, I’d rather start with the generated code then nothing at all, especially if this was a longer, more complicated test.  Plus, I admit there are features of the recorder that I am not familiar with so maybe it would work better if I actually knew what I was doing! 


AJAX Issues:




Technically, the changes I made are correct but it still won’t work right.  I am using ASP.Net Ajax to call back to the server when the state (ddlState) changes.  I’m populate a list of counties (ddlCounty) on the server.  When you run the test it goes so fast that it tries to select the county before the drop down list is loaded!  I found some documentation about a WaitUntil() method but I couldn’t get it to work.  So I did it the old fashioned way and put the thread to sleep:

            ie.SelectList(Find.ById(“ddlState”)).SelectByValue(“Pennsylvania”);
System.Threading.Thread.Sleep(100);
ie.SelectList(Find.ById(“ddlCounty”)).SelectByValue(“Delaware”);

Validation:


After the submit button is clicked, the application returns to the list of users.  Since I am writing a test, I should validate the results.  I’ll add in a few asserts:

            Assert.AreEqual(“Andy”, ie.TextField(Find.ById(“txtFirst”)).Text);
Assert.AreEqual(“Schwam”, ie.TextField(Find.ById(“txtLast”)).Text);
Assert.AreEqual(“me@email.com”, ie.TextField(Find.ById(“txtEmail”)).Text);

The Final Test Class:


The solution contains a class library with a class Tests . Using NUnit, I can execute the test easily.

using WatiN.Core;
using NUnit.Framework;

namespace Tests
{
[TestFixture]
public class Tests
{
[Test]
public void FirstTest()
{
IE ie = new IE(“http://localhost/WatinDemoSite/RegisteredList.aspx”);
ie.Refresh();
ie.Link(Find.ById(“LinkButton1″)).Click();
ie.TextField(Find.ById(“txtFirst”)).TypeText(“Andy”);
ie.TextField(Find.ById(“txtLast”)).TypeText(“Schwam”);
ie.TextField(Find.ById(“txtEmail”)).TypeText(“me@email.com”);
ie.RadioButton(Find.ById(“rdoSendInfo_0″)).Checked = true;
ie.SelectList(Find.ById(“ddlState”)).SelectByValue(“Pennsylvania”);
System.Threading.Thread.Sleep(100);
ie.SelectList(Find.ById(“ddlCounty”)).SelectByValue(“Delaware”);
ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Hiking”);
ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Camping”);
ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Mountain Biking”);
ie.SelectList(Find.ById(“lstHobbies”)).SelectByValue(“Kayaking”);
ie.Button(Find.ById(“btnSubmit”)).Click();

//VALIDATION

ie.Link(Find.ByUrl(“javascript:__doPostBack(‘GridView1′,’Select$0′)”)).Click();

Assert.AreEqual(“Andy”, ie.TextField(Find.ById(“txtFirst”)).Text);
Assert.AreEqual(“Schwam”, ie.TextField(Find.ById(“txtLast”)).Text);
Assert.AreEqual(“me@email.com”, ie.TextField(Find.ById(“txtEmail”)).Text);

}
}
}


Running The Tests:


I use ReSharper from JetBrains which makes my life easier in so many ways.  One of which is that it includes a tool to run unit tests.  The tests within the Visual Studio solution included in this post work great when run through ReSharper.  But I found that when I ran the tests with NUnit GUI directly I got an exception:



Tests.Tests.FirstTest : System.Threading.ThreadStateException : The CurrentThread needs to have it’s ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer.


There are some posts out there about resolving this issue but I have a better solution.  Either install ReSharper or install UnitRun, a free tool that runs tests (also from JetBrains).  While I haven’t tested UnitRun, I expect it will work the same as the ReSharper solution.

13 thoughts on “Getting Started with WatiN and WatiN Test Recorder

  1. Hello. Thanks for this post. I know it’s a bit dated but like many have said regarding WatiN there is not much training and basic scripts out for learning how to use this tool. The existing material is over complicated and ends up confusing rather than of being of any use. This page at least gives a starting point. I have found the recently released v3 test recorder has installation issues. I’ve tries installing it on various WINXP (32bit) machines with no joy. It wont work on win7 either. Thanks.

    Reply
  2. How to handle logon dialog box for a Sharepoint application?
    I tried in this way, but authentication dialog box is closing within no time.
    I am using IE8 browser.
    using (var ie = new IE())
    {
    var logonDialogHandler = new LogonDialogHandler("admin", "password");
    using (new UseDialogOnce(ie.DialogWatcher, logonDialogHandler))
    {

    ie.GoTo("http://myapplication.aspx&quot ;) ;
    }
    ie.WaitUntilContainsText("admin", 5);
    }

    Please let me know, is there any way to handle sharepoint authentication dialog box?

    Reply
  3. Once you have retrieved a reference to the link of interest, you might want to check the .Exists property before you clink it. Otherwise, an exception will get thrown; e.g.:

    Link myLink = table.Link(Find.ByText(new Regex(columnName)));

    if (myLink.Exists)
    {
    myLink.Click();
    }
    else
    {
    // decide how you want to handle the missing hyperlink
    }

    Reply
  4. hi Keshav,

    Following changes will resolve the issue,

    Settings.WaitForCompleteTimeOut = 120;// wait 120 mins before time out. u may adjust this value as needed
    Link myLink = table.Link(Find.ByText(new Regex(columnName)));
    myLink.Click();

    Reply
  5. hi ,

    Help required in how to handle the click of a table column header link button which calls asynchronusly(uses AJAX) in WATIN

    I currently have a table column, on click of that column header , all the items under that column are sorted in ascending or dsecnding order.

    .This table colummn header link button makes use of AJAX to do the post back.

    Now i not getting a way to wait untill the completion of the post back. i tried the following steps

    Link myLink = table.Link(Find.ByText(new Regex(columnName)));
    myLink.ClickNoWait();
    myLink.WaitForComplete();

    then didnt work. Again i tried with

    Link myLink = table.Link(Find.ByText(new Regex(columnName)));
    myLink.ClickNoWait();
    System.Threading.Thread.Sleep(3000);

    this above code works properly for some time. If i keep on clicking the column again and again then it will not wait for the complete post back :( .Here is where i am facing the trouble. I dont know how to handle the ajax request in Watin on click of a button or a link button.I read in few blogs that , "WaitUntil" is helpful in ajax call … but i am not able to use this for my table column header link button.

    also i tried with myIE.WaitUntilContainsText(columnName); , but here also no hopes :( .Its also not working

    Could anyone please tell me how to handle the ajax calls for a table column header link button in WATIN ? .Thanks in advance for your patience and help :) .

    Thanks again
    Keshav

    Reply
  6. Readers,

    I wrote this post in my blog in August 2007. To this day, it gets more hits from search engines than any other on my blog. I’ve also received a lot of emails from readers with follow up questions, only a few of them are shown here as comments. The problem is, there are not many resources for help with Watin.
    I am very happy to help in any way I can but I should mention mention that I stopped using Watin shortly after writing this post. I found it a little frustrating to use and also my focus in work shifted and the automated testing became less of a priority. So I am not really able to offer much more help to readers. It is possible that newer versions of this tool and others like it are better now, but I am not sure since I haven’t used them.

    If someone has some good suggestions for additional reading, I would be happy to post them here! Please send any suggestions to me.

    Best of luck with Watin and testing!

    Andy (Schwammy)

    Reply
  7. Hi Schwammy,
    I am a new bee in testing field. I after analysis selected WatiN as a webtesting tool for my company. Now I have to work on this tool which I am trying but not succedeed well. I want to write tests using VB.net. Plz can you help me in giving some tutorial for test writting.

    Reply
  8. Hi Schwammy,
    This is a great article indeed. Looking at this article I thought of asking you a query that I had regarding WatiN. I am in the process of evaluating the test tool for our AUT. I used Watin for writing test scripts in VS, C#. and found it very easy. And when I run test recorder, my test shows error where there is iFrame in the page. Now I have looked at the code that you have corrected, the one generated by test recorder. I want to know that when we run the recorder, where do we make changes in the existing code, and once we make the changes does it execute when we Playback the test in recorder.

    And I am well-versed in writing testscripts in VS, C# for Watin and I am using NUnit to execute my tests, but my manager wants me to make use of Record and Playback method as much as possible. So I am wondering how can I do that if I am getting error where iframes are there in page, when I playback the recorded test.

    Also I want to understand the difference between using Watin and Watin Test Recorder. If you can shed light on this it will be really helpful to me. Hope to hear from you soon.
    Thanks,
    Mona

    Reply
  9. Hi Schwammy,

    First, Thanks for you blog and video about WatiN and WatiN Test Recorder!

    Regarding the Need to use Thread.Sleep(). If you change this line:

    ie.SelectList(Find.ById("ddlCounty")).SelectByValue("Delaware");

    to

    ie.SelectList(Find.ById("ddlCounty")).Option(Find.ByValue("Delaware")).Select;
    or
    ie.SelectList("ddlCounty").Option("Delaware").Select

    WatiN will wait (for as long as specified by IE.Settings.WaitUntilExistsTimeOut, default 30 seconds) for the item to appear in the list.

    ERgarding the threading issue, see this page http://watin.sourceforge.net/apartmentstateinfo.htmlon the WatiN website for more info.

    Regards,
    Jeroen van Menen
    Lead developer WatiN

    Reply

Leave a reply

required

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>