E2exe: How we solved Windows desktop automation for enterprise scale | QA Wolf
Pangram verdict · v3.3
We believe that this text is a mix of AI and human-written content.
AI likelihood · overall
AIArticle text · 809 words · 7 segments analyzed
There’s a good reason why testing Windows desktop apps was one of the most requested features from customers: no one in the world has the infrastructure to parallelize thousands of runs per month. Web testing infrastructure is relatively easy: a headless browser starts inside a Linux container in a couple seconds, costs a fraction of a cent to run, and gets thrown away when the test ends. There’s no equivalent for testing a Windows desktop app. When testing Windows apps: Every test needs a full VM because Windows containers don’t include a graphical desktop to run the app. The machines are slow to start.
A cold Windows VM takes 2 to 3 minutes to boot. A browser container takes seconds. Someone has to be logged in. Windows UI Automation (UIA), the accessibility interface that test tools use to find buttons and fields, only works inside an active, logged-in desktop session. A machine that's merely switched on isn't enough. Machines remember things. Installed files, registry keys, user profiles, saved logins and stray processes all survive between runs. Every app brings its own world. Installers, admin prompts, licensed dependencies, first-run dialogs, sign-ins, etc. There's no built-in visibility. A browser hands you traces, logs and screenshots. A remote Windows machine hands you nothing unless you build it. The tooling assumes Linux. Kubernetes, CI runners and most test infrastructure were designed around Linux containers. Our answer was to stop treating Windows machines as servers and treat them like phones: a device that one test claims, uses once, and throws away. The Architecture The basic architecture borrows from our mobile testing infrastructure, because mobile testing has the same constraints: the test code can't run on the device it's testing, and each test needs a device to itself while it runs.
Since a Windows machine is modeled as a device in Kubernetes, a test can ask our custom device scheduler for a VM with a DeviceClaim, get its connection details back, control the device remotely through WebdriverIO and Appium, and release the machine when the test is done.
Windows needed two extensions to the device model: a device no longer has to live inside the Kubernetes cluster (a GCE VM lives outside it entirely), and a claim can return a desktop's connection addresses, including CDP for browsers. Otherwise, the Windows runner follows the mobile runner's lifecycle step for step (claim, heartbeat, record, connect, run, release), tests talk to native apps through the same WebdriverIO and Appium pairing, and private Windows pools work the way private iOS devices do. Like the mobile system, it has three parts: A controller running in Kubernetes. It keeps a pool of Windows VMs on Google Compute Engine (GCE) and hands them out to tests. A runner, a Linux pod that runs the test code. A Windows VM that runs the app under test, the automation tools and a small desktop agent. The runner talks to the VM over three connections. Playwright connects over CDP (Chrome DevTools Protocol) for anything in a browser. Appium handles native Windows apps. A WebRTC (Web Real-Time Communication) stream carries the screen so people can watch the test live and review a recording afterward. Like an Android emulator, each Windows VM is disposable. Nobody logs into it, patches it or keeps it running for weeks. A test claims it, uses it once and gives it back, and a fresh VM takes its place.
A Linux runner pod runs the test code (@qawolf/flows/windows). Step 1: the test claims a device from the device scheduler, which runs with a Windows VM reconciler in the Kubernetes controller. Step 2: the scheduler assigns a ready Windows VM on Google Compute Engine (GCE) to the test.
The scheduler also keeps a pool of warm Windows VMs ready through the GCE API. The test then talks to the claimed VM over three connections: CDP (Playwright) to a browser, and Appium (WebDriver) to Appium and WinAppDriver, which drive the app under test through UI Automation (UIA). A Go desktop agent on the VM sends a WebRTC screen stream back to the runner. So now, when a user kicks off a run: The test starts in a Linux runner pod, which asks for a Windows device. The scheduler assigns it a VM from a pool of machines that are already booted and logged in. The runner receives that VM's connection addresses for CDP, Appium, and screen streaming. The app under test is delivered to the VM and launched. The test runs. The screen streams live and is recorded. The test finishes, the claim is released, and the VM is destroyed. A fresh VM takes its place in the pool.
Step 1 of 6The test starts in a Linux runner pod, which asks for a Windows device.Sequence between the runner pod (test code), the device scheduler (Kubernetes) and a Windows VM from the warm pool.