At a glance
| Tool | Platforms | Licence | Best for |
|---|---|---|---|
| Appium NovaWindows Driver |
|
Apache-2.0 | Appium 2 driver for Win32, WPF, WinForms and UWP built on UI Automation, without WinAppDriver. |
| Appium Windows Driver |
|
Apache-2.0 | The original Appium driver; proxies to Microsoft's WinAppDriver, which is no longer actively developed. |
| Appium Mac2 Driver |
|
Apache-2.0 | Drives macOS applications through Apple's XCTest framework; needs Xcode on the test machine. |
| pywinauto |
|
BSD-3-Clause | Python library for Windows GUI automation through Win32 messages or UI Automation. |
| Dogtail |
|
GPL-2.0 | Python GUI testing for GTK and Qt applications through the AT-SPI accessibility bus. |
Web testing has converged on a handful of excellent tools. Native desktop testing has not: each operating system exposes its user interface through its own accessibility API, and every automation tool is, underneath, a client of that API. Understanding this one fact explains most of what works, what does not, and why.
How desktop automation works
| System | Accessibility API | What tools see |
|---|---|---|
| Windows | UI Automation (UIA) | A tree of elements with control types, names, automation IDs and patterns (Invoke, Value, Toggle…) |
| macOS | Accessibility (AX) API, used by XCTest | AX elements with roles, titles and identifiers; access must be granted in System Settings |
| Linux | AT-SPI over D-Bus | Accessible objects exposed by GTK and Qt; quality depends on the toolkit and the application |
The practical consequence: an application that is accessible is automatable. Giving controls stable identifiers — AutomationProperties.AutomationId in WPF, accessibilityIdentifier in AppKit, accessible names in GTK — is the single most effective thing developers can do for testability, and it helps real users of assistive technology at the same time.
Windows: Appium drivers and pywinauto
For years the standard answer was Microsoft's WinAppDriver, used through Appium's Windows driver. WinAppDriver has not seen active development for a long time, and it shows: slow XPath queries, keyboard-layout problems and a developer-mode requirement.
NovaWindows is a newer Appium 2 driver that talks to UI Automation directly, with no WinAppDriver process in between. It covers the same application types — Win32, WPF, WinForms and UWP — and is designed as a near drop-in replacement, so existing Appium tests mostly keep working.
npm install -g appium
appium driver install --source=npm appium-novawindows-driver
appiumfrom appium import webdriver
from appium.options.common import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy
options = AppiumOptions()
options.set_capability('platformName', 'Windows')
options.set_capability('appium:automationName', 'NovaWindows')
options.set_capability('appium:app', r'C:\Windows\System32\notepad.exe')
driver = webdriver.Remote('http://127.0.0.1:4723', options=options)
try:
editor = driver.find_element(AppiumBy.CLASS_NAME, 'RichEditD2DPT')
editor.send_keys('Hello from a test')
finally:
driver.quit()If your test team writes Python and only targets Windows, pywinauto is a lighter alternative: no server, no WebDriver protocol, direct access to UIA or to Win32 messages for older applications.
macOS: the Mac2 driver
Appium's Mac2 driver runs a small XCTest-based agent that drives applications through Apple's own testing framework. It requires Xcode on the machine and, the first time, explicit permission: the test runner must be allowed under *System Settings → Privacy & Security → Accessibility*.
xcode-select --install # or a full Xcode from the App Store
appium driver install mac2
appiumSessions use platformName: mac and automationName: Mac2, with the target identified by its bundle identifier, such as com.apple.TextEdit. If you own the application's source, plain XCUITest in Xcode is the more direct route; Mac2 earns its place when one Appium-based suite must also cover Windows.
Linux: AT-SPI tools
Linux has no Appium driver as mature as the Windows and macOS ones. The dependable route is the accessibility bus itself: Dogtail (Python, used for years to test GNOME applications) walks the AT-SPI tree of GTK and Qt applications and clicks, types and asserts by role and name.
- Make sure accessibility is enabled for the session — in GNOME,
gsettings set org.gnome.desktop.interface toolkit-accessibility true. - In headless CI, run the application under a virtual display (
xvfb-run) together with a D-Bus session bus. - Wayland restricts synthetic input more than X11. Tools that inject keystrokes may need an X11 session or the compositor's own test hooks.
When the UI tree is not enough
Games, canvas-based editors and some cross-platform toolkits draw their own pixels and expose little or nothing to the accessibility API. Image-recognition tools such as SikuliX can still drive them, at the cost of brittleness: a theme change or a different DPI setting breaks the match. Treat them as a last resort, and invest instead in exposing a test hook or an accessibility layer in the application.
Choosing a stack
| Situation | Recommended approach |
|---|---|
| Electron or web-based desktop app | Playwright, not a native driver |
| One suite for Windows and macOS native apps | Appium with NovaWindows and Mac2 |
| Windows only, Python team | pywinauto |
| macOS only, you own the code | XCUITest in Xcode |
| GTK or Qt application on Linux | Dogtail over AT-SPI |
Whatever the tool, run desktop tests on disposable machines — a virtual machine snapshot or a fresh CI runner — so that a test that crashes halfway never leaves the next one a dirty desktop. Our guide to virtual machines and sandboxes covers how.