AI-Stack Selenium 自動化測試 — 安裝與測試指南
版本:v1 (2026-06-25) · repo
gitlab.infinitix.co:jefflinux/aistack-testautomation對象:在「已安裝好的 AI-Stack」上,用 Selenium 做平台設定 + fixture 備齊 + 全覆蓋功能測試,並可串接 CI/CD。 範圍邊界:L0 安裝 + L1 平台設定(安裝後 5 步)由安裝器(ansible/install-tui)備好,不在本套件範圍;本套件從「裝好且設定好的站」開始 → check-assert L1 → 補 L2 test fixture → 功能測試。
1. 總覽
| 項目 | 值 |
|---|---|
| 套件 | jefflinux/aistack-testautomation(deterministic Selenium,純 UI 驅動) |
| 規模 | 69 test 檔 / 53 page object / 999 test collected(canonical;pytest tests/ == pytest 無 path 一致)。 |
| 被測站 | AI-Stack v4.27.2-HA(web tier = docker-compose ai-stack-web,:8080;workload = k8s) |
| Runner | VM80 Linux(google-chrome 149 + venv),禁本機 Windows 跑(flaky) |
| 紀律 | 操控 AIS 只走 Selenium/UI;k8s/API/DB 一律 read-only |
分層模型(artifact manifest):
L0 平台 = k8s + AI-Stack 已裝好 ← 安裝器(ansible/install-tui),套件只 check
L1 平台設定 = 超管/License/CloudProvider+ ← 安裝器「安裝後系統設定 5 步」/install-tui auto
skyport/CloudRegion/Harbor 套件只 check-assert(2026-06-26 修正:非 Selenium)
L2 應用 fixture = golden01/測試專案/sel-* 規格 ← preflight ensure() 自動補(Selenium 真責任)
樣板/LDAP/MailHog/容器/cupy
功能測試 = 454+ QA case(opui/portal/...) ← pytest marker 分流跑
hw 物理硬體 = 單卡限制(ETHPC 多 worker≥2GPU) ← pending-hardware,標 reason 不偽造
2. 安裝(套件本身)
跑測試的機器 = VM80(已備好,通常不用重裝);以下為從零建環境的步驟。
2.1 前置
- Python 3.10+
- Google Chrome(Selenium Manager 自動抓對應 chromedriver)
- 能連到被測站(VM80 上 =
https://10.20.12.80:8080或https://localhost:8080,self-signed cert)
2.2 取得 + 建環境(VM80)
ssh 80
cd ~ && git clone git@gitlab.infinitix.co:jefflinux/aistack-testautomation.git
cd aistack-testautomation
python3 -m venv .venv
./.venv/bin/pip install -r requirements.txt
deps pin(
requirements.txt,權威):selenium==4.27.1/pytest==8.3.4/pytest-html==4.1.1。 ⚠️ VM80 已有專屬.venv;勿污染 ixCSP 的.venv-smoke。(註:現有 VM80 venv 的 runtime 版本可能高於 pin,以 requirements.txt 為安裝基準。)
2.3 設定(config.py / 環境變數)
| 變數 | 預設 | 說明 |
|---|---|---|
BASE_URL |
https://10.20.12.80:8080 |
被測站;CI 參數化指向目標 AIS |
SUPERUSER / SUPERUSER_PW |
superuser / P@ssw0rd123 |
OP UI 管理者 |
PORTAL_USER / PORTAL_USER_PW |
golden01 / P@ssw0rd123 |
User Portal(一般登入) |
LDAP_USER / LDAP_USER_PW |
testuser01 / password1 |
User Portal(LDAP) |
DEFAULT_TIMEOUT |
10 |
元素等待秒數 |
3. Artifact / Fixture 安裝步驟與內容
「artifact」= 跑測試前該站必須具備的狀態(設定 / fixture)。原則:在就複用、缺就補到好、唯一非綠=實體硬體缺。落地 =
preflight.pyregistry(manifest as data)+conftest.py的ensure(artifact)fixture(依deps拓樸排序,check→缺則 provision→recheck)。
3.1 preflight 狀態檢視(read-only)
ssh 80 'cd ~/aistack-testautomation && PREFLIGHT_ON_VM80=1 ./.venv/bin/python -c "import preflight; preflight.check_all()"'
# 每個 artifact 印 ok / MISSING / ?(needs WebTerminal);read-only,不改站
3.2 目前 preflight.py ARTIFACTS(實況,17 keys — 與 source 對齊)
以下是
preflight.py的ARTIFACTSregistry 實際 keys 與 provisioner 狀態(Codex 對齊 source 查核 2026-06-25)。✅自動=prov_ 已實作;⏳TODO=prov_ raise ProvisionTODO;手動=prov=None(缺則 RuntimeError,須手動 OpUI)。
| artifact key | 層 | 內容 | provision | 狀態 |
|---|---|---|---|---|
platform_up |
L0 | AIS web 200 + k8s nodes Ready | prov_installer(raise ProvisionTODO:L0 外部安裝,套件只 check) |
check-only(範圍外) |
superuser |
L1 | OP UI 超管可登入 | prov_superuser |
⏳ TODO(待建 page object;僅 fresh 站可驗) |
cloudregion |
L1 | sys_cloudregioninfo 有 region(check 僅查存在,未驗 skyport/:443) |
prov=None | 手動 OpUI |
gpu_node |
L1/HW | GPU worker node Ready | prov=None | 手動 |
mls_spec_1gpu |
L1 | MLS 1-GPU 規格存在 | prov=None | 手動 OpUI |
mls_template |
L1 | MLS 樣板存在 | prov=None | 手動 OpUI |
ixgpu_webhook |
L1 | ixgpu-scheduler endpoint up | prov=None | 手動 |
golden01 |
L2 | Portal 用戶 golden01 | prov_golden01(seed_golden01.py 冪等) |
✅ 自動 |
project_golden |
L2 | 專案 golden-gpu-demo | prov_project |
⏳ TODO |
ldap_server |
L2 | osixia/openldap 容器 | prov_ldap(docker run 冪等) |
✅ 自動 |
mailhog_sink |
L2 | MailHog SMTP sink | prov_mailhog(docker run 冪等) |
✅ 自動 |
rcs_spec_hermes |
L2 | GPU-off hermes-spec | prov_rcs_spec_hermes(create_hermes_spec.py 冪等) |
✅ 自動 |
hermes_image |
L2 | Harbor hermes-agent:official-0.15.2 | prov_hermes_image |
⏳ TODO |
container_seltestmls01 / container_seltfgpu01 / container_selgpu01 |
L2 | MLS 容器 1/1 Running(seltfgpu01=canonical tensorflow+WebTerminal;另二為 back-compat,多讀 MISSING) | prov_container(mls-creator 精靈;需 free GPU) |
✅ 自動(gated on free GPU) |
cupy_in_container |
L2 | 容器內裝 cupy(GPU 負載) | prov_cupy |
⏳ TODO(需容器 WT_URL) |
3.2b L1/L2 責任分工(2026-06-26 修正:L1 是安裝器的,不是 Selenium)
🚨 修正:先前把 L1 平台設定列成「Selenium 待建 provisioner」是 scope 錯。官方 ansible installer「安裝後系統設定 5 步」+ install-tui auto 就是 L1 owner;Selenium 不重做,只 check-assert。
L1 = 安裝器責任(ansible 安裝後 5 步 / install-tui auto)— Selenium 只 check-assert,不 provision:
| L1 項目 | 安裝器來源 |
|---|---|
| 超管建立 | ansible 安裝後 step1(/operation/super-admin-creating)/ install-tui auto |
| License 上傳 | ansible 安裝後 step2 |
CloudProvider + skyport key + :6443 測試 |
ansible 安裝後 step3(skyport key 來自 cluster-21) |
| CloudRegion + serviceTypes | ansible 安裝後 step4 |
| Harbor Registry | ansible 安裝後 step5 + cluster-10 |
| gpu_node / ixgpu_webhook | ansible cluster-13/14/15/20/21/22(infra) |
L2 = Selenium/preflight 真要 provision 的 test fixture:
| L2 fixture | 狀態 | 可在 VM80 開發? |
|---|---|---|
| golden01 用戶 / LDAP / MailHog / rcs_spec_hermes | ✅ 已自動 | — |
project_golden(測試專案) |
⏳ TODO | ✅ |
| 測試專用 spec/template(sel-mls-1gpu/frac4、tensorflow+WebTerminal) | ⏳ 待建(有 script 雛形) | ✅ |
| auto-approve(測試前置開啟) | ⏳ 待建 | ✅ |
| 測試容器 / cupy | container ✅自動 / cupy ⏳TODO | ✅ |
| hermes_image / harbor 測試鏡像 | ⏳(infra docker push,非 UI) | ✅ |
所以 Selenium 的 P0 真正範圍只有上面 L2 那幾項(比原以為小很多);L1 缺 = 安裝器 5 步沒做完,走安裝器補,不是 Selenium 的事。
3.3 ensure 用法(測試內自動備齊前置)
# conftest 提供 ensure fixture;測試宣告依賴 → 自動 check→provision→recheck
def test_xxx(ensure, ...):
ensure("container_seltfgpu01") # 解 deps: project_golden→mls_template→spec→gpu_node→container
- 已驗:
test_portal_interface9 passed,log[ok] superuser/[ok] golden01(ensure 真跑、解依賴、session-cached)。 - Harbor 鏡像準備範例(已驗 pattern):
ssh 80 'sudo docker login 10.20.12.80:18080 -u admin -p Harbor12345 && \
sudo docker pull <img> && sudo docker tag <img> 10.20.12.80:18080/library/<name>:<tag> && \
sudo docker push 10.20.12.80:18080/library/<name>:<tag>'
# MLS/RCS 鏡像 picker 直讀 Harbor library/*(免 import-tool)
4. 測試執行步驟
4.1 Marker 分流(CI stage 對應)
pytest.ini 註冊 marker(實況 14 個):
smoke login hermes opui portal v428gated batch3 gpu_load container_create rcs_deploy ethpc_cluster gpu_frac_verify gpu_shared_create gpu_mode_switch。
| marker | 內容 | CI stage |
|---|---|---|
smoke |
最小 gate(超管+golden01 登入) | Stage 1(每 commit,<3min) |
login |
登入流程(op + portal + LDAP) | Stage 1 |
opui / portal |
OP UI / User Portal 功能(非破壞) | Stage 2(每 commit,~30min) |
batch3 |
容器詳情功能深測(F-038~F-056) | Stage 2 |
hermes |
hermes-webui app 測試 | Stage 2/3 |
container_create / rcs_deploy / gpu_load / gpu_frac_verify / gpu_shared_create / gpu_mode_switch / ethpc_cluster |
opt-in DESTRUCTIVE(建容器/部署/GPU 負載/模式切換) | Stage 3(nightly) |
v428gated |
v4.28 限定 feature(4.27.2-HA 跳過) | 版本相關 |
4.2 單檔 / 子集(前景,短)
ssh 80 'cd ~/aistack-testautomation && git pull -q && \
BASE_URL=https://localhost:8080 ./.venv/bin/python -m pytest tests/<file>.py -o addopts="" -q'
4.3 Smoke gate
ssh 80 'cd ~/aistack-testautomation && BASE_URL=https://localhost:8080 ./.venv/bin/python -m pytest -m smoke -o addopts="" -q'
# 期望 1 passed,exit 0
4.4 全 suite(chunked,避 Chrome ~350-launch 天花板)
ssh 80 'cd ~/aistack-testautomation && bash scripts/run_full_suite_chunked.sh'
# file-by-file fresh process + 每檔 junit → scripts/aggregate_junit.py 聚合
-o addopts=""清掉 pytest.ini 預設的--junitxml=results.xml --html=report.html,避免並行搶檔。
4.5 收尾 cleanup(mutation 測必跑,四件套)
1. 刪測試容器(走 UI / kubectl delete pod)
2. deadletter = 0(SELECT count act_ru_deadletter_job)
3. ACL state reset(test 容器 → OWNER_ONLY)
4. hash_mapping 清(無孤兒)
5. CI/CD pipeline(5 stage)
Stage 0 PROVISION (慢/nightly) : 安裝器裝 L0+L1(ansible/install-tui)→ Selenium check-assert L1 + 補 L2 fixture
Stage 1 SMOKE (每 commit) : -m smoke(登入 gate),紅即 fail
Stage 2 FUNCTIONAL-READONLY : -m "opui or portal"(非破壞)+ chunked
Stage 3 FUNCTIONAL-MUTATION : opt-in destructive + cleanup 四件套(nightly)
Stage 4 REPORT + GATE : aggregate_junit → 綠判準
綠判準(accounted-for,非 100% green):0 fail + 每個 skip 都有分類 reason(pending-hardware / pending-fixture / opt-in-not-selected / v428gated),無 unexplained skip。
6. 已知限制 / 邊界
- L0 安裝不在範圍:站須外部先裝好,套件只 check
platform_up。 - 超管 / License provisioner 僅 fresh 站可驗:已設站該頁 redirect。
- 物理硬體:單卡(1×RTX-3090)→ ETHPC 多 worker、多 GPU 併發 =
pending-hardware(標 reason,不偽造、不算 fail)。 - ~177 case 仍 skeleton:W2 容器 / W3 MailHog 發信 e2e / W4 mutation / ETHPC 待填。
7. 參考
- plan:
selenium-coldstart-cicd-pipeline-plan-v1-20260624.md(冷啟動 pipeline 完整化) - manifest:
selenium-artifact-manifest-draft-20260623.md(L0-L4 artifact 定義) - 程式:
preflight.py(ensure 拓樸)、conftest.py(ensure fixture)、scripts/run_full_suite_chunked.sh+aggregate_junit.py(CI runner) - skill:
selenium-vm80-runner(執行紀律)、aistack-postinstall-ui-config(L1 5 件套)、aistack-fresh-site-checklist、aistack-qa-v427(454 case 權威步驟) - repo 內:
README.md/COVERAGE-MATRIX.md/PORT-REGISTRY.md/SELENIUM-COVERAGE-GAP-PLAN-20260622.md