Chạy kiểm thử ứng dụng Windows từ Linux bằng máy ảo dùng một lần

Phần mềm14 tháng 10, 2026·13 phút đọc

QA Wolf đã giải quyết bài toán tự động hóa kiểm thử ứng dụng desktop Windows bằng cách đối xử với máy Windows như thiết bị di động: mỗi bài test nhận một máy ảo dùng một lần rồi hủy đi. Hệ thống dùng Kubernetes, Google Compute Engine và các giao thức CDP, Appium, WebRTC để điều khiển từ xa, giúp việc kiểm thử Windows nhanh và sạch sẽ như kiểm thử web.

Chạy kiểm thử ứng dụng Windows từ Linux bằng máy ảo dùng một lần

Kiểm thử ứng dụng desktop Windows từ lâu đã là một trong những yêu cầu được khách hàng hỏi nhiều nhất, đơn giản vì gần như không ai có hạ tầng để chạy song song hàng nghìn lượt kiểm thử mỗi tháng. Trong khi đó, kiểm thử web lại tương đối dễ: một trình duyệt headless khởi động trong container Linux chỉ mất vài giây, tốn một phần nhỏ của một xu và bị hủy ngay khi bài test kết thúc. Không có thứ tương đương như vậy cho ứng dụng desktop Windows.

Vì sao kiểm thử Windows lại khó đến thế

Khi kiểm thử ứng dụng Windows, mọi thứ đều nặng nề hơn:

  • Mỗi bài test cần một máy ảo (VM) đầy đủ, vì container Windows không có màn hình đồ họa để chạy ứng dụng.
  • Máy khởi động chậm. Một VM Windows khởi động nguội mất 2 đến 3 phút, trong khi container trình duyệt chỉ mất vài giây.
  • Phải có người đăng nhập. Giao diện trợ năng UI Automation (UIA) mà các công cụ kiểm thử dùng để tìm nút và ô nhập chỉ hoạt động trong một phiên desktop đang hoạt động và đã đăng nhập. Máy chỉ được bật lên là chưa đủ.
  • Máy nhớ mọi thứ. File đã cài, khóa registry, hồ sơ người dùng, thông tin đăng nhập đã lưu và các tiến trình còn sót lại đều tồn tại giữa các lượt chạy.
  • Mỗi ứng dụng mang theo cả một thế giới riêng: trình cài đặt, hộp thoại yêu cầu quyền quản trị, thư viện phụ thuộc có bản quyền, hộp thoại lần chạy đầu, màn hình đăng nhập.
  • Không có khả năng quan sát sẵn có. Trình duyệt cung cấp trace, log và ảnh chụp màn hình. Một máy Windows từ xa không cho bạn gì cả trừ khi bạn tự xây dựng.
  • Toàn bộ công cụ đều giả định môi trường Linux. Kubernetes, runner CI và phần lớn hạ tầng kiểm thử được thiết kế xoay quanh container Linux.

Giải pháp của QA Wolf là ngừng coi máy Windows như server mà coi chúng như điện thoại: một thiết bị được một bài test nhận, dùng một lần rồi vứt đi.

Kiến trúc: máy Windows như một thiết bị di động

Kiến trúc cơ bản vay mượn từ hạ tầng kiểm thử di động, vì kiểm thử di động có cùng những ràng buộc: mã kiểm thử không thể chạy trên chính thiết bị đang được kiểm thử, và mỗi bài test cần độc chiếm một thiết bị trong suốt quá trình chạy.

Vì máy Windows được mô hình hóa như một thiết bị trong Kubernetes, một bài test có thể yêu cầu bộ lập lịch thiết bị tùy chỉnh cấp cho nó một VM thông qua DeviceClaim, nhận lại thông tin kết nối, điều khiển thiết bị từ xa qua WebdriverIO và Appium, rồi giải phóng máy khi xong việc.

Mô hình thiết bị cần hai phần mở rộng cho Windows: thiết bị không nhất thiết phải nằm trong cụm Kubernetes (một VM trên GCE nằm hoàn toàn bên ngoài), và một claim có thể trả về địa chỉ kết nối của desktop, bao gồm cả CDP cho trình duyệt.

Hệ thống gồm ba phần:

  • Bộ điều khiển (controller) chạy trong Kubernetes, duy trì một nhóm VM Windows trên Google Compute Engine (GCE) và phân phát cho các bài test.
  • Runner — một pod Linux chạy mã kiểm thử.
  • VM Windows chạy ứng dụng cần kiểm thử, các công cụ tự động hóa và một desktop agent nhỏ.

Runner giao tiếp với VM qua ba kết nối: Playwright kết nối qua CDP (Chrome DevTools Protocol) cho mọi thứ trong trình duyệt, Appium xử lý các ứng dụng Windows gốc, và một luồng WebRTC truyền màn hình để người dùng xem trực tiếp và xem lại bản ghi sau đó.

Giống như trình giả lập Android, mỗi VM Windows đều dùng một lần. Không ai đăng nhập vào nó, vá nó hay giữ nó chạy hàng tuần. Một bài test nhận nó, dùng một lần, trả lại, và một VM mới thay chỗ.

Sáu bước của một lượt chạy

Khi người dùng khởi động một lượt chạy, trình tự diễn ra như sau:

  1. Bài test khởi động trong pod runner Linux và yêu cầu một thiết bị Windows.
  2. Bộ lập lịch cấp cho nó một VM từ nhóm máy đã khởi động và đăng nhập sẵn.
  3. Runner nhận địa chỉ kết nối của VM đó cho CDP, Appium và truyền màn hình.
  4. Ứng dụng cần kiểm thử được tải lên VM và khởi chạy.
  5. Bài test chạy. Màn hình được truyền trực tiếp và ghi lại.
  6. Bài test kết thúc, claim được giải phóng, VM bị hủy và một VM mới thay vào nhóm.

Điểm đáng chú ý là VM gửi nhịp tim (heartbeat) về bộ lập lịch trong lúc chạy. Nếu nó im lặng trong 60 giây, bộ điều khiển coi như bài test đã chết và thu hồi máy.

Thuê máy Windows theo yêu cầu

Việc phân phát máy Windows là nhiệm vụ của bộ lập lịch thiết bị — dịch vụ nội bộ vốn đã phân phát trình giả lập Android. Với Windows, nó được dạy thêm hai việc: duy trì một lượng VM thuê từ GCE và cấp một máy cho mỗi bài test yêu cầu.

Bộ lập lịch theo dõi đội máy qua ba tài nguyên tùy chỉnh của Kubernetes:

  • WindowsVMTemplate mô tả hình dáng của một VM: ảnh máy, kích thước và cấu hình.
  • WindowsVMPool mô tả cần giữ bao nhiêu VM sẵn sàng cho một template nhất định.
  • WindowsVM đại diện cho một máy cụ thể.

Những bản ghi này giúp trạng thái của đội máy luôn bền vững và quan sát được. Nếu bộ lập lịch khởi động lại, nó đọc lại các bản ghi và tiếp tục từ chỗ đã dừng; kỹ sư có thể kiểm tra bất kỳ pool hay VM nào bằng công cụ Kubernetes tiêu chuẩn.

Một reconciler bên trong bộ lập lịch liên tục so sánh bản ghi với thực tế đang chạy trên GCE và lấp đầy khoảng cách. Nếu một pool thiếu ba máy, nó tạo ba máy. Vì VM Windows mất hàng phút để tạo và khởi động, reconciler đẩy từng máy tiến một bước qua các lượt ngắn và ghi tiến độ vào bản ghi của VM đó.

Máy sạch, cấp phát nhanh

Mâu thuẫn trung tâm của hạ tầng kiểm thử desktop là: máy sạch thì chậm, còn máy nhanh thì không sạch. Khởi động lại từ ảnh mới tốn hàng phút, còn tái sử dụng máy nghĩa là mỗi bài test thừa hưởng những gì bài trước để lại.

Hệ thống xử lý cả hai mặt:

  • Mọi VM chỉ dùng một lần. Không bài test nào thấy được file, cài đặt hay thông tin đăng nhập của bài khác, nên cả một nhóm lỗi kiểu "chạy riêng thì đỗ, chạy trong bộ thì trượt" biến mất.
  • Pool ấm hấp thụ thời gian khởi động. Mỗi pool giữ sẵn các VM đã khởi động và đăng nhập, giúp bài test bỏ qua 2 đến 3 phút khởi động nguội.
  • Máy bị bỏ rơi được thu hồi. Một VM đã được claim sẽ báo cáo hoạt động trong lúc chạy test. Nếu im lặng 60 giây, bộ điều khiển thu hồi máy.
  • Thiếu dung lượng thì chuyển vùng. Nếu một zone của cloud không cấp được VM Windows, pool sẽ tạo nó ở zone khác.
  • Cập nhật diễn ra theo kiểu hao mòn tự nhiên. Vì VM dùng một lần, ảnh máy mới không cần quy trình nâng cấp. VM cũ bị dùng hết và thay bằng VM mới, các VM rảnh rỗi còn dùng ảnh cũ bị tái chế, nên pool dần tự chuyển đổi.

Việc biến máy thành dùng một lần loại bỏ rất nhiều công việc thường đi kèm với một đội máy Windows: vá máy chạy dài hạn, dọn dẹp sau kiểm thử và truy tìm lý do một máy hành xử khác các máy còn lại.

Ảnh máy Windows được thiết kế để tự động hóa

Ứng dụng gốc không có DOM cho Playwright điều khiển, nên một bản cài Windows tiêu chuẩn không thể chạy kiểm thử giao diện tự động. Appium, driver Appium cho Windows và WinAppDriver của Microsoft phải được cài đặt, cấu hình và chạy trong một phiên desktop hoạt động trước khi bài test đầu tiên đến — tất cả đều được đóng gói sẵn vào ảnh máy cơ sở.

Một script PowerShell tạo ra ảnh và công bố nó lên một image family trong GCE để dễ tái tạo. Không ai bảo trì thủ công một chiếc máy vàng.

Ảnh cơ sở bao gồm phần mềm phổ biến như Google Chrome và Adobe Acrobat, vốn thường được gọi trong kiểm thử E2E. Hệ thống cũng hỗ trợ các biến thể, ví dụ một ảnh Office xóa các hộp thoại lần chạy đầu của Microsoft Word trước khi bài test nhìn thấy chúng. Khi ứng dụng cần nhiều hơn thế — phần mềm bên thứ ba có bản quyền, cấu hình riêng hay ứng dụng đi kèm — khách hàng có thể cung cấp script để dựng ảnh riêng.

Mã kiểm thử vẫn ở lại Linux

Mọi thứ khác của một bài test QA Wolf — runner, bản ghi, tích hợp CI, báo cáo kết quả — đều được xây trên Linux. Chạy mã kiểm thử trên Windows nghĩa là phải xây và bảo trì hai bản sao của tất cả. Vì vậy mã kiểm thử không chạy trên Windows mà chạy trong pod runner Linux và điều khiển VM từ xa.

Khi runner kết nối tới VM, nó mở hai kênh tới cùng một máy: trình duyệt trên VM được truy cập bằng chromium.connectOverCDP() của Playwright, ứng dụng gốc qua WebdriverIO và Appium. Người viết test chỉ thấy một API duy nhất — entrypoint @qawolf/flows/windows cung cấp launch() cho trình duyệt và startApp() cho ứng dụng gốc, với một lệnh expect dùng matcher của Playwright hay WebdriverIO tùy theo đối tượng.

const app = await startApp("C:\\qawolf\\apps\\Invoicing.exe");
await app.$("~NewInvoiceButton").click();
await app.$("~CustomerName").setValue("Acme Corp");
await app.$("~SaveButton").click();
await expect(app.$("~StatusBar")).toHaveText("Invoice saved");

Hiệu quả thực tế là một bài test Windows trông giống hệt mọi bài test QA Wolf khác và chạy qua cùng một pipeline.

Đưa ứng dụng lên một máy hoàn toàn mới

Với VM dùng một lần, ứng dụng cần kiểm thử phải đến được máy mới trong mỗi lượt chạy, nhanh chóng và không tạo lỗ hổng bảo mật. Nó cũng thường đến dưới dạng trình cài đặt chứ không phải thứ sẵn sàng khởi chạy.

File của ứng dụng không bao giờ đi qua runner. Khi bài test gọi startApp(), hệ thống phát một URL có chữ ký, thời hạn ngắn, và VM tải ứng dụng trực tiếp từ kho lưu trữ qua Private Google Access — đường mạng nằm hoàn toàn bên trong hạ tầng của Google. Chỉ dịch vụ API trung tâm của QA Wolf mới ký được những URL đó. Mã kiểm thử chạy dưới người dùng không có đặc quyền và yêu cầu tải xuống thông qua một tiến trình cha đáng tin cậy.

Sau khi file đến nơi, VM xử lý việc cài đặt, hỗ trợ các định dạng .exe, .msi và .msix, kể cả truyền thuộc tính MSI. Bài test cũng có thể đẩy file lên VM và kéo file về, phục vụ các luồng như nhập tài liệu hay kiểm tra báo cáo xuất ra.

Nhìn thấy bên trong một desktop từ xa

Một VM Windows từ xa mặc định là một hộp đen. Viết test, gỡ lỗi hay xem lại lượt chạy đều đòi hỏi phải thấy được những gì bài test đã thấy, đúng lúc nó xảy ra.

Mỗi VM chạy một desktop agent nhỏ viết bằng Go. Nó chụp màn hình bằng FFmpeg và truyền qua WebRTC, đồng thời mô phỏng chuột, bàn phím và clipboard bằng cách gọi user32.dll của chính Windows. Agent không dùng CGo nên có thể biên dịch chéo sang Windows từ máy Mac hoặc Linux, với các phần đặc thù nền tảng nằm sau build tag của Go. Agent cho Linux, Windows và Mac dùng chung một mã nguồn, và bản build Linux không bị ảnh hưởng bởi mã Windows.

Agent đọc kích thước màn hình thật từ Windows thay vì tin vào cấu hình, nên luồng stream luôn hiển thị đầy đủ desktop với tỷ lệ đúng. Nó cũng cung cấp các endpoint chẩn đoán và log để báo cáo pipeline chụp hình và kết nối WebRTC đang thực sự làm gì.

Với người dùng QA Wolf, điều này mang lại:

  • Xem trực tiếp một bài test Windows ngay khi nó chạy.
  • Bản ghi video của mọi lượt chạy.
  • Công cụ chọn phần tử cho ứng dụng gốc, để chọn phần tử UIA khi viết test.
  • Ảnh chụp màn hình, hành động và kiểm tra phần tử qua MCP server (Model Context Protocol) và API công khai, để các tác nhân AI có thể làm việc với lượt chạy Windows giống như với lượt chạy trình duyệt.

Giữ mạng lưới khách hàng luôn đóng

Ứng dụng desktop thường nói chuyện với các hệ thống nằm sau tường lửa: API nội bộ, máy chủ cấp phép, cơ sở dữ liệu. Khách hàng cần biết chính xác thứ gì đang kết nối tới họ.

  • Một dải IP đã biết. Lưu lượng từ VM đi ra từ dải IP riêng của QA Wolf, nên khách hàng chỉ cần cho phép một dải thay vì một tập địa chỉ cloud luôn thay đổi.
  • Pool riêng vẫn riêng tư. Một pool chuyên dụng chỉ có thể được claim bởi workspace sở hữu nó.
  • Không lưu khóa cloud. Bộ điều khiển xác thực với Google Cloud qua Workload Identity, nên không có thông tin xác thực dài hạn nào nằm trên máy.
  • Không lưu giữ gì. Vì VM bị hủy sau mỗi bài test, không dữ liệu khách hàng nào còn lại trên máy sau lượt chạy.

Ý nghĩa với đội ngũ kiểm thử tại Việt Nam

Với các công ty phần mềm Việt Nam đang phát triển ứng dụng desktop cho thị trường nội địa hoặc xuất khẩu, bài toán kiểm thử tự động trên Windows thường bị đẩy lùi vì chi phí hạ tầng và công sức vận hành. Cách tiếp cận "máy Windows như thiết bị di động" cho thấy một hướng đi đáng tham khảo: thay vì cố duy trì một đội máy Windows chạy dài hạn, hãy biến chúng thành tài nguyên dùng một lần, cấp phát theo yêu cầu và tự hủy sau khi dùng.

Cách làm này cũng thu hẹp khoảng cách giữa kiểm thử web, di động và desktop: cùng một API, cùng một pipeline, cùng một quy trình quan sát và gỡ lỗi. Khi các tác nhân AI ngày càng tham gia vào quy trình kiểm thử, việc chuẩn hóa giao diện điều khiển cho mọi nền tảng sẽ trở thành lợi thế cạnh tranh thực sự.

Kiểm thử ứng dụng desktop Windows hiện đã chính thức hoạt động trên nền tảng QA Wolf và MCP của họ, dùng chung một API để viết test cho web, iOS, Android và Windows desktop.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗