logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·30.10.26
← Back to news

Running Windows desktop tests from Linux with disposable VMs

Original article
qawolf.com|49 points|22 comments|by jadenlemmon|Oct 14, 2026

Scaling Windows Desktop Automation via Disposable VMs

By Jaden Lemmon | October 14, 2026

For a long time, automating Windows desktop applications was a major pain point for our clients. The reason is simple: almost no one possesses the infrastructure required to parallelize thousands of Windows test runs every month.

The Infrastructure Gap: Web vs. Windows

Testing for the web is streamlined. You spin up a headless browser in a Linux container, it costs nearly nothing, and you delete it the moment the test concludes. Windows is a different beast entirely.

FeatureWeb Testing (Linux)Windows Desktop Testing
EnvironmentLightweight ContainerFull Virtual Machine (VM)
Startup TimeSecondsMinutes
StateEphemeral/CleanPersistent (Registry, Profiles)
UI AccessDOM/CSS SelectorsUI Automation (UIA)
Cost≈0.001\approx 0.001≈0.001 per runVM Hourly Rate×Duration\text{VM Hourly Rate} \times \text{Duration}VM Hourly Rate×Duration

The challenges are systemic:

  • Windows Containers →\rightarrow→ They lack the graphical desktop required for most apps.
  • UIA Constraints: Windows UI Automation only functions within an active, authenticated desktop session.
  • State Pollution: Registry keys, cached logins, and zombie processes linger between tests.
  • Setup Friction: Dealing with admin prompts, installers, and first-run wizards is a nightmare.

"A remote Windows machine provides absolutely nothing unless you explicitly build it."

Since most CI/CD pipelines and Kubernetes clusters are optimized for Linux, we had to pivot our strategy.


The Solution: The "Mobile Device" Model

Instead of treating Windows machines as persistent servers, we decided to treat them like mobile phones: a device is claimed by one test, used once, and then discarded.

The High-Level Architecture

We adapted our existing mobile testing framework. In that model, the test logic cannot run on the device itself. By modeling a Windows VM as a "device" within Kubernetes, a test can request a DeviceClaim, receive connection details, execute commands via WebdriverIO and Appium, and then release the VM.

Key Extensions for Windows:

  1. External Hosting: VMs live on Google Compute Engine (GCE), outside the K8s cluster.
  2. Multi-Protocol Access: Claims return multiple addresses, including the Chrome DevTools Protocol (CDP) for browser-based elements.

System Components

The system consists of three primary pillars:

  • The Controller (K8s): Manages the GCE VM pool and handles distribution.
  • The Windows VM (GCE):
    • Runs the target application.
    • Hosts automation tools and a Go-based desktop agent.
    • Uses WebRTC to stream the screen for live monitoring and recording.
  • The Linux Runner Pod: Executes the actual test code using @qawolf/flows/windows.

Architecture Diagram Placeholder


The Execution Lifecycle

When a user triggers a test run, the following sequence occurs:

Detailed Step-by-Step:

  1. Request: The Linux pod asks the scheduler for a device.
  2. Assignment: The scheduler picks a "warm" (already booted and logged-in) VM from GCE.
  3. Connection: The runner receives the connection strings for:
    • CDP →\rightarrow→ Playwright (for browser content).
    • Appium/WinAppDriver →\rightarrow→ UIA (for native Windows content).
    • WebRTC →\rightarrow→ Visual stream.
  4. Deployment: The startApp() command triggers the VM to download the app via a signed URL and install it.
  5. Execution: Commands are sent; the VM streams video back. If the VM stops sending heartbeats for 60 seconds, the scheduler reclaims it.
  6. Cleanup: The claim is released, the VM is terminated, and a fresh one is added to the pool.

Managing the Fleet with Kubernetes

To manage these VMs at scale, we integrated them into our existing emulator scheduler using three custom Kubernetes resources:

  • WindowsVMTemplate: Defines the "blueprint" (machine image, CPU/RAM, config).
  • WindowsVMPool: Defines the desired count of ready-to-use VMs for a specific template.
  • DeviceClaim: The request object used by a test to acquire a VM.

Example Configuration Logic:

apiVersion: qawolf.io/v1
kind: WindowsVMPool
metadata:
  name: enterprise-app-pool
spec:
  template: windows-win11-standard
  minReady: 5
  maxReady: 20

By using these resources, our engineers can use standard kubectl commands to inspect the health of the Windows fleet. If the scheduler restarts, it simply reads these records and resumes management without losing track of the VMs.

Final Checklist for Implementation:

  • Provision GCE Project
  • Configure Go Desktop Agent
  • Set up WinAppDriver on Base Image
  • Implement WebRTC Streaming
  • Integrate with K8s Custom Resource Definitions (CRDs)