NAV Navbar
Logo1

Introduction

TestControl is a light weight test automation framework for Windows Native, WinForm and WPF applications.

Features

Installation

Download binaries and unzip to your favourite location or relative to your Visual Studio project

Note: Nuget distribution is not yet available at this time but eventually.

Why TestControl?

Well, the framework is being developed out of many hurdles and shortcomings with many other frameworks and tools available both open source and commerically. Most of the time, locating the control on the screen is the key for any successful automation but it has been a challenge. So TestControl is trying to solve two main issues here: provide a precise way to locate a control on the screen and secondly be resilent to beat the failure! Lastly, CEF browser automation which you will see in another section as how to automate using TestControl.

Getting started

TestConntrol is a library is meant for people who have some .net developement skills because it does not offer record and replay mechanism. However it is not difficult for someone to work with very basic coding skills on C# or VB. This framework written up around MS UIAutomation so highly recommended if any third party controls implement UIAutomation patterns in order to fully take control on accessing elements. There are cases where paint events are drawing things on the screen and its simple imposible to capture those or to automate so that something you need to be aware of and will be discussed in advanced sections as how to overcome those.

Write a simple test


    ApplicationUnderTest calcApp = new ApplicationUnderTest(@"C:\Windows\System32\", "calc.exe");

    //build your locators
    var repo = new ControlLocatorDefRepo("calcapp");
    repo.Wait(500);  // 
    repo.FindByName("Calculator", true); // find calculator by its name

    //now use locators to find
     var w = new Window();
     w.SystemUnderTestFromRepo("calcapp");
     Assert.AreEqual("Calculator", w.Caption);   

So the above example is using repository concept if you would like to keep key map to store your locators for later use

Locators

Control Locator

Control locators are used to find the right element on the target window in order to automate further. Control locators are defined in a sequence of actions using following locator types. Window elements are hierarchical by nature for example window being the root element and drop down being a child element like that. So one can use multiple locator types to navigate to target element of interest.

       //define as how to locate an element 
       var controldef = new ControlLocatorDef<FindControl>(
                                                    () => new FindWindow("Demo Form"),   // locate the window first
                                                    () => new FindByAutomationId("radioButton1") // and then locate the radio button using automation id
                                                   );

      //now choose or define your target element to be in order to access its values or trigger events on them 
      var radio = new RadioButtonControl();  // target element type
      radio.SystemUnderTest( controldef ); // set the locator def here
      radio.Selected = true; // now check radio button


Find By Automation Id

Automation id is generally an unique id given for the elements.


    IFindControl findcontrol = FindByAutomationId("<automation id to locate a target element >");

Find By Caption


    IFindControl findcontrol = FindByCaption("<caption/text to be used to locate a target element>");

Find By Name


    IFindControl findcontrol = FindByName("<developers given name or OS based predefined names to be used to locate a target element>");

Find Child By Caption


    IFindControl findcontrol = FindChildByCaption("<caption/text to be used to locate a target element from an root elementt>");

Find Desktop Window


    IFindControl findcontrol = FindDesktopWindow();  //returns your desktop window as your target element

Find Window


    IFindControl findcontrol = FindWindow(<Caption>, <className optional>);  //locating a target window element by its caption or class name or combination of both.

Find Window By Mouse Position


    IFindControl findcontrol = FindWindowByMousePosition();  //locating a target window element by current mouse position.

From Handle


    FromHandle(IntPtr handle);  //locating a target window element by HWND / window handle.

Mouse Click


    MouseClick(Point pt);  //send mouse click on the given point position

Move Mouse


    MouseClick(int moveToX, int moveToY);  //move mouse cursor position to desired x and y coordinates

Right Click Mouse


    RightClickMouse();  //send right click on the current mouse cursor position

Send Key Strokes


    SendKeyStrokes(keys);  //send key stroke, check microsoft documentation on SendKeys

Wait


    Wait(int milliSec);  //waits for given time in milli sec 

    //for example

   var controldef = new ControlLocatorDef<FindControl>(
                                                () => new FindWindow("Demo Form"),   // locate the window first
                                                () => new Wait(1000),  //wait for 1 sec before proceed next step
                                                () => new FindByAutomationId("radioButton1") // and then locate the radio button using automation id
                                               );


Click Non-Window Control By Caption



    ClickNonWindowControlByCaption(String[] captionPath, bool dblClick = false, int offsetX = 2, int offsetY = 2);  

    //for example to work with context menu
            var cdef = new ControlLocatorDef<IFindControl>(() => new FindbyCaption("Demo application"),
                                                () => new RightClickMouse(),
                                                () => new Wait(100),
                                                () => new SendKeyStrokes("{DOWN}", true),
                                                () => new Wait(100),
                                                () => new FindWindowByMousePosition(),
                                                () => new Wait(100),
                                                () => new ClickNonWindowControlByCaption({"New", "Create folder"})  //under 'new' sub menu then click 'create folder' menu item
                );
            return cdef;    


Standard Controls

CEF Browser Control

CEF is a real chrome browser embedded into a window control. CEF control is becoming popular as organisations are moving towards web offerings and discontiue developements on desktops. As a result, desktop applications are embedded with web applications inside that makes automation complex because you need to have a seamless flow of automation between window controls on the applicatons and CEF control as a browser in order to manipulate its elements. Rather reinvinting the wheel, TestControl uses Selenium drivers to work with but with modified version of chromedriver that can work along with TestControl. So the modified version chromedriver.exe is named as TCChromeDriver.exe for our use.


    // set your application under test
    IApplicationUnderTest app = new ApplicationUnderTest(@"..\TestApps\", "ceftest.exe"); //ceftest.exe is a winform cotinaing cef control

    //application main form has only a cef control browser control 
    //and your mainform window caption is set to "Google"

    app.RunOnce(); //now launch the application
    if (app.WaitForCaptionIfExists("Google", 20))  // wait for window appears with 20 retries
    {
        Assert.IsTrue(true);
    }
    else Assert.Fail("unable to get window caption");


      //locate the control as like any other .NET Control
    WebBrowserControl aBrowser = new WebBrowserControl("chrome"); //browser type to chrome
    aBrowser.SystemUnderTest(new ControlLocatorDef<FindControl>(
                                        () => new FindByAutomationId("Form1", true), //your main form id
                                        () => new FindByName("Chrome Legacy Window") //the spy shows the name as Chrome Legacy Window
            ));
    Assert.IsTrue(aBrowser.IsVisible);  //make sure your cef control is visible


    //** make sure, for this test formshow event of main form is set to load google.com into the cef browser             

    //now Testcontrol loads Selenium driver and switching to Selenium world

    // goto an Url
    var url = aBrowser.InternalDriver.GotoUrl("http://msn.com");
    Assert.AreEqual("http://msn.com", url);
    url = aBrowser.InternalDriver.GotoUrl("http://yahoo.com");
    Assert.AreEqual("http://yahoo.com", url);


    //to find an element
    aBrowser.InternalDriver.GotoUrl("http://google.com");
    var element = aBrowser.InternalDriver.FindChild("name:q"); // equivalent to ByName()
    Assert.IsNotNull(element);
    element.Text = "TDD"+ Enter;
    element = aBrowser.InternalDriver.FindChild("name:q");
    Assert.AreEqual("lst-ib", element.AsString("Attribute:id"));


    //here is an example if you want use direct selenium way
    aBrowser.GetWebDriver().Url = "http://www.littlewebhut.com/articles/html_iframe_example/";

    var frame = aBrowser.GetWebDriver().FindElement(By.Id("imgbox"));

    Assert.AreEqual("http://www.littlewebhut.com/images/eightball.gif", frame.GetAttribute("src"));

    //switch frame
    aBrowser.GetWebDriver().SwitchTo().Frame(frame);

    var img = aBrowser.GetWebDriver().FindElement(By.TagName("img"));
    Assert.AreEqual("http://www.littlewebhut.com/images/eightball.gif", img.GetAttribute("src"));