3238 字
16 分鐘
Python 開發的按鍵精靈:Airtest Project 筆記

想讓電腦自己找到畫面上的按鈕、點下去,再接著做下一個動作,可以試試 Airtest。它用圖片辨識尋找操作目標,搭配 AirtestIDE 產生 Python 腳本,操作方式有點像按鍵精靈。

Airtest Project 是網易研發並開源的自動化測試框架,著重在腳本錄製與遊戲測試。它希望降低腳本撰寫與維護的門檻,讓不熟悉程式的人也能透過點擊、拖曳等操作產生腳本;另一個方向則是支援不同遊戲引擎與平台。這些是專案的目標,實際使用仍要確認裝置、畫面和操作方式是否適用。Airtest 官方介紹(在新分頁開啟)有列出框架的功能與支援平台。

錄製可以省下輸入基本指令的時間,等待畫面、判斷成功或失敗、處理例外等流程,還是需要自己補。下面以 Windows 為主,做一個「找到按鈕 → 點擊 → 確認結果」的小練習。

Airtest、AirtestIDE 和 Poco 有什麼差別?#

這幾個名稱經常一起出現,安裝前先分清楚比較不會混淆。

名稱負責的工作
AirtestPython 自動化框架,用圖片辨識尋找畫面上的目標,再執行點擊、拖曳等動作。
AirtestIDE圖形化編輯器,提供裝置連線、截圖、腳本錄製、執行與報告查看功能。
Poco依介面元件的結構、名稱或屬性定位目標,適合能取得 UI 階層的情境。

Airtest 主要靠「畫面長什麼樣子」找東西,Poco 則能在支援的環境裡查找介面元件。遊戲使用 Poco 時,可能需要在專案內接入對應的 SDK,不能只安裝 Python 套件就讀到所有遊戲的按鈕。官方快速入門(在新分頁開啟)有說明兩種定位方式。

如果只是想做 Windows 熱鍵或鍵盤操作,也可以參考另一篇用 Python 寫 AutoHotkey 腳本。這篇先練習 Airtest 的圖片辨識流程。

環境安裝與設定參考#

先用 AirtestIDE 錄製#

到 AirtestIDE 官網(在新分頁開啟)下載 Windows 版本,依下載版本的說明解壓縮、啟動。IDE 自帶執行環境,單純從 IDE 錄製及執行腳本時,不必先替系統 Python 安裝 Airtest。

啟動後,先選擇要連線的 Windows 視窗。裝置面板通常會有選取視窗或搜尋視窗的功能;不同版本的按鈕名稱可能略有差異。若嵌入後畫面或點擊異常,可以改用設定裡的 Connect windows without embedding。詳細步驟見官方 Windows 視窗連線說明(在新分頁開啟)。

需要命令列執行時,再準備 Python#

下面的練習會用 Python 建立測試視窗,也會示範從 PowerShell 執行 Airtest,因此另建一個虛擬環境。

這裡選用 Python 3.11 作為環境範例;電腦要先安裝這個版本,py -3.11 才能使用。Airtest 1.4.3 的相依套件包含 numpy<2.0 和較舊的 OpenCV 版本,新版 Python 若遇到安裝問題,需先核對套件相容性,不要直接把版本限制移除。版本與相依資訊可查 PyPI 的 Airtest 頁面(在新分頁開啟)。

在準備放練習檔案的位置開啟 PowerShell:

Terminal window
New-Item -ItemType Directory -Path airtest-practice
Set-Location airtest-practice
py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install "airtest==1.4.3"
.\.venv\Scripts\python.exe -m airtest version

本文以 Airtest 1.4.3 的 API 為準。最後一行能顯示版本資訊,表示這個虛擬環境可以載入 Airtest。以下都直接呼叫 .venv 裡的 Python,不需要執行 Activate.ps1,也不必為了啟用環境修改 PowerShell 執行原則。

IDE 內建的 Python 與這個虛擬環境是分開的。在其中一邊安裝套件,不會自動讓另一邊也能使用;若要讓 IDE 改用本地 Python,需在 IDE 的設定中指定 .venv\Scripts\python.exe。可參考官方執行環境說明(在新分頁開啟)。

建立一個用來練習的 Windows 視窗#

先做一個只有狀態文字和按鈕的小程式,避免一開始就拿複雜的遊戲畫面練習。把下面內容存成 demo_app.py:

import tkinter as tk
def mark_done():
status.set("Done")
root = tk.Tk()
root.title("Airtest Demo")
root.geometry("360x220")
root.resizable(False, False)
status = tk.StringVar(value="Ready")
tk.Label(root, textvariable=status, font=("Arial", 24)).pack(pady=24)
tk.Button(
root,
text="Run test",
font=("Arial", 16),
command=mark_done,
).pack()
root.mainloop()

在 PowerShell 執行:

Terminal window
.\.venv\Scripts\python.exe .\demo_app.py

畫面應該會出現 Ready 和 Run test 按鈕,點一下後,狀態會變成 Done。這個程式只修改自己的視窗內容,不會操作其他應用程式。終端機會持續執行到視窗關閉;後面的命令請另開一個 PowerShell,切到相同的 airtest-practice 資料夾執行。

用 AirtestIDE 產生第一份腳本#

在 AirtestIDE 建立一份 demo.air 腳本,存到剛才的練習資料夾,再連線到標題為 Airtest Demo 的視窗。

.air 是一個資料夾,裡面放同名 Python 檔案和辨識用的截圖。完成後,檔案大致會長這樣:

airtest-practice/
├── .venv/
├── demo_app.py
└── demo.air/
├── demo.py
├── run_button.png
└── done_label.png

run_button.png 和 done_label.png 要從你自己的測試視窗擷取,無法只靠複製下面的 Python 程式產生。

  1. 在 Airtest 輔助面板選擇 touch,框選 Run test 按鈕,讓 IDE 產生點擊語句與圖片。將圖片另存或重新命名為 run_button.png;如果改了檔名,也要同步修改程式內的引用。
  2. 手動點一下按鈕,讓畫面顯示 Done。
  3. 選擇 assert_exists,框選 Done 文字,儲存為 done_label.png,作為執行後的檢查目標。
  4. 關閉並重新開啟測試視窗,讓狀態回到 Ready,再重新連線。

也可以用錄製功能產生操作,再回頭整理程式。入門時一次只做一兩個動作,確認點擊和截圖都正確,再接著錄,比一次錄完整個流程容易找出問題。

IDE 自動產生的圖片名稱通常含有時間數字,不一定和本文相同。若保留 IDE 的名稱,就把範例裡的兩個檔名換成實際名稱。框選與錄製功能可參考官方腳本錄製教學(在新分頁開啟)。

把腳本補成「等待、點擊、檢查」#

將 demo.air/demo.py 整理成下面內容:

from airtest.core.api import (
Template,
assert_exists,
auto_setup,
snapshot,
touch,
wait,
)
auto_setup(__file__)
button = Template("run_button.png")
finished = Template("done_label.png")
button_pos = wait(button, timeout=10)
touch(button_pos)
assert_exists(finished, "Clicking Run test should show Done")
snapshot(msg="Demo completed")

這份 .air 腳本預期由 IDE 或後面的 Airtest 命令列啟動,裝置連線與紀錄路徑交給啟動方式指定。auto_setup(__file__) 會把腳本所在位置加入圖片搜尋路徑。

wait() 會在指定時間內尋找按鈕,找到就回傳座標,再交給 touch() 點擊;逾時找不到會拋出 TargetNotFoundError。相較於固定等待十秒,這種寫法在畫面提早準備好時就能繼續。用法見 Airtest API 文件(在新分頁開啟)。

assert_exists() 負責檢查 Done 是否出現。沒有通過就會讓測試失敗,報告也能顯示失敗的位置;snapshot() 則留下完成時的畫面。檢查函式的行為見官方斷言文件(在新分頁開啟)。

在 IDE 按下執行後,預期會看到按鈕被點擊、狀態變成 Done,並完成圖片檢查。不要只看游標有沒有動,也要確認檢查真的通過。再次執行前記得重開測試視窗,回到相同的起始狀態。

從 PowerShell 執行,再產生 HTML 報告#

保持測試視窗開啟、位於 Ready 狀態。在另一個 PowerShell 切到 airtest-practice,執行:

Terminal window
.\.venv\Scripts\python.exe -m airtest run .\demo.air --device "Windows:///?title_re=^Airtest Demo$" --log .\demo.air\log

這裡用視窗標題的正規表示式連線。^Airtest Demo$ 表示完整標題必須符合 Airtest Demo,執行前請只保留一個同名視窗。IDE 常用的視窗 handle 在關閉、重開後可能改變,不適合直接複製成永久固定值。裝置字串與參數見官方命令列執行說明(在新分頁開啟)。

執行後,再把紀錄轉成報告:

Terminal window
.\.venv\Scripts\python.exe -m airtest report .\demo.air --log_root .\demo.air\log --outfile .\demo.air\log\report.html --lang zh
Invoke-Item .\demo.air\log\report.html

run 的 --log 與 report 的 --log_root 要指向同一個資料夾。報告使用執行時留下的紀錄,必須先跑腳本,才有內容可以產生。

如果要將報告連同截圖交給別人,請用 --export 匯出完整資料夾,避免只傳 HTML 導致圖片或樣式找不到。參數及兩種輸出方式的差異,見官方報告產生說明(在新分頁開啟)。

如果只想直接跑一支 Python 檔案#

普通 .py 也能使用 Airtest,不過要自行指定連線與紀錄位置。例如先做一個只截圖、不點擊的版本,存成 capture_desktop.py:

from pathlib import Path
from airtest.core.api import auto_setup, snapshot
script_dir = Path(__file__).resolve().parent
auto_setup(
__file__,
devices=["Windows:///"],
logdir=str(script_dir / "capture-log"),
)
snapshot(filename="desktop.png", msg="Desktop capture", quality=90)
print(script_dir / "capture-log" / "desktop.png")

執行方式:

Terminal window
.\.venv\Scripts\python.exe .\capture_desktop.py

Windows:/// 連的是整個桌面,圖片預期儲存在腳本旁的 capture-log/desktop.png。這和前面的視窗連線範圍不同,畫面上其他可見視窗也可能被截進去。

.air 範例透過啟動命令提供裝置,這份 .py 則在程式內設定 devices。兩種方式先分開練習,避免同一份程式重複連線,或讓命令列指定的目標被程式內的固定設定蓋過。可參考官方 .air 與 .py 執行差異(在新分頁開啟)。

圖片明明在畫面上,為什麼找不到?#

圖片辨識會受到視窗大小、顯示縮放、主題、反鋸齒和動畫影響。先讓錄製與執行使用相同的視窗尺寸和顯示設定,再檢查截圖有沒有框到會改變的內容,例如倒數秒數、滑鼠懸停效果或角色動畫。

框選範圍要能辨識出目標。只截一小塊純色容易誤判,連大半個視窗一起截又容易受版面變動影響。前面的按鈕可以包含文字和邊框,Done 則保留文字周圍少量背景即可。

需要調整比對門檻時,可以針對單一圖片設定:

button = Template("run_button.png", threshold=0.85)

這是替換原本 button 定義的片段。門檻提高會要求更相似的結果,並不代表辨識一定更準;降低門檻則可能把其他區域當成目標。先檢查截圖與畫面,再調整參數。threshold、record_pos 與 resolution 的定義可查 Template 原始碼與說明(在新分頁開啟)。

若用桌面模式,IDE 裡顯示的模板縮圖也可能被當成目標。執行時收起 IDE、切換成程式碼顯示,或改連特定視窗,會比較容易排除干擾。多螢幕與縮放造成的位置偏移,可再查前面的 Windows 連線文件。

Android 與 Poco:需要時再接著學#

測試 Android 時,先在手機開啟開發人員選項與 USB 偵錯,用 USB 連接電腦,並在手機上允許這台電腦偵錯。接著在 IDE 重新整理 ADB 裝置清單、選擇手機連線。連線方法見官方 Android 教學(在新分頁開啟)。

Android 的裝置字串是 Android:///裝置序號,與 Windows 視窗字串不同;實際序號以 ADB 或 IDE 顯示為準。Windows 練習用的按鈕截圖也不能直接當成手機畫面的模板。

如果之後要練習 Poco,才在同一個虛擬環境安裝:

Terminal window
.\.venv\Scripts\python.exe -m pip install pocoui

套件名稱是 pocoui。這個安裝步驟不會自動替遊戲接上 SDK,還要依 Android 原生介面或遊戲引擎選擇對應的初始化方式。本文的 Windows 圖片練習不需要安裝 Poco。

常見問題#

狀況先檢查的地方
No module named airtest安裝與執行是否使用同一個 Python。用 .venv\Scripts\python.exe -m pip show airtest 核對。
py -3.11 找不到 Python用 py --list 核對版本。若是 uv 管理的 Python,可能需要用清單中的完整標籤,或以該版本 python.exe 的完整路徑取代 py -3.11。
找不到模板圖片圖片是否放在 .air 資料夾內、檔名是否一致,以及是否保留 auto_setup(__file__)。
找不到視窗或找到多個視窗確認標題完全符合,且只有一個 Airtest Demo 視窗;重開視窗後不要沿用舊 handle。
找到圖片但點擊位置不對檢查連的是桌面還是特定視窗,以及多螢幕、縮放與錄製時的尺寸差異。
腳本執行完卻沒有報告先確認產生了 log.txt,再檢查 --log 與 --log_root 是否一致。
第二次測試的結果怪怪的重開測試視窗,讓畫面回到 Ready,再執行同一份腳本。

Airtest 設定檔(settings.py)#

原始設定檔:https://github.com/AirtestProject/Airtest/blob/master/airtest/core/settings.py(在新分頁開啟)

需要調整全域等待時間時,可以在自己的腳本匯入設定類別,不必直接修改安裝目錄裡的檔案:

from airtest.core.settings import Settings as ST
ST.FIND_TIMEOUT = 20

這是全域設定片段,放在初始化之後、操作之前。像前面 wait(button, timeout=10) 已明確指定等待時間,就會使用該次呼叫的十秒設定。

其他參考資料#

下面保留原筆記收錄的連結與名稱,方便對照。部分舊版文件網址已改版,若開不起來,可改看前面各節補上的現行官方文件。

官方文檔:http://airtest.netease.com/docs/cn/index.html(在新分頁開啟)

文檔:https://airtest.netease.com/docs/docs_AirtestIDE-zh_CN/4_run_script/run_script.html(在新分頁開啟)

https://airtest.doc.io.netease.com/IDEdocs/record_script/3_poco_assistant(在新分頁開啟)

https://airtest.doc.io.netease.com/IDEdocs/run_script/1_useCommand_runScript(在新分頁開啟)

https://airtest.doc.io.netease.com/tutorial/11_test_Unity3D_game(在新分頁開啟)

https://airtest.doc.io.netease.com/IDEdocs/device_connection/1_android_phone_connection/#4(在新分頁開啟)

https://airtest.doc.io.netease.com/tutorial/1_quick_start_guide(在新分頁開啟)

https://airtest.doc.io.netease.com/tutorial/1_quick_start_guide/#windows(在新分頁開啟)

Python 開發的按鍵精靈:Airtest Project 筆記
https://aishuafei.com/posts/python開發的按鍵精靈/
作者
愛耍廢
發佈於
2026-04-18
更新於
2026-10-26
許可協議
CC BY-NC-SA 4.0