UI automation of Windows Desktop based applications using Winium


Winium is a library Java library similar to Windows UI libraries/ TestStack.White tools for .Net, which we have seen in our previous blogs and it is developed by 2gis company. It is capable of doing UI automation for Windows desktop applications (both legacy Win32 UI apps as well as modern UWP applications). If you are looking for an open source and a good library to achieve the UI tests automation tasks, then this is a tool for you to ahead with.
Winium uses the Selenium WebDriver interface so its UI elements/ control identification and operations techniques are similar to Selenium when you see from language binding point of view. If you remember Selenium RC, wherein it spins up the browser compatible server to fire commands (REST API calls) on Web application. Winium too uses similar concept. It spins up the Winium desktop compatible driver using an executable file and listens on specified port in order to complete the desired operations.
Setup requirements:
  1. Winium libraries
  2. Winium desktop driver
  3. UISpy/ Inspect / VisualUIVerify etc.
  4. Java (JDK)

Steps to get started with your 1st UI test:
  1. Start Winium’s windows desktop driver executable by providing the path to Winium.Desktop.Driver.exe and the UI application executable path which is under test file using command below:
File file = new File(Winium.Desktop.Driver.exe");
service = new WiniumDriverService.Builder().usingDriverExecutable(file).usingPort(9999).withVerbose(true).withSilent(false).buildDesktopService();
options = new DesktopOptions();
options.setApplicationPath("Calculator.exe");
driver = new WiniumDriver(service, options);
In case the process already exists, to be safe side it is always better to kill such process (if running) and then go ahead with above command. Below Java code snippet can be used to kill such process, also you may like to free up the port 9999 in case any process is using that.
Process p = Runtime.getRuntime().exec("taskkill /F /IM Winium.Desktop.Driver.exe /T");                            
p.waitFor(30, TimeUnit.SECONDS);
p.destroyForcibly();
It will Launch the application and you are good to start with element identification and operation steps.
Note/ Tip: In few cases Winium server does not get start/ element identification fails with below exception in such can above operation (restarting the Winium server) can be retried. Refer logic below
public void waitForElementToGetEnabled(){
            WebElement element = null;
            int timeLimit = defaulttimeout;
            long timeDiff = 0;
            Date d2 = null;
            Date d1 = new Date();
            do{
                  d2 = new Date();
                  timeDiff = ((d2.getTime() - d1.getTime()) / 1000);
                  try{
                        element = rootelement.findElement(By.xpath("//button[@AutomationId='clearButton']"));                       
                        if(element != null && element.isEnabled())
                              return;
                  } catch (Exception e) {
                        e.printStackTrace();
                        if (Arrays.toString(e.getStackTrace()).contains("java.net.ConnectException") || Arrays.toString(e.getStackTrace()).toString().contains("System.Net.Sockets.SocketException:"))
                              startWiniumServer();
                  }
            }while(timeDiff <= timeLimit);
      }

  1. Element identification can be done in different ways – AutomationId, Name, ClassName, ControlType, XPath etc. It is always better to use the identifier which uniquely identifies the element in the application Window (The default search happens throughout the desktop screen). To make Winium just to work on intended application one would definitely choose to find the application Window element first – let’s call it as root element and all other operations (test steps) can be performed to child elements of the root element.
rootelement = driver.findElementByXPath("//window[@LocalizedControlType='window' and @Name='Calculator']");
There are tools like UISpy.exe/ inspect.exe / UIVerify.exe which can be easily downloaded from internet (Inspect.exe tool comes as a part of Visual Studio bundle). These are used to identify the Windows applications UI elements. Refer screenshot for finding the value for different identifiers/ selectors (AutomationId, Name, ClassName, ControlType, XPath etc.)


As you can see in the righmost section the properties for selected element ‘C’ on Calculator window can be seen. In this case AutomationId = clearButton can be used in our JAVA code.
To find the element using Id/ XPath Selenium WebDriver methods can be leveraged:
WebElement element = rootelement.findElement(By.xpath("//button[@AutomationId='clearButton']");
  1. To perform any operations you can use the methods supported by this element type. In this it is button so click can be performed.
element.click();
In case you want to get the text property for the element(which is really useful in case you are looking for Localization tests automation for desktop UI applications), again you can choose the below method
String title = element.getText();
And then apply an JuUnit/ TestNG asserts on it to validate the test ecxpections.
Assert.AssertEquals(title, “C”, “Failed to validate the Clear button title”);

Few tips:
1.  In case there are applications which required admin privileges to interact with UI, the program which is running your UI tests (intern using Winium) should be run with higher privileges.
2.  As mentioned above always find the window element for application under test first and set it as rootelement to minimize the operation scope for Winium and this will make the UI tests faster compared to running using the driver object – which uses the complete desktop screen / all running application scope.
3.  In case certain elements are not working / operable with Winium, always have another backup logic / provision in place in the framework to handle such cases – AutoIT, Sikuli, Robot libraries can be used in specific such cases.

Comments