# 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`