1. 为什么我建议你用 Playwright 而不是 Selenium 搭 UI 自动化
如果你正在搜 Python Playwright UI 自动化测试环境配置,大概率遇到两种情况:一是 Selenium 跑起来各种等待、驱动版本对不上,二是想给测试脚本接个模型服务做日志分析,结果 Key 散落在好几个文件里。这篇就把这两件事一次讲清楚。
Playwright 是微软出的跨浏览器自动化测试工具,能同时驱动 Chromium、Firefox、WebKit,自带自动等待机制,API 设计比 Selenium 现代不少。它适合谁?适合已经会一点 Python、想快速把 UI 自动化跑起来的人,也适合团队里需要统一管理模型调用凭证的测试同学。
我实测下来,从零到跑通第一个测试脚本,Windows 上大概 20 分钟,其中大部分时间花在下载浏览器内核上。真正卡人的不是安装本身,而是后面接模型服务时 Key 到处复制、环境变量互相覆盖的问题。所以这篇除了讲环境搭建,还会把 TaoToken 统一 Key 接入的部分讲透,让你一套凭证管住所有模型调用。
先说清楚整体路线:装 Python → 建虚拟环境 → 装 Playwright 和 pytest → 下载浏览器内核 → 写第一个测试 → 配 pytest → 接统一 Key → 跑自检。每一步都有可复制的命令,你跟着敲就行。
环境要求不复杂:Windows 10/11 或 macOS 都行,Python 3.9 到 3.11 最稳,内存 8GB 以上,硬盘留 10GB 给浏览器内核。Python 3.12 也能用,但个别依赖包编译时可能报错,新手建议先用 3.11。
这里有个容易忽略的点:Playwright 的浏览器内核和系统里装的 Chrome 是两回事。它默认下载自己的一套内核,放在用户目录下,不污染系统。你也可以让它直接用系统 Chrome,省下载时间,后面会讲怎么配。
2. Python 与 Playwright 安装踩坑实录:pip 命令与浏览器驱动配置
这一节把安装过程拆细,每一步都给你能直接复制的命令。先说 Python 版本选择,再讲虚拟环境,最后是浏览器内核下载。
Python 版本我建议 3.11。3.9 太老,有些新库不支持;3.12 太新,部分依赖还没出预编译包,pip 装的时候会现场编译,容易失败。装的时候记得勾选 "Add Python to PATH",不然命令行里敲 python 找不到。
验证 Python 装好没有:
python --version pip --version两条都能输出版本号就对了。如果 pip 报错,用python -m ensurepip --upgrade修一下。
接下来建项目目录和虚拟环境。虚拟环境的好处是依赖隔离,不会和你系统里其他 Python 项目打架:
mkdir auto_ui cd auto_ui python -m venv venvWindows 激活:
.\venv\Scripts\activatemacOS 或 Linux:
source venv/bin/activate激活成功后命令行前面会出现(venv)。如果 Windows 报执行策略错误,用这行解决:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser然后装 Playwright 和 pytest 相关包:
pip install playwright pytest pytest-playwright如果你还要做报告和配置管理,一起装上:
pip install pytest-html allure-pytest PyYAML python-dotenv装完写个 requirements.txt 锁版本,方便团队复现:
playwright==1.58.0 pytest==8.0.0 pytest-playwright==0.4.4 pytest-html==4.1.1 PyYAML==6.0.1 python-dotenv==1.0.1以后换机器直接pip install -r requirements.txt。
现在是关键一步,下载浏览器内核:
python -m playwright install chromium只要 Chromium 的话这条就够。要全部浏览器:
python -m playwright install下载可能要 5 到 15 分钟,取决于网络。如果卡住不动,先确认网络通畅,再重试。下载失败可以清掉缓存重来:
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\ms-playwright" python -m playwright install chromium如果你系统里已经有 Chrome,可以跳过下载,直接在代码里指定用系统 Chrome。在 conftest.py 里加channel='chrome'就行,后面配置章节会给完整片段。
验证安装是否成功:
python -m playwright --version再跑一段自检代码,确认浏览器能启动:
python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); b = p.chromium.launch(); print('Chromium OK'); b.close(); p.stop()"输出Chromium OK就说明环境通了。这一步很关键,很多人后面测试跑不起来,其实是内核没装好。
3. 可复制的 pytest 配置与 TaoToken 统一 Key 接入片段
环境装好后,先别急着写测试,把配置结构搭好,后面维护省心。这一节给你完整的目录结构、pytest.ini、conftest.py,以及 TaoToken 统一 Key 的接入配置。
目录结构建议这样:
auto_ui/ ├── config/ │ ├── __init__.py │ ├── settings.py │ └── config.yaml ├── pages/ │ ├── __init__.py │ └── base_page.py ├── tests/ │ ├── __init__.py │ └── test_smoke.py ├── utils/ │ ├── __init__.py │ └── ai_logger.py ├── conftest.py ├── pytest.ini ├── .env └── requirements.txtpytest.ini 配置:
[pytest] testpaths = tests python_files = test_*.py python_classes = Test* python_functions = test_* addopts = -v --tb=short --strict-markers --html=reports/report.html --self-contained-html markers = ui: UI自动化测试 smoke: 冒烟测试 regression: 回归测试conftest.py 里配浏览器启动参数和页面 fixture:
import pytest from config.settings import HEADLESS, TIMEOUT, SLOW_MO @pytest.fixture(scope="session") def browser_type_launch_args(browser_type_launch_args): return { **browser_type_launch_args, "headless": HEADLESS, "slow_mo": SLOW_MO, "args": ["--start-maximized"], } @pytest.fixture(scope="function") def browser_context(browser): context = browser.new_context(no_viewport=True) context.set_default_timeout(TIMEOUT) yield context context.close() @pytest.fixture(scope="function") def page(browser_context): page = browser_context.new_page() page.set_default_timeout(TIMEOUT) yield page page.close()config.yaml 放业务配置:
base_url: "https://example.com" timeout: 30000 headless: false slow_mo: 100 browser: "chromium"settings.py 读配置:
import os import yaml from pathlib import Path BASE_DIR = Path(__file__).parent.parent CONFIG_FILE = BASE_DIR / "config" / "config.yaml" with open(CONFIG_FILE, "r", encoding="utf-8") as f: _config = yaml.safe_load(f) BASE_URL = _config.get("base_url") TIMEOUT = _config.get("timeout", 30000) HEADLESS = _config.get("headless", False) SLOW_MO = _config.get("slow_mo", 0)现在讲重点,TaoToken 统一 Key 接入。测试脚本里如果要用模型做日志分析、用例生成,Key 管理是个麻烦事。TaoToken 提供统一的 API 通道,一个 Key 管住多个模型服务,Base URL 固定,模型 ID 按需切换。
在 .env 里配置(记得加进 .gitignore):
TAOTOKEN_API_KEY=你的Key TAOTOKEN_BASE_URL=https://taotoken.net/api TAOTOKEN_MODEL_ID=claude-sonnet-4-5如果你用 OpenAI 兼容的 SDK,这样初始化:
import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.getenv("TAOTOKEN_API_KEY"), base_url=os.getenv("TAOTOKEN_BASE_URL"), ) def analyze_error(error_info: str) -> str: response = client.chat.completions.create( model=os.getenv("TAOTOKEN_MODEL_ID"), messages=[ {"role": "user", "content": f"分析这个测试错误并给出修复建议:\n{error_info}"} ], timeout=30, ) return response.choices[0].message.content三件套记牢:Base URL 是https://taotoken.net/api,Key 从控制台拿,Model ID 按你用的模型填。换模型只改 Model ID,Key 和 Base URL 不动,这就是统一通道的好处。
如果你用 Claude Code 做编码辅助,配置方式类似,Base URL 填同一个,Key 用同一个。Cline 或 MCP 场景下,也是这三件套,别把 Base URL 写成别的地址。
4. 跑通第一个测试并验证请求成功结果
配置齐了,写第一个测试脚本验证整条链路。新建 tests/test_smoke.py:
import pytest from config.settings import BASE_URL @pytest.mark.smoke def test_homepage_title(page): page.goto(BASE_URL) title = page.title() assert title, "页面标题不应为空" print(f"页面标题: {title}") @pytest.mark.smoke def test_page_load_state(page): page.goto(BASE_URL) page.wait_for_load_state("networkidle") assert page.url.startswith("http")运行:
pytest tests/ -v正常输出类似:
tests/test_smoke.py::test_homepage_title PASSED tests/test_smoke.py::test_page_load_state PASSED两条都 PASSED,说明 Playwright 环境通了。如果失败,看报错信息,常见的是 base_url 填错或网络不通。
接着验证 TaoToken 请求。写个独立脚本 test_ai.py:
import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.getenv("TAOTOKEN_API_KEY"), base_url=os.getenv("TAOTOKEN_BASE_URL"), ) resp = client.chat.completions.create( model=os.getenv("TAOTOKEN_MODEL_ID"), messages=[{"role": "user", "content": "回复两个字:通了"}], timeout=30, ) print(resp.choices[0].message.content)运行python test_ai.py,输出「通了」就说明 Key 和通道都正常。这一步验证的是模型服务链路,和 Playwright 是独立的,分开验证好定位问题。
把两者结合,在测试失败时自动调模型分析:
import pytest from utils.ai_logger import analyze_error @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() if report.when == "call" and report.failed: error_info = str(report.longrepr) suggestion = analyze_error(error_info) print(f"\n模型分析建议:\n{suggestion}")这样测试挂了会自动打印修复建议,省得你手动去翻日志。
跑完整套:
pytest tests/ -v --html=reports/report.html --self-contained-html报告生成在 reports/report.html,浏览器打开就能看。到这里,环境自检、测试运行、模型调用三条链路都验证过了。
5. 本篇常见报错排查:401、local proxy failed、reading choices
这一节把高频报错列出来,对照着查。每个都给你原因和解决动作。
401 Unauthorized。这个基本是 Key 问题。先确认 .env 里 TAOTOKEN_API_KEY 没写错,没有多余空格。再确认 base_url 是https://taotoken.net/api,别漏了 /api。如果 Key 是从控制台复制的,注意别把前后引号也复制进去。验证方法:
python -c "import os; from dotenv import load_dotenv; load_dotenv(); print(os.getenv('TAOTOKEN_API_KEY')[:8])"能打印出前 8 位就说明读到了。
local proxy failed。这个报错通常是环境变量里有残留的代理设置,或者网络配置冲突。检查系统环境变量里有没有 HTTP_PROXY、HTTPS_PROXY 指向一个不可用的地址。清掉再试:
unset HTTP_PROXY unset HTTPS_PROXYWindows 上用Remove-Item Env:HTTP_PROXY。如果你确实需要走网络配置,确保地址是通的,别指向一个已经关掉的端口。
reading choices 报错,完整信息一般是AttributeError: 'NoneType' object has no attribute 'choices'或者响应结构里没有 choices 字段。这说明请求发出去了但返回结构不对。常见原因:Model ID 填错,服务端返回了错误信息而不是正常响应。先打印完整响应看看:
resp = client.chat.completions.create(...) print(resp)如果 resp 里是错误信息,对照改 Model ID。另一个原因是 base_url 少了 /v1 或多了 /v1,TaoToken 的地址是https://taotoken.net/api,不要自己加 /v1。
OAuth 相关报错。如果你用 Claude Code 或类似工具,报 OAuth 失败,通常是认证方式没配对。这类工具要么用 API Key,要么用 OAuth,别混用。用 API Key 方式时,Base URL 填https://taotoken.net/api,Key 填控制台拿的,Model ID 填对应模型。三件套齐全就不会报 OAuth。
浏览器启动失败。报错里带Executable doesn't exist,说明内核没装好。重跑python -m playwright install chromium。如果报缺依赖,Linux 上跑python -m playwright install-deps,Windows 上装一下 Visual C++ Redistributable。
元素找不到。报TimeoutError,先加等待:
page.wait_for_selector(".element", timeout=5000)或者等页面加载完:
page.wait_for_load_state("networkidle")截图保存失败。确认目录存在:
import os os.makedirs("screenshots", exist_ok=True) page.screenshot(path="screenshots/error.png")排查顺序建议:先确认 Playwright 自检通过,再确认模型请求通过,最后跑组合测试。分开验证,问题定位快很多。
6. 把统一 Key 用起来:测试场景里的模型调用与后续扩展
环境跑通只是开始,真正省时间的是把模型调用嵌进测试流程。这一节讲几个实用场景,以及怎么用统一 Key 管理这些调用。
场景一,失败日志自动分析。前面给过 hook 示例,测试挂了自动调模型分析报错,输出修复建议。这样你早上来看报告,直接看到建议,不用逐条翻堆栈。
场景二,用例生成辅助。把页面结构描述给模型,让它生成 Page Object 和测试用例草稿:
prompt = """ 页面包含:用户名输入框、密码输入框、登录按钮、记住我复选框。 请生成 Page Object 类结构和三条测试用例:正常登录、错误密码、空用户名。 """生成的草稿你再改,比从零写快。
场景三,选择器修复建议。页面改版后选择器失效,把旧选择器和新页面 HTML 片段给模型,让它给新选择器。
这些场景都调同一个 Key,Base URL 和 Model ID 在 .env 里统一配。团队协作时,每个人本地 .env 填自己的 Key,代码里不硬编码,提交时不带 .env。CI 环境里用环境变量注入。
如果你要长期跑编码和 Agent 任务,可以考虑 Coding Plan,额度更稳。验证模型是否可用,用模型对话页面快速测一下。接入文档里有各语言的示例,照着改就行。
后续扩展方向:加 Allure 报告、加并行执行pytest -n auto、加 CI 集成。这些都在现有结构上加,不用重构。
最后给个实用技巧:把环境自检写成一个脚本,每次换机器先跑一遍,确认 Python、Playwright、模型通道都通,再开始写测试。这样能省掉大量「为什么跑不起来」的排查时间。
python -m playwright --version python -c "from playwright.sync_api import sync_playwright; p=sync_playwright().start(); b=p.chromium.launch(); print('browser ok'); b.close(); p.stop()" python test_ai.py三条都过,环境就没问题。