⬆️ ⬇️

Automate testing of Windows applications using Winium

What to eat



With Winium, we can automate ordinary Windows applications. As a rule, Winium can work with those elements that can be found in windows using standard Windows tools (as a rule, these elements have a tab order). These tools are supplied in standard whales (download, for example, here , after installation, search for them, for example, here: C: \ Program Files (x86) \ Windows Kits \ 8.1 \ bin \ x64). I consider inspect and uiverify to be the most convenient for me, but the taste and color, as some of my comrades say, are all different markers.



However, in order to automate self-written applications, it would be nice for fellow developers to make sure that the elements have adequate ClassName, Name and AutomationId. Of course, in certain situations, we can save the transfer of pressing certain keys and clicking the mouse on the coordinates, but this is not a panacea. It is better to always have a set of pre-prepared “levers” in the form of descriptions of objects than to rely on the fact that the GUI will always be the same and behave well in different situations.



With Winium in normal mode, you can communicate through Selenium using Python and Java; one way or another, but the stars rose so that the choice fell on Java.



Installation



First, we need Winium Desktop Driver. You can download it, for example, here . We will be required to unzip this case and run it during tests. Through it, the Selenium server will communicate with Windows applications.

')

Secondly, in fact, the Java-IDE (used IntelliJ IDEA Community, for which he thanks a lot) and JDK. Do not forget to check / set the JAVA_HOME environment variable with the path value to the JDK (in my case - C: \ Program Files \ Java \ jdk1.8.0_131).



Thirdly, we also need the Selenium server - go here , download the Selenium Standalone Server (JAR file).



Next, by setting up the project, we create a new Java project and add it to the External libraries (click the Project Structure button (or Ctrl + Alt + Shift + S), then select Libraries and click the plus sign in the Project Settings ) our selenium JAR file. That's all you can write.



Using



In order for everything to work, you need to run Winium.Desktop.Driver with admin rights at the time of using the tests. But, since the driver may hang from time to time for one reason or another, it is convenient to run it before each test and kill it at the end. For example, you can use ProcessBuilder for this purpose:



ProcessBuilder pro = new ProcessBuilder(windriverPath + windriverName, windriverParam); shell = pro.start(); //< > shell.destroy(); 


where for convenience of deployment you can specify windriverPath , windriverName is the path to the driver and the name of the executable file; windriverParam - additional launch parameters, if any, are required.



At the beginning of the beginning in the code you need to attach the driver variable to the Winium driver itself:



 DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability("app","<path to executable file>"); //    -  cap.setCapability("launchDelay","5"); //    WebDriver driver = new RemoteWebDriver(new URL("http://localhost:9999"),cap); //      Winium  


If we don’t want to launch any application, but simply attach to some already running one, then lines 2 and 3 can be safely omitted.



In order for us to work with any element, we first need to attach to it. Three attachment mechanisms are known - By.name - by the Name field, By.className - by the ClassName field, and By.xpath for more sophisticated search conditions. Also, if we need the first / only element, we can use the findElement method, and if we want to get a list of all such elements, then we need to use the findElements method. In the second case, the elements will be added in the order of the tab order. Examples of using:



 WebElement wrk = driver.findElement(By.name("  Name")); // ,    Name List<WebElement> wrkL = driver.findElements(By.className("  ClassName")); //     ClassName 


We can also attach to elements of another element:



 WebElement wrk1 = wrk.findElement(By.name("  Name")); 


If the first two attachment mechanisms are very narrowly specialized, i.e. work strictly in a hierarchical structure and strictly with the Name and ClassName fields, then to work with other cases we need a third mechanism, namely By.xpath .



In this mechanism, everything is strictly according to the canons of using xpath (in any case, everything worked as needed from the cases used). With xpath, you can get and process IsOffscreen, AutomationId, HasKeyboardFocus fields:



 WebElement field = wrk.findElement(By.xpath("*[@HasKeyboardFocus='True']")); //   wrk,     


When using xpath, especially if we are working under more complex conditions, it is convenient for tracking possible errors to log the entire line passed to xpath:



 String xpathStr = "*[(@AutomationId='" + autId + "') and (@IsOffscreen='False')]"; //       -  AutomationId = autId     IsOffscreen = False log("Performing xpath search: " + xpathStr); WebElement tWrk = wrk1.findElement(By.xpath(xpathStr)); 


Of course, we can search for xpath with elements not only of the current window, but such a search can last quite a long time.



There are other ways of searching, but, anyway, it all comes down to those described above. For example, such .



We may also need to simulate key input from the keyboard. In the usual manner, this is done with the sendKeys (“Character String”) method of the element. However, it should be remembered that some symbols are used as service symbols and must be escaped (for example, "+" is Shift, and in order to enter "+", you must pass the sequence "+ ="). For the convenience of using the code, you can write a wrapper that automatically replaces all "+" with "+ =", but here it is more convenient for someone. You can learn more about the standards for the transmission of key combinations, for example, here . Nevertheless, there were problems with the correct transmission of key presses on the keyboard, so unfortunately, with the current version of the driver, you will have to look for workarounds.



One of these workarounds is clicking the coordinates of a given element with the mouse. This is not a trivial task, but here you can use Actions:



 Actions builder = new Actions(driver); Action enter = builder .moveToElement(wrk) .moveByOffset(x,y) .click() .build(); enter.perform(); 


where wrk is the name of WebElement, from the center of which we will move the mouse; x , y - the distance that we will move (a positive value of x moves the cursor to the right, a positive y - down).



Just a little bit about the overall project structure.



As it was already slightly noted above, “levers” are the main element of interaction with the outside world. They can be conveniently described by a class with the name , className and automationId fields and stored in separate classes by blocks.



Since automated tests often repeat any steps of each other, these procedures are also conveniently arranged in the form of separate static methods and also stored in separate classes by blocks.



Everything else can be safely done as usual - classes with tests, a class for running tests, and so on.



Conclusion



In general, immersion into the world of Winium is quite interesting and not very difficult. Thanks to all readers who have read this post to the end. I really hope that this post will help someone in mastering Winium. Special thanks to my partner Eugene, with whom we plunged into his jungle. All good!

Source: https://habr.com/ru/post/331292/



All Articles