# WinAppDriver - windows application test automation with Python https://www.fleekitsolutions.com/use-winapp-driver-python/ ## Setup and install ### Configuring the WinAppDriver Environment 1. Step 1: Download and install WinAppDriver 2. Step 2: Enable **Developer Mode** 3. Step 3: Download and install **Windows SDK** ### Download and install Appium ``` pip install Appium-Python-Client ``` ## Scripts ### Desire capabilities https://github.com/appium/appium-windows-driver#windowsdriver-specific-capabilities - Desire capabilities: app - Set the installed application ID #### Set application exe path 1. When it's a portable application, or when there's no ID of the application. Put the application file under the project working directory. 2. Get the root directory of the project https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure/45944002 ``` rootDir = os.path.dirname(os.path.abspath(__file__)) ``` 3. Set the value of the app of desired capabilities to the **root directory + relative path of the application** under the project working directory. Use path joins to prevent slash issue of the path. ``` desiredCaps = {} desiredCaps["app"] = os.path.join(rootDir, "appFolder", "app.exe") ``` #### Desire capabilities: appTopLevelWindow ``` desiredCaps["appTopLevelWindow"] = ... ``` ## Tools Using **Inspect.exe** to locate elements ## Flows Auto launch WinAppDriver (kill process if it exists) -> Run test scripts -> kill WinAppDriver process after tests finish ## Locate elements http://appium.io/docs/en/commands/element/find-element/ To locate elements by its AutomationId on Inspect.exe, use: ``` driver.find_element_by_accessibility_id("AutomationId of element") ``` ## Issues and solutions ### Fix "AttributeError" when call webdriver.Remote() after setting Desire capabilities https://stackoverflow.com/questions/2720014/how-to-upgrade-all-python-packages-with-pip **Solution:** upgrade all installed pip packages ``` pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U ``` ### Handling NoSuchElementException When locating elements of a new window after window changes https://stackoverflow.com/questions/10629815/how-to-switch-to-new-window-in-selenium-for-python https://github.com/microsoft/WinAppDriver/issues/375 **Solution:** Get all windows of the application, and check how many windows exist: ``` windows = self.driver.window_handles print(len(windows)) for window in windows: print(window) ``` Check if the current window is different from the previous window. If there is only one window after window switch, print the address of the window to check: ``` print(self.driver.window_handles[0]) # Do something here that leads to windows change print(self.driver.window_handles[0]) ``` Get the current window again, and set focus to the window (If there's only one window after window switching): ``` self.driver.switch_to.window(self.driver.window_handles[0]) ``` Switch to the target window (If there are many windows): ``` self.driver.switch_to.window(self.driver.window_handles[indexOfTargetWindow]) ``` ## Setup and teardown (init driver and close driver) https://stackoverflow.com/questions/52245411/quit-driver-instance-in-pytest-after-all-the-tests-are-executed ### To close the windows application after tests 1. Use Pytest setup and teardown and get all windows, close all windows in the teardown function 2. Add try catch and finally in the try catch function, call quit() in the finally block ``` try: # do test actions ... except: # do things when Exception happens, eg, softAssert or print Exception string ... finally: driver.close() driver.quit() ``` ## Load different tests based on the OS ``` import platform currentOS = platform.platform() if "windows" in currentOS: # Run windows related tests ... elif "linux" in currentOS: # Run linux related tests ... ``` ###### tags: `winappdriver` `python` `test automation` `software test`