想讓電腦自己找到畫面上的按鈕、點下去,再接著做下一個動作,可以試試 Airtest。它用圖片辨識尋找操作目標,搭配 AirtestIDE 產生 Python 腳本,操作方式有點像按鍵精靈。
Airtest Project 是網易研發並開源的自動化測試框架,著重在腳本錄製與遊戲測試。它希望降低腳本撰寫與維護的門檻,讓不熟悉程式的人也能透過點擊、拖曳等操作產生腳本;另一個方向則是支援不同遊戲引擎與平台。這些是專案的目標,實際使用仍要確認裝置、畫面和操作方式是否適用。Airtest 官方介紹(在新分頁開啟)有列出框架的功能與支援平台。
錄製可以省下輸入基本指令的時間,等待畫面、判斷成功或失敗、處理例外等流程,還是需要自己補。下面以 Windows 為主,做一個「找到按鈕 → 點擊 → 確認結果」的小練習。
Airtest、AirtestIDE 和 Poco 有什麼差別?
這幾個名稱經常一起出現,安裝前先分清楚比較不會混淆。
| 名稱 | 負責的工作 |
|---|---|
| Airtest | Python 自動化框架,用圖片辨識尋找畫面上的目標,再執行點擊、拖曳等動作。 |
| 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:
New-Item -ItemType Directory -Path airtest-practiceSet-Location airtest-practicepy -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 執行:
.\.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.pngrun_button.png 和 done_label.png 要從你自己的測試視窗擷取,無法只靠複製下面的 Python 程式產生。
- 在 Airtest 輔助面板選擇
touch,框選Run test按鈕,讓 IDE 產生點擊語句與圖片。將圖片另存或重新命名為run_button.png;如果改了檔名,也要同步修改程式內的引用。 - 手動點一下按鈕,讓畫面顯示
Done。 - 選擇
assert_exists,框選Done文字,儲存為done_label.png,作為執行後的檢查目標。 - 關閉並重新開啟測試視窗,讓狀態回到
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,執行:
.\.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 在關閉、重開後可能改變,不適合直接複製成永久固定值。裝置字串與參數見官方命令列執行說明(在新分頁開啟)。
執行後,再把紀錄轉成報告:
.\.venv\Scripts\python.exe -m airtest report .\demo.air --log_root .\demo.air\log --outfile .\demo.air\log\report.html --lang zhInvoke-Item .\demo.air\log\report.htmlrun 的 --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().parentauto_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")執行方式:
.\.venv\Scripts\python.exe .\capture_desktop.pyWindows:/// 連的是整個桌面,圖片預期儲存在腳本旁的 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,才在同一個虛擬環境安裝:
.\.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(在新分頁開啟)
