White

Posted on Wednesday, 27 February 2008

The guys at Thoughtworks have released yet another open source project. This one is called white and is on codeplex http://www.codeplex.com/white/. What is white? White is a library that sits on top of the .Net 3.0 UIAutomation API's. I have written one of these myself and we use it internally, so I haven't looked at white.

Combined with WatiN, and ItiN if you use InfoPath, with white you should be able to write 100% of your tests using managed code in Visual Studio 2008. We do!

Another next Gen feature: XML based tests

Posted on Monday, 04 February 2008

In my last post I gave a glimpse into our new WatiN stack, another feature is that we have implemented the command pattern, and serialise the commands out as XML. This lets us build tests that have randomised execution and still replay them when they fail. As a nice by-product, we also can write tests as XML if we wish.

For example the following XML:

<?xml version="1.0"?>
<ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <anyType xsi:type="TestExecutionCommand">
    <MethodName>Search</MethodName>
    <AssemblyName>SearchTests.Logical, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</AssemblyName>
    <ClassName>SearchTests.Logical.SearchModel</ClassName>
    <Parameters>
      <anyType xsi:type="DataProvider">
        <DataIdentifier>SearchForWatin</DataIdentifier>
      </anyType>
    </Parameters>
  </anyType>
</ArrayOfAnyType>

will execute the same test as before. Building a tool to generate this would be completely trivial, should we choose to go down that route.

Write WatiN tests using Excel

Posted on Saturday, 15 December 2007

Tonight I noticed a cool project on codeplex called WAX http://www.codeplex.com/wax, whilst this isn't something that I will use myself, I have done something similar in the past, and generating tests in excel can save a LOT of time.

ItiN - Infopath testing in .Net

Posted on Thursday, 24 May 2007

The project that I am currently working on uses infopath forms. This was causing us a few hassles on the testing front, especially now we are using WatiN extensively. So after a few failed attempts at using the new .Net 3.0 automaton API's and not really wanting to learn MSAA, I decided to create a specalised port of WatiN to test infopath and ItiN was born.

ItiN uses a hybrid approach allowing manipulation of an InfoPath document  directly using XPath and the XML dom, or the view using traditional WatiN automation.

The full set of HTML controls supported by WatiN is not required for ItiN, so only: buttons, check boxes, radio buttons, textboxes and select lists are supported.

The ItiN framework I is open source on Codeplex here http://www.codeplex.com/itin.

A sample script using the framework that works against the 2003 sample IssueTrackerSimple form saved in c:\ is as follows.

using Microsoft.VisualStudio.TestTools.UnitTesting; 

using System;

using ItiN;

namespace Itin.Tests

{

       [TestMethod()]

       public void IssueTrackingSample()

       {

            // Open test form

           string infopathFileName = @"c:\IssueTrackingSample.xml";

           InfopathTester FormTester = new InfopathTester(infopathFileName);

           FormTester.SetInfopathNamespace("xmlns:iss='http://schemas.microsoft.com/office/infopath/2003/sample/IssueTracking'");

            FormTester.SetFormValue(@"//iss:title", "Issue Title");

            // Click the send email button which does nothing as I don’t have email configured for infopath

            FormTester.Button(ItiN.Find.ByValue("Send as E-mail")).ClickNoWait();

            FormTester.SaveDocumentAs(@"c:\SavedForm.xml");

            FormTester.CloseAndQuit();

           // TODO: Implement code to verify target

          Assert.Inconclusive("TODO: Implement code to verify target");

        }

    }

}

Scott Guthrie recommends WatiN

Posted on Thursday, 03 May 2007

In a comment on a blog entry by Jeremy D. Miller codebetter.com, Scott Guthrie, General Manager within the Microsoft Developer Division*, had the following to say about WatiN.

"Instead of using only a mock approach on the server, I'd recommend always having at least some end to end UI integration tests that you incorporate into your project.  You can use a replay tool (like what is in VSTS) for this, although increasingly I'm seeing .NET developers leverage programmatic unit testing frameworks like WatiN that provide more control and flexibility.  

If you haven't tried WatiN, I'd recommend visiting these two links to download it and try it out:

http://watin.sourceforge.net/gettingstarted.html

http://www.codeproject.com/useritems/WatiN.asp

You can incorporate WatiN within NUnit, MBUnit or the VS test framework and use your standard unit testing run tools with it (it allows you to use C# or VB to write the tests as standard NUnit or MBUnit test cases).  It does launch and use the browser to test the application, so it won't be as fast as zipping through 5000 class-based unit tests.  But it will give you exactly the experience that you'll have when a customer hits the site, which ends up being a far more accurate assessment of the application quality.  It also allows you to fully test AJAX and JavaScript scenarios."

Cool !

* He runs the development teams that build the Common Language Runtime (CLR), .NET Compact Framework, ASP.NET, Atlas, Windows Forms, WPF, IIS and Visual Studio.

Debunking Anti-WatiN bullshit marketing from SWEA

Posted on Monday, 02 April 2007

In a previous post, I talked in a closing comment about how some tool vendors are trying to piggyback on WatiN to promote their inferior tools. Well there have been a couple of comments on my blog since from SWEA evangelist, Alex at a Hotmail address.

SWEA is much better product than WATIN. It can save days on test development and maintenance. Any small UI change will require change in the WATIN scripts, but SWEA scripts are more resilient to the UI changes – the control binding is separated from the script code. WATIN is just thin wrapper around HTML DOM, but SWEA is complex automation framework.

You can also try SWExplorerAutomation (SWEA) from webiussoft. SWEA is not free but provides more functionality (Recorder, Data Extractors, internal support for AJAX, more resilient to UI changes scripts) than WATIN.

Ok first things first. This is my blog and not a public forum. If you want to advertise on my blog, you can pay for your adds via Google. It is for this reason that I have deleted these comments.

Let's debunk these claims one at at time.

Claim #1 SWEA is much better product than WATIN.

Dictionary.com defines a product as "the totality of goods or services that a company makes available."  WatiN is free and not produced by a company. So I will concede that point SWEA is a better "product" than WatiN, simply because WatiN is not a product at all.

Claim #2 SWEA scripts are more resilient to the UI changes ...  any small UI change will require change in the WATIN scripts

Now that is complete BULLSHIT. Good script design and development practices have significantly more impact on how resilient a script is to UI changes than the underlying tool does. WatiN supports controls defined as .net regular expressions. Using WatiN Attributes in a control class, allows controls to be defined in a single location and called consistently regardless of how WatiN finds the control. Couple that with Visual Studio 2005's refactoring support and I am working in UI change nirvana with WatiN. If anyone needs to know how good script design should be done, please feel free to follow my blog post series and learn how to do it properly.

Claim #3 SWEA is not free ...

That one is true.

Claim #4 SWEA is not free but provides more functionality (Recorder, Data Extractors, internal support for AJAX ...

You can get WatiNRecorder from here, so that is an outright lie.

I honestly don't know what a "Data Extractor" is, nor why I would need one.

WatiN does support AJAX, and yes there are some issues, however they are well know and being improved every day, so that is another lie as well.

Claim #5 WATIN is just thin wrapper around HTML DOM, but SWEA is complex automation framework.

WatiN is a thin wrapper around Internet Explorer, not just the HTML DOM. One of the key reasons WatiN and Watir do so well are their elegance, simplicity and speed. I personally would not be quoting complexity as a feature or any application.

Honestly, SWEA may be an OK product, however if it was so good, webiussoft wouldn't need to leave comments on every WatiN related blog post they can find, pleading for people to try their products instead.

I'll leave the last word on this to a comment one one of my posts from Petey in regard to test tool companies that resort to blog spam marketing : "Don't forget SWEA. It is so annoying!" 

If that isn't a great reason to not try a tool, I don't know what is. 

Building a GUI test automation framework: Structuring the project

Posted on Thursday, 29 March 2007

This post is the third in a series of posts, building a GUI test automation framework. In the first post, I outlined the key design goals of an automation framework. In the second second post I talked to the need for a control file. Since the original posts way back in early 2006, a lot has changed. As a result I am going to re-focus (and finish) these posts on how you can structure and develop a set of simple tests using WatiN.

Ok there are some pre-requites if you want to run these examples. I am going to assume that you are running Visual Studio 2005, SQL Express 2005, nUnit 2.4.0 and we are using the asp.net job site starter kit as our test application.  I was planning to use the .net petshop 4.0 for this article, however it wouldn't install with Windows Vista.

Ok assuming you are up and running, let's get started.

The general structure that I like to follow for this type of project is to have a single solution broken up in to several projects. The standard projects that I like to have are Controls, Framework and Tests. In this example I am also going to add a fourth project to hold the site URLs.

Once I have these projects in place I set up the classes so they are all using single namespace that is then subdivided in a similar fashion such as: JobSite.Controls, JobSite.Tests and JobSite.URLs.

You can download the solution with the basic structure from here. I have set up a Codeplex project http://www.codeplex.com/WatinJobsiteSample/ to store the source code for the examples in the rest of this series of blog posts. In the next post we will get seriously back on track and start putting our test framework together.

Open source test tools are the way of the future

Posted on Thursday, 22 March 2007

As you can tell from my blog, I am a big fan of WatiN. One thing that WatiN doesn't do is test non IE stuff. Well as part of .net 3.0 Microsoft has now shipped API's that allow testing of Windows apps, including both legacy Win32 and WPF applications. There is an MSDN article on how to do this here.

So what does this mean? It essentially means that commercial tools are  dead in the long term. If it is possible for a single developer to build tools that work better than commercially available tools costing hundreds or thousands of dollars, which it currently is. It won't be long until they are not purchased any longer.

Another interesting phenomenon is that companies are trying to advertise their tools by adding comments to blogs, such as this one saying things like, you should try tool xxxx.

Sorry but when your commercial tool costs more and does less than the open source alternative, it is time to look for a new product to develop.

Another major irony is that if the open source tool has a bug, or doesn't have a feature I need, then you can simply open up the code and fix it or add the feature. Most commercial vendors take 4-6 months or more to investigate, test and resolve issues.

So if you haven't yet, download a copy of WatiN, WatiNRecorder, nUnit and C# Express, then see what the future is like and join in by submitting back features.

One final word, Webiussoft and Inscif, please stop trying to promote your commercial tools by adding comments to blogs about WatiN, we aren't changing !

WaiN turns 1.0

Posted on Thursday, 01 March 2007

WatiN 1.0 has been released, you can get it here. The full release notes are here. This release includes a license change to the Apache 2.0 open source license.

WatiN 0.9 is released

Posted on Thursday, 02 November 2006

Jeroen van Menen has released WatiN 0.9. The full release notes for Watin 0.9 can be found at http://watin.sourceforge.net/releasenotes-0-9-0-4000.html. Highlights of this release are:

  • Added an extensible model for handling IE dialogs through the DialogWatcher instance
    of each DomContainer (IE and HTMLDialog). If no specific handling of a dialog (type)
    is needed, DialogWatcher will automatically close any dialog that pops up.
  • This release contains the following dialog handlers:
    • Added support for Logon dialog handling (thanks to Bruce McLeod for the initial implementation).
      Some of the constructors of the IE class accept an instance of LogonDialogHandler
      to automatically logon to a website.
    • Improved support for handling alert and confirm dialogs in various ways through AlertAndConfirmDialogHandler, AlertDialogHandler, ConfirmDialogHandler and SimpleJaveDialogHandler.
    • Added support for handling Certificate warning dialog.
  • Added support for automating a frames page which shows websites from different
    domains (thanks to Ken Herman for the initial implementation).
  • Added support for IFrame element(s) using the ie.Frames syntax (thanks to Gaurav
    Jayal for supplying some good iframe web pages to test with).
  • Added support for file upload (input element of type upload) through
    ie.FileUpload.Set(MyFile).
  • Added support for ie.Element() and ie.Elements to get any or all elements in a
    document (or elements container like the div element). This way elements not natively
    supported by WatiN can also be accessed through the WatiN API. If an element can contain
    elements, like the html element, the return value of ie.Element can be casted
    to ElementsContainer.
  • Added basic support for tags through ie.Button() and ie.Buttons. Use
    ie.Element() or ie.Elements instead if access to the inner elements is required.
  • Improved the speed of the Table.FindRow implementation. It uses a special
    TableRowFinder instead of looping through all kinds of collections.
  • Speed is improved when closing an IE instance. This is because all IE instances in the
    same process share one instance of DialogWatcher. Also disposing DialogWatcher is
    speed up by terminating the watcher thread earlier.
  • WatiN allows the use of regular expressions in some more situations.
  • Removed all constructors of the IE class that had autoclose as an argument. Use the ie.AutoClose property if you need to change the auto close behaviour of an IE instance. The default value of AutoClose is true.
  • Made a change to the new IE implementation to better support using WatiN on Vista
    with User Account Control (UAC) turned on. (Thanks to Bruce McLeod for testing on
    Vista and supplying this change).
  • Made extending and reusing some parts of the WatiN API easier:
    By exposing some new methods in the ElementsSupport class it's possible to more
    natively access the code which finds html elements in a webpage. Together with the
    changes of the constructors of some elements and of all element collection classes,
    this makes it possible to create your own customized wrappers for your own or third
    party web controls. A more complete example on how to do this will be available on
    the website soon.

And yes, just in case you were wondering, the Bruce McLeod mentioned is me :-)

WatiN Recorder

Posted on Monday, 23 October 2006

Richard Griffin has ported WatirRecorder++ to work with WatiN. For more details please visit the post on Richard's blog.

Using regular expressions in WatiN

Posted on Monday, 25 September 2006

Anyone that has done any serious test automation of ASP.NET applications knows that .NET is a tad verbose when it comes to the control names that it generates. ASP.NET generates its control ID's based on a hierarchy of controls. For example, if you have a textbox inside a user control that is placed in side a placeholder, the of name property of the control will be something like name="ctl00$ContentPlaceHolderMain$UserConrol1$txtLogin". On some applications I test, I have seen control ID's 130+ characters in length. This presents an interesting challenge to the automator where your scripts can easily become something like this:

ie.TextField(Find.ByName(ctl00$ContentPlaceHolderMain$UserConrol1$txtLogin)).TypeText("Bruce McLeod");

There are two scenarios that we want to be able to easily handle to maximise script maintainability. Firstly, if the control is renamed, we only want to have to change the control in one place. Second, if the hierarchy of the controls is changed, (or if the control moves in the page) we want to be able to handle it easily.

One of the new features introduced into version 0.8 of WatiN is support for using regular expressions. This provides a extremely powerful way of solving both problems.

The first thing we will do is define a static class that returns the name property of the control. If this control was being used to test, say Amazon.com, I would structure the class that uses a namespace structure that allows the use of intellisense to help find controls at design time.

using System;

namespace Amazon
{
    class LoginPage 
    {
        public static string txtLogin = "ctl00$ContentPlaceHolderMain$UserConrol1$txtLogin";
    }
}
This allows the test script to be simplified as follows:

ie.TextField(Find.ByName(Amazon.LoginPage.txtLogin)).TypeText("Bruce McLeod");

Ok problem one solved, and now that we have our class, we can easily change it to use the regular expression support. If we want to ignore the whole control hierarchy and only match the control name txtLogin, then we can use an expression like:
[a-zA-Z0-9\$]*txtLogin
(If like me, you can never remember what the expression should be, I can highly recommend regexlib.com, which contains examples, reference sheets and a regex tester.) WatiN implements overloads in Find.ByName and can consume the control name as either a string or a Regex. This allows us to use the regular expressions by only changing how the control is defined in the class. An updated version of the class using regular expressions is as follows:
using System;
using System.Text.RegularExpressions;

namespace Amazon
{
    class LoginPage 
    {
        public static Regex txtLogin = new Regex("[a-zA-Z0-9\$]*txtLogin");
    }
}
Now the only thing that will cause us problems is if the txtLogin control us renamed, or another txtLogin control is added to the page somewhere else. But what are the chances of that happening ...

WatiN and Vista RC1

Posted on Tuesday, 05 September 2006

I have spent the evening debugging WatiN on Vista RC1, and I have uncovered the following issues:

1. Your test tool of choice must be run as administrator.

If you are using nunit or VSTS to run your tests you MUST run them as administrator. If you don't then a second process is spawned in the ie.goto function when Internet explorer's Navigate function is called. The second process will then go where you told it, and the original process will just hang and never load.

2. Finding IE by title doesn't work as expected.

The AttachToIEByPartialTitleAndByUrl unit test fails. On further digging this one get's interesting. If you launch a browser window, and point it to www.google.com, the test will fail because it finds the window as expected. However when WatiN opens a window itself and points it to google the same comparison fails. The problem is that in FindIE, the following line.

ShellWindows allBrowsers = new ShellWindows();

Does not return the ie windows that WatiN has created, as expected. A solution here may be to replace that code with win32 code that gets the window title, but it essentially looks like the ShellWindows command does not work as expected in Vista RC 1.

Update: WatiN works 100% on Vista RC1 with the User Account Control (UAC) feature of Vista is turned off. UAC must have altered the way that the ShellWindows class works.

WatiN 0.8 ships

Posted on Sunday, 03 September 2006

Jeroen van Menen has released WatiN 0.8.4. This new version includes several bugfixes, simpler syntax and a .net 2.0 version out of the box. Full release notes are here, and you can download the .net 2.0 verison here.

Looking forwards to version 0.9, you can expect support for authenticaton and improved dialog handling.

Scott Hanselmann starts mixing WatiN with PowerShell

Posted on Wednesday, 23 August 2006

I was plesantly suprised today when, whilst taking to another Geek at Teched that he knew what the heck WatiN was without me having to explain it from scratch. It seems that Scott Hanselmann has blogged about trying to intergrate WatiN with powershell.

Looking at Scott's post, I would guess that the problems are related to the way WatiN starts a secondary thread to handle pop-up windows, or this could be related to some recient issues that Jeroen has sorted around threading apartments.

If I get some time I might have a quick look if we can get this going, but it won't be very high on my list of priorites at the moment.

WatiN based unit tests using the ASP.NET Development web server

Posted on Wednesday, 23 August 2006

One of the more interesting and less documented features of VSTS is how to handle the ever changing port of your local development server when running unit tests. This really becomes an issue when you want to write WatiN tests that can run out of the box on any developers machine or a server that is performing continuous integration.

As part of this week's Teched, Mitch Denny has organized a Smith Family community project to develop an application for the smith family. My contribution was to port WatiN to .net 2.0 (again), so it didn't have my recent enhancements.

The next step was to write a test that used WatiN, but would work with the TFS continuous integration tool Chris Burrows, without a hardcoded test server. Whilst not the exact code, Chris showed me how to utilise the AspNetDevelopmentServer attribute from the Microsoft.VisualStudio.TestTools.UnitTesting.Web namespace to work with the local ASP.NET Development web server. I have written up a short example below that shows how it is done.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using WatiN.Core;

[TestClass]
public class UnitTest1
{
    private TestContext m_testContext;
    public TestContext TestContext
    {
        get { return m_testContext; }
        set { m_testContext = value; }
    }

    public string DevServerURL
    {
        get
        {
            Uri webServer = m_testContext.Properties["AspNetDevelopmentServer.localhost"] as Uri;
            return webServer.AbsoluteUri;
        }
    }

    [TestMethod]
    [AspNetDevelopmentServer("localhost", @"C:\Docu ... \WebSite1")]
    public void TestMethod1()
    {
        using (IE ie = new IE(DevServerURL))
        {
            Assert.IsTrue(ie.MainDocument.ContainsText("This is a test."));
        }
    }
}

To make this work you will need to add a COM reference to Microsoft Internet Controls, and a reference to your Watin.Core.dll. To our complete surprise, once we had defined the initial test as part of the team build, it ran first go on the server, sight unseen and passed.

Adding Authenticaton to WatiN

Posted on Wednesday, 23 August 2006

Well after a week or so of not touching WatiN, I had another crack at getting authentication to work. In the short term I have abandoned the "technically correct" solution of trying to get impersonation to work, and instead I have ported over the AutoIT code from watir. To do this I created two new classes AutoIT and AutoItLogonParamaters. The main methods in the AutoIT class are:
public void logon(AutoITLogonParameters loginParamaters)
{
     autoit.WinWait(loginParamaters.windowTitle, "", _timeout);
     autoit.WinActivate(loginParamaters.windowTitle, "");
     autoit.Send(loginParamaters.userName, 0);
     autoit.Send("{TAB}", 0);
     autoit.Send(loginParamaters.password, 0);
     autoit.Send("{ENTER}", 0);
}
The logon parameters class just contains properties to get and set three strings so I can pass in one parameter instead of three. The next trick was to work out how to get this code to work on another thread. This required “drilling a hole” through the IE class, passing the login paramaters class into the popupwatcher class and adding the following to the MyEnumThreadWindowsProc method.
private bool MyEnumThreadWindowsProc(IntPtr hwnd, IntPtr lParam)
{
   if (IsDialog(hwnd))
   {        
   	IntPtr handleToDialogText = NativeMethods.GetDlgItem(hwnd, 0xFFFF);
        string alertMessage = GetText(handleToDialogText);
        alertQueue.Enqueue(alertMessage);

        // get the window title, and check if it matches our login window
        if (GetText(hwnd).StartsWith("Connect to"))
        {
            if (logonParameters != null)
            {
                //  TODO: We should be able to use win32 for all this like
                //  NativeMethods.SetWindowText(hwnd, "Hello");
                WatiN.Core.AutoIT auto = new AutoIT();
                auto.logon(logonParameters);
            }
            else
            {
                throw new MissingFieldException("A window title is missing.");
            }
        }
        NativeMethods.SendMessage(hwnd, NativeMethods.WM_CLOSE, 0, 0);
   }
   return true;
}
This works exactly as I expected and the following test passed with no problem.
IE ie = new IE(new AutoITLogonParameters("Connect to localhost", "uid", "pwd"));
ie.GoTo("http://localhost");
Assert.IsTrue(ie.ContainsText("this is a test"), "Text not found");
ie.Close();
The main problem with this approach is that it requires the AutoIT dll to be bundled with the code, and it needs to be registered on the machine before it can be used. My next step is to investigate the Win32 calls similar to what already exists to close the popup windows, removing the need for AutoIT entirely.

Refining the code - updates to my previous WatiN example

Posted on Wednesday, 09 August 2006

In my previous post I mentioned that further investigation was required to refine the script to remove the thread.sleep statements. Well post investigation I can share some insights on exactly what is happening and what changes are required.

In addition to the ReadyState property, Internet Explorer exposes a Busy property as well. When a normal page has completed loading the ReadyState will return READYSTATE_COMPLETE and Busy will return false. Internally WatiN uses this to let the browser to dictate when the test script should continue through the Wie.aitForComplete method. This method internally calls two private methods WaitWhileIEBusy() and WaitWhileIEStateNotComplete(). These methods wait for their corresponding methods to return the expected value, then the script continues.

The challenge comes in when a dialog is displayed. When a modal dialog is displayed, IE set's ie.busy = true, and returns READYSTATE_COMPLETE. If a test is calling WaitForComplete, then the script will hang forever. WatiN caters for this with the WaitForComplete method on it's HTMLDialog class, which ignores the busy property. Armed with this information, our script now looks like this.

 [TestMethod]
 public void AddNewUser()
 {
    using (IE ie = new IE(baseURL))
    {
        // Click on the 'Manage customers' button to open the customer 
        // management screen 
        ie.MainDocument.Button(Find.ByName(btnManageCustomers)).Click();
// Click on the add customer image button (an INPUT tag with type image) // We need to use ClickNoWait as the Create customer dialog is a modal dialog // and the readystate does not return to complete until the dialog is closed. ie.MainDocument.Input(Find.ById(btnSelectTicketType_id)).ClickNoWait();
// Find the new 'Create new customer' dialog that opens in the collection // of dialogs and wait a maximum of 2 seconds for the dialog HtmlDialog dialog = ie.HtmlDialog(Find.ByTitle("Select ticket type"),2);
// Select Melbourne, Qantas and Business class // We need the dialog.WaitForComplete() as these contols load dynamically based on // the previous selection and we are in dialog mode dialog.MainDocument.SelectList(Find.ById(ddlDestination_Id)).Select("Melbourne"); dialog.WaitForComplete(); dialog.MainDocument.SelectList(Find.ById(ddlCustomerAirline_Id)).Select("Qantas") ; dialog.WaitForComplete(); dialog.MainDocument.SelectList(Find.ById(ddlCustomerClass_Id)).Select("Business"); dialog.WaitForComplete(); dialog.MainDocument.Button(Find.ById(btnOk_Id)).ClickNoWait(); ie.WaitForComplete();
// Test that the text 'Melboune' is in the page Assert.IsTrue(ie.MainDocument.ContainsText("Melbourne"));
// Test that the text 'Qantas' is in the page Assert.IsTrue(ie.MainDocument.ContainsText("Qantas"));
// Test that the text 'Business class' is in the page Assert.IsTrue(ie.MainDocument.ContainsText("Business class")); }

Modal dialog's and dropdowns in Watin

Posted on Monday, 24 July 2006

Although I don't yet have time to start using WATIN full time at work, I managed to convert a few more tests over to compare how the tests work. I am doing this in my spare time (i.e lunch and after work), to building A proof of concept and see how the framework will go in real world testing situations. For this post I have removed all references to our real application and mocked up a sample application.

The part of our app that I have simulated has a model dialog, a group of drop down's in that each refresh when the one above it changes, and an image button implemented on an 'input' tag to launch the dialog. The sample dialog looks like this mock-up.




The test case was a very simple one, click the image, select a value in each of the drop-down's, click OK then validate the page contains some text. There were a few interesting challenges, but nothing that I couldn't solve by adding some code to the Watin framework and recompiling. Here is an altered version of the resultant code.

 [TestMethod]
 public void AddNewUser()
 {
    using (IE ie = new IE(baseURL))
    {
        // Click on the 'Manage customers' button to open the customer 
        // management screen 
        ie.MainDocument.Button(Find.ByName(btnManageCustomers)).Click();
// Click on the add customer image button (an INPUT tag with type image) // We need to use ClickNoWait as the Create customer dialog is a modal dialog // and the readystate does not return to complete until the dialog is closed. ie.MainDocument.Input(Find.ById(btnSelectTicketType_id)).ClickNoWait();
// Find the new 'Create new customer' dialog that opens in the collection // of dialogs and wait a maximum of 2 seconds for the dialog HtmlDialog dialog = ie.HtmlDialog(Find.ByTitle("Select ticket type"),2);
// Select Melbourne, Qantas and Business class // We need the thread.sleep as these contols load dynamically based on // the previous selection and we are in dialog mode dialog.MainDocument.SelectList(Find.ById(ddlDestination_Id)).Select("Melbourne"); Thread.Sleep(2000); dialog.MainDocument.SelectList(Find.ById(ddlCustomerAirline_Id)).Select("Qantas") ; Thread.Sleep(2000); dialog.MainDocument.SelectList(Find.ById(ddlCustomerClass_Id)).Select("Business"); Thread.Sleep(2000);
dialog.MainDocument.Button(Find.ById(btnOk_Id)).ClickNoWait(); ie.WaitForComplete();
// Test that the text 'Melboune' is in the page Assert.IsTrue(ie.MainDocument.ContainsText("Melbourne"));
// Test that the text 'Qantas' is in the page Assert.IsTrue(ie.MainDocument.ContainsText("Qantas"));
// Test that the text 'Business class' is in the page Assert.IsTrue(ie.MainDocument.ContainsText("Business class")); }
So what were the traps?

Internet Explorer implements a ReadyState property which indicates that the browser is loading, rendering the page, etc. ReadyState typically returns an enum value of READYSTATE_COMPLETE when the browser is loaded and ready for more input. Where the challenge comes in is that his behaviour changes when when a modal dialogue is shown The browser does not return READYSTATE_COMPLETE, yet it is waiting for user input. To work around this issue Watin implements a ClickNoWait() method to use instead of the Click() method under these circumstances.

The problem I ran into (apart from an un-handled exception being thrown from the click method) was that the applicaiton dynamically loads the value of one dropdown after a value is selected in the one above it. This required a Thread.Sleep call to pause the script for 2 seconds, after each drop-down list is selected. I don't think that this solution is very elegant, and it adds some 6 additional seconds to the execution time for this test. This definitely warrants some further investigation into what the IE ReadyState is when the dialog is shown, writing another wait method for the Watin ie object, that waits for that state to change.

Anyway so far Watin is meeting my expectations and still looks like it will be able to handle just about everything I can throw at it.

The holy grail: .net automated web GUI testing for internet explorer

Posted on Thursday, 20 July 2006

If you are looking (as I have been for a while) for a solution on how to write automated web GUI tests for internet explorer in .net then look no further. WATIR has been ported to C# as the WATIN framework. I have compiled the framework in .net 2.0 with minimal fuss, and it feels like it should have shipped out of the box with Visual Studio Team Edition for Software Testers.

So is it any good? I have spent about 2 hours so far converting one of my simple tests across, and this thing rocks. The tests are simple and execute very quickly. The following sample, copied from the WATIN homepage, searches for this site in google and checks for the text "Saving the world, one test case at a time" in the browser window.
    [Test]
    public void Google()
    {
      using (IE ie = new IE("http://www.google.com"))
      {
        ie.MainDocument.TextField(Find.ByName("q")).TypeText("Teknologika");
        ie.MainDocument.Button(Find.ByName("btnG")).Click();
 
        Assert.IsTrue(ie.MainDocument.ContainsText("test case"));
      }
    }
The best part of all, is that if you use NUnit and Visual C# Express Edition, your total cost is $0.