Page 1 of 1

C# TestStack.White for Beginners

#1 GuageCage  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 5
  • Joined: 30-May 13

Posted 30 May 2013 - 12:38 PM


I recently took on a project that would automate a process. A user had to select data from many fields such as Company, Query to run, Begin date, End date, etc. using an existing application. This process was not as tedious as the process of waiting for the report to be generated. The report would often take several hours to complete. As the application, which I will call Report App, only runs for one company at a time. Each report takes hours to complete. Afterwards the user must set up the next company then wait for the report to complete. With a list of companies over 30 names deep, one can see where there could be an efficiency loss generated when the user has other tasks to complete and no way of knowing when each report has completed other than manually checking on it. Retooling the original code was out of the question. Creating a new app to run the reports with automation built in was out of the question as this was just a helpful thing that I wanted to do without becoming a full blown project. I reviewed the “interwebs” and found a neat little framework called TestStack.White. LINK

Below is quoted information from the link above describing what TestStack.White is.

“White is a framework for automating rich client applications based on Win32, WinForms, WPF, Silverlight and SWT (Java) platforms. It is .NET based and does not require the use of any proprietary scripting languages. Tests/automation programs using White can be written with whatever .NET language, IDE and tools you are already using. White provides a consistent object-oriented API, hiding the complexity of Microsoft's UIAutomation library (on which White is based) and windows messages.”

Below is a general tutorial on how I developed an application to automate the above process. I hope that you enjoy and or find a use for it in your coding endeavors now and in the future.**Note** This is the first tutorial of any kind that I have posted on the “interwebs”. Any constructive criticism is welcome.

When creating a UI Automation application, the developer may not be aware of the “Names” that have been given to each of the controls on the original application such as “btnSubmit, lblIntructions, etc.”.

In this case the developer will need to use a tool to acquire that information. A handy tool that I used was included in another Automation framework called UIA Verify. You can find more info here LINK. This was another framework that I ran through but ultimately decided on TestStack.White.

Below shows the application being investigated using UIA Verify. You can see that the Browse button is highlighted.

Attached Image

Here is a shot of the actual UIA Verify interface. It listed in a hierarchical way with your desktop being the starting point. It will show you the breakdown of each UI object and the name that has been assigned to it when it was created. The highlighted section shows that the name given is btnBrowse.

Attached Image

This is very important as this is the data that you will need to use when implementing TestSack.White in your code.

Now that you have the data that you will need, you will need to install the TestStack.White library. You may do so by using NuGet to install. Use the code below:

PM> Install-Package TestStack.White


You may also want to download the files to your computer. Either way make sure that a reference to the library has been added to your project.

Attached Image

Make sure that you add the following namespaces

using White.Core;
using White.Core.UIItems;
using White.Core.UIItems.Finders;
using White.Core.UIItems.MenuItems;
using White.Core.UIItems.TreeItems;
using White.Core.UIItems.WindowItems;
using White.Core.UIItems.WindowStripControls;



The below code is the complete set of code that I used to implement the automation.

White.Core.Application app = White.Core.Application.Launch(The file path to the application exe that you are automating goes here in string format);
                    Window window = app.GetWindow(SearchCriteria.ByText(The form name of the app to automate should go here in string format), White.Core.Factory.InitializeOption.WithCache);
                    window.WaitWhileBusy();

                    //inputs the Client into the Client dropdown
                    var cName = window.Get<White.Core.UIItems.ListBoxItems.ComboBox>(SearchCriteria.ByAutomationId("cbClient"));
                    cName.Click();
                    window.WaitWhileBusy();
                    cName.Select(dt1.Rows[i][client].ToString());
                    window.WaitWhileBusy();

                    //inputs the Query into the Query dropdown
                    var cQuery = window.Get<White.Core.UIItems.ListBoxItems.ComboBox>(SearchCriteria.ByAutomationId("cbQueryfile"));
                    cQuery.Click();
                    window.WaitWhileBusy();
                    cQuery.Select(dt1.Rows[i][query].ToString());
                    window.WaitWhileBusy();

                    //checks the suppress error checkbox
                    var sError = window.Get<White.Core.UIItems.CheckBox>(SearchCriteria.ByAutomationId("cb_Suppress"));
                    window.WaitWhileBusy();
                    sError.Checked = true;
                    window.WaitWhileBusy();

                    //inputs the start date
                    var sDate = window.Get<White.Core.UIItems.DateTimePicker>(SearchCriteria.ByAutomationId("datePicker1"));
                    var st = Convert.ToDateTime(dt1.Rows[i][start]);
                    window.WaitWhileBusy();
                    sDate.SetDate(st, DateFormat.monthDayYear);
                    window.WaitWhileBusy();

                    //inputs the end date
                    var eDate = window.Get<White.Core.UIItems.DateTimePicker>(SearchCriteria.ByAutomationId("datePicker2"));
                    var et = Convert.ToDateTime(dt1.Rows[i][end]);
                    window.WaitWhileBusy();
                    eDate.SetDate(et, DateFormat.monthDayYear);
                    window.WaitWhileBusy();

                    //clicks the Run button
                    var rQuery = window.Get<White.Core.UIItems.Button>(SearchCriteria.ByAutomationId("btnRun"));
                    window.WaitWhileBusy();
                    rQuery.Click();
                    window.WaitWhileBusy();

                    var label = window.Get<White.Core.UIItems.Label>(SearchCriteria.ByAutomationId("label2"));
                    do
                    {
                        Thread.Sleep(5000);
                    } while (label.Text == "Running Query...");


                    //clicks the Retrieve button
                    var Retrieve = window.Get<White.Core.UIItems.Button>(SearchCriteria.ByAutomationId("btnRetrieve"));
                    window.WaitWhileBusy();
                    Retrieve.Click();
                    window.WaitWhileBusy();

                    var pBar = window.Get<White.Core.UIItems.ProgressBar>(SearchCriteria.ByAutomationId("progressBar1"));
                    do
                    {
                        Thread.Sleep(5000);
                    } while (pBar.Value != pBar.Maximum);

                    dataGridViewCAMList[colStatus, i].Value = complete;
                    UpdateLog(i, dataGridViewCAMList);

                    currentCount++;
                    i++;

                    app.Close();
                    app.Dispose();



Below is a breakdown of parts of the code above.

This is where you create and launch an instance of the application that you are automating
White.Core.Application app = White.Core.Application.Launch(The file path to the application exe that you are automating goes here in string format);


Next you must specify which window that it is that you will be automating.
Window window = app.GetWindow(SearchCriteria.ByText(The form name of the app to automate should go here in string format), White.Core.Factory.InitializeOption.WithCache);


Below shows code to wait while the “window” object is busy so as not to simply run through your code, skipping steps while the UI elements are busy, such as a dropdown populating.
window.WaitWhileBusy();


There are other ways perform this task such as waiting while the mouse in hour glass form, but that would require that the app to automate was coded to do exactly that while it was busy. You may find more information on “hooking” into events that will give you more precise control over this type of wait function in the references that I have included.

Below shows how one will “gain control” of the UI components of the app to automate. In the code below I am assigning the combobox for the client dropdown list to cName.
var cName = window.Get<White.Core.UIItems.ListBoxItems.ComboBox>(SearchCriteria.ByAutomationId("cbClient"));


In my application that I have created, the user will be able to create a list of reports to run all at one time. This list is then stored in a DataTable. Below shows the code to first click the combo box on the app to automate, wait while it populates, then select from the dropdown list the client name that has been stored in the “dt1” DataTable “client” column.
cName.Click();
window.WaitWhileBusy();
cName.Select(dt1.Rows[i][client].ToString());
window.WaitWhileBusy();



Below is the result of not having researched the above hook that I described. Luckily the creator of the app to automate used a label to convey what the application was doing. I simply used these labels texts to dictate what to do and when to do it using a do while loop. I also used something similar using the progressbar a few lines down the code.
var label = window.Get<White.Core.UIItems.Label>(SearchCriteria.ByAutomationId("label2"));
                    do
                    {
                        Thread.Sleep(5000);
                    } while (label.Text == "Running Query...");



Overall TestStack.White proved to be very useful for this particular project. I was able to bring a greater amount of efficiency to another application and process. So dig right in and give it a shot. Keeep in mind, you can also use this framework to actually test applications.

References and additional info:

UIA Verify Framework
TestStack.White
NuGet-TestStack.White



Is This A Good Question/Topic? 2
  • +

Replies To: C# TestStack.White for Beginners

#2 codeprada  Icon User is offline

  • Changed Man With Different Priorities
  • member icon

Reputation: 944
  • View blog
  • Posts: 2,353
  • Joined: 15-February 11

Posted 29 September 2013 - 07:02 PM

This has got my attention. Great find. Since this is using the IDs of the controls I'm guessing the target application can be minimized throughout the long process, correct?
Was This Post Helpful? 0
  • +
  • -

#3 GuageCage  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 5
  • Joined: 30-May 13

Posted 29 September 2013 - 08:15 PM

View Postcodeprada, on 30 September 2013 - 02:02 AM, said:

This has got my attention. Great find. Since this is using the IDs of the controls I'm guessing the target application can be minimized throughout the long process, correct?

I do believe so as the calling program that uses the "White" library instantiates the instance of the original application. I did not completed extensive testing after writing due to other projects that I had started. That and the fact that this project was not on "Company" time. However, I have received word that when the original app throws an exception, the calling app doesn't record the error. I did not include error capture from the called app due to time. I hope to get back to this project and do the following: Call reporting app in background; Mirror UI reporting from Reporting app to calling app; Allow for pausing of report, editing the dt1 list referred to and continuing. If you happen to get to any of this before I do, feel free to throw a link to your tutorial/walkthrough in these comments.

This post has been edited by GuageCage: 29 September 2013 - 08:16 PM

Was This Post Helpful? 1
  • +
  • -

#4 adnan123  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 21-January 10

Posted 04 October 2013 - 07:15 PM

View PostGuageCage, on 29 September 2013 - 08:15 PM, said:

View Postcodeprada, on 30 September 2013 - 02:02 AM, said:

This has got my attention. Great find. Since this is using the IDs of the controls I'm guessing the target application can be minimized throughout the long process, correct?

I do believe so as the calling program that uses the "White" library instantiates the instance of the original application. I did not completed extensive testing after writing due to other projects that I had started. That and the fact that this project was not on "Company" time. However, I have received word that when the original app throws an exception, the calling app doesn't record the error. I did not include error capture from the called app due to time. I hope to get back to this project and do the following: Call reporting app in background; Mirror UI reporting from Reporting app to calling app; Allow for pausing of report, editing the dt1 list referred to and continuing. If you happen to get to any of this before I do, feel free to throw a link to your tutorial/walkthrough in these comments.


Hi. I am new to the UI Automation and I have created a UI Automation application for automating Paint.net using .Net Automation UI. When Automating Paint.net a large number of times puts a lot of loads on the system. While searching across the solution I came across this tutorial of yours based on White (Now TestStack White). Could you guide me that is there any way to Automate any window application headless? Meaning without launching the application on the front and showing it to the user I want to run the application in the background. Does White supports it or do you know some other way to do it? Any suggestion will be highly appreciated.

Regards
Was This Post Helpful? 0
  • +
  • -

#5 stackeroo  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-January 14

Posted 06 January 2014 - 11:23 PM

Hi, I just want to tell you that this article is very helpful I created an account to vote up, and now I was able to start a simple automated test.

Looking forward to more tutorials, like using "Assert" in testing.

Thanks!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1