说实话,Web自动化测试这个方向,网上教程多到能把你淹没,但真正能拿到工位上跑、能扛住业务变化、能应付面试官追问的方案,其实少之又少。我最近复盘了自己从Selenium转到Playwright,再到基于LangChain做测试脚本生成的整个过程,想把踩过的坑和沉淀下来的方法一次说透。这篇文章不教你点录制回放,而是回答三个更关键的问题:你的Web项目为什么需要自动化测试,框架到底怎么选才不返工,以及从一条用例到一套稳定体系,中间到底要趟过哪些坑。适合刚入门想搭框架的测试同学,也适合做了好几年手工测试、想往测试开发方向转的朋友。
1. 先想清楚再动手:Web自动化测试的本质与选型
1.1 自动化测试解决的不是“手动点得慢”的问题
很多团队一上来就说“我们测试太累了,天天回归要两小时,上自动化吧”。但如果你只是为了省时间,往往会做出一个人工点击脚本化,最后变成“录屏回放机器”的东西,维护成本高到崩溃。
我个人的理解是,Web自动化测试真正的价值在三个方面:回归效率、质量门禁、可重复性。
回归效率最好懂,发版前把核心链路跑一遍,20分钟完事,不依赖人工状态。质量门禁是更高级的用法,把冒烟用例挂到CI流水线里,全部变绿才允许继续发布,这是自动化最有说服力的价值,它变成了发布流程的一部分,而不是发布完再补测。可重复性也常被忽略,人点久了会疲劳、会漏字段,脚本不会,同样的步骤每次执行结果都一样,这本身就是一种质量保障。
另外必须聊聊测试金字塔。我见过不少团队把八成用例全堆在UI层,最后结果就是三层里最脆的那一层承担了最多的回归任务,一跑就红,红了没人改,改不过来就放弃。正确的比例应该是:单元测试最多,接口测试适量,UI测试少而精。UI自动化更适合覆盖核心链路和高频回归场景,比如登录、下单、支付、权限,别指望它把所有边界值都测一遍。
所以第一步不是选框架,是把“哪些用例值得自动化”和“哪些场景适合同步进CI”想清楚。这个动作越早做,后面返工越少。
1.2 选型:Selenium、Playwright、Cypress怎么选
工具选型是每次聊自动化必被问到的问题。我三个都用过,简单说下感受。
Selenium是老牌选手,基于WebDriver协议,生态成熟,支持的语言最多,Java、Python、C#、Ruby都能写。传统企业里遗留系统多、老浏览器(比如IE内核)多的时候,Selenium几乎是唯一选择。但它的缺点也很明显,等待策略要自己写,多标签页和下载文件要配置一堆,调试体验一般,运行不稳定的时候,你得自己处理很多事情。
Playwright是微软家的,这几年大火不是没道理。它内置自动等待,定位器设计得更贴近用户,天然支持多浏览器、多标签页、移动端模拟,还能拦截网络请求、录Trace、直接截图录视频。我目前的主力框架就是pytest加Playwright,下面整个实战流程都会按这个来。
Cypress是前端工程师比较喜欢的那类工具,上手快,调试面板漂亮,但它的模型偏向纯前端单页应用,多标签页和跨域场景处理比较弱,适合前端团队自己写组件测试和少量端到端测试。
这里放一张选型对比表,方便直观参考:
| 维度 | Selenium | Playwright | Cypress |
|---|---|---|---|
| 协议基础 | WebDriver | CDP协议 | 内置代理 |
| 等待策略 | 需显式等待 | 自动等待 | 自动重试 |
| 语言支持 | Java/Python/JS等 | Java/Python/JS等 | 仅JS/TS |
| 多标签页 | 麻烦 | 原生支持 | 受限 |
| 网络拦截 | 需借助代理 | 原生支持 | 原生支持 |
| 调试体验 | 一般 | Trace/录像/截图强 | 极强 |
| 适合场景 | 遗留系统 | 现代Web快速迭代 | 前端团队 |
我的建议是:老项目、老浏览器多,继续用Selenium;新项目、业务变化快,直接上Playwright;如果是给公司搭长期平台,pytest加Playwright这套组合在灵活性和维护性上都更平衡。
2. 从零搭建pytest+Playwright工程:环境、目录、第一个用例
2.1 环境准备和目录结构
先说环境。如果你用的是Python 3.9以上版本,建议先建一个虚拟环境,避免污染系统Python。
python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install pytest pytest-playwright playwright playwright install chromiumplaywright install chromium这步会下载浏览器内核,如果本地网络慢,可以考虑只装chromium,后面调试、CI都用它,等有需要再装firefox和webkit。
工程目录不要随便堆文件,我建议按下面这个结构来:
project/ ├── config/ │ └── settings.yaml ├── page_objects/ │ ├── __init__.py │ ├── base_page.py │ ├── login_page.py │ └── cart_page.py ├── test_cases/ │ ├── conftest.py │ └── test_order_flow.py ├── reports/ ├── data/ │ └── accounts.csvconftest.py里放pytest的fixture,最重要的就是浏览器和页面这两个fixture。
import pytest from playwright.sync_api import sync_playwright @pytest.fixture(scope="session") def browser(): with sync_playwright() as p: b = p.chromium.launch(headless=False) yield b b.close() @pytest.fixture() def page(browser): context = browser.new_context() pg = context.new_page() yield pg context.close()这里的context是一个浏览器上下文,你可以把它理解成一个独立的“无痕窗口”。每个用例创建新的context,登录态、Cookie互相隔离,这样用例之间不会串数据。这是我特别强调的一点,别省这一步,一旦用例多了,上下文隔离缺失会让失败率飙升。
本地调试时,headless=False可以看到浏览器操作过程;CI里跑,改成headless=True,稳定性更好。
2.2 第一个用例:登录、搜索、加购一条龙
下面这条用例覆盖了登录、搜索、加购三个动作,它已经能说明Playwright的定位器风格和断言方式:
from playwright.sync_api import expect def test_login_search_add_to_cart(page): page.goto("https://example.com/login") page.get_by_placeholder("用户名").fill("tester") page.get_by_placeholder("密码").fill("123456") page.get_by_role("button", name="登录").click() page.get_by_placeholder("搜索商品").fill("无线耳机") page.get_by_role("button", name="搜索").click() page.get_by_role("link", name="无线耳机 Pro").click() page.get_by_role("button", name="加入购物车").click() expect(page.locator(".cart-count")).to_have_text("1")运行命令很简单:
pytest test_cases/test_order_flow.py -v如果失败了,pytest-playwright默认会把失败截屏和页面快照保存到test-results目录,打开快照你能直接看到失败瞬间的页面长什么样。
这条用例虽然短,但有一个非常重要的设计:定位器优先用get_by_role、get_by_placeholder这类语义化定位,而不是XPath长路径。原因后面单独讲。断言用的是expect,Playwright会自动等待条件满足,默认超时30秒,这就避免了手工写sleep带来的不确定性问题。
2.3 数据不写死:配置文件与环境变量
很多新手脚本喜欢把URL、用户名、密码直接写在用例里,看着方便,实际一换环境就废了。今天在测试环境跑通了,明天想切到预发布环境,得改半小时。
我建议用YAML配置加环境变量双保险。配置文件里保存非敏感数据和URL,账号密码放在环境变量或CI的凭据管理里。
# config/settings.py import os import yaml def load_config(): env = os.getenv("TEST_ENV", "dev") with open(f"config/{env}.yaml", "r", encoding="utf-8") as f: return yaml.safe_load(f) config = load_config()在conftest.py里通过pytest的--env参数来动态选择环境,而不是每次手动切文件。这样同一个用例,只需要传不同的参数,就能在dev、test、staging三套环境上跑同样的回归。
密码这类敏感信息,千万不要提交到Git仓库。至少也要用环境变量读取,然后配合CI平台的密钥管理功能,否则出了安全事故第一个追责的就是你。
3. 元素定位与等待策略:从“能跑”到“稳定跑”
3.1 定位器选择优先级
先说一个生活化类比。你要在一间教室里找一个穿红衣服戴眼镜的人,最快的方法是问“谁是穿红衣服戴眼镜的人”,而不是按“从门口数第三排第五个座位”去找。座位会变,特征不会。定位器也是这个道理。
Playwright定位器的优先级我建议是:
get_by_role:按角色和名称定位,比如按钮、链接、标题。get_by_label:按表单标签定位。get_by_placeholder:按输入框占位提示定位。get_by_text:按可见文本定位。get_by_alt_text:针对图片。- CSS选择器:适合很稳定的页面结构。
- XPath:作为最后手段,尤其是复杂的页面结构。
我这里特意把XPath排到最后,不是说它没用,而是很多新手一遇到问题就开始复制浏览器生成的绝对路径,类似/html/body/div[2]/div/div[3]/form/input[1]这种,前端稍微改一下结构就全断。用语义化定位器还有个隐藏好处——试运行代码的时候更容易让人看懂,后面AI生成脚本也有更好的基础。
如果前端开发愿意配合,强烈建议在页面关键元素上面统一加>from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By element = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, ".submit-btn")) )
我见过很多Selenium项目用了大量time.sleep(3),这是能用但很蠢的等待方式。固定等待要么不够、要么太多,稍微优化一下,优先等待“业务条件”,比如等待某个提示文字出现、等待某个请求完成、等待某个元素从页面消失。体验就是用例的稳定性和执行速度都显著提升。
3.3 我踩过的三个稳定性大坑
第一个坑是元素被遮挡。页面顶部固定了一个吸顶导航栏,按钮其实在视口外或者被遮住了,Playwright会报“元素不可交互”。解决办法是先用scroll_into_view_if_needed()把元素滚进视野,再点击。
第二个坑是懒加载。电商列表页滚动到底部才加载下一批商品,如果脚本从头到尾不滚动,就会漏掉一部分数据。我写过一个轮询滚动的循环,每次滚到页面底部,直到页面高度不再变化或者出现“加载完成”标识为止。这样虽然看起来笨,但能把数据抓全。
第三个坑是tab切换的监听时机。很多用例需要点击按钮后打开新标签页,新手直接page.expect_page用错地方,就会发现新页面监听不到。正确方法是把监听写在点击之前:
with context.expect_page() as new_page_info: page.get_by_role("button", name="在新窗口打开").click() new_page = new_page_info.value new_page.wait_for_load_state("networkidle")这类稳定性问题其实占用例失败的大头,等跑起来以后你会慢慢积累出一套“稳定清单”,这比写一版脚本重要得多。
4. 页面对象模型与业务层封装:告别脚本堆砌
4.1 PO模式到底在封装什么
页面对象模式,英文叫Page Object Model,简称PO。一句话解释:把页面上“元素在哪”的信息和“对这个元素做什么”的操作,从测试用例中抽出去。
没有PO的用例是什么样?就是之前那种打开页面、找到用户名输入框、填值、找密码、填值、找登录按钮、点击的流水账。如果同一个登录框在20条用例里出现,前端把登录按钮改了个name,20条用例全得改。
有了PO之后,登录的逻辑只存在于LoginPage这个类里,用例只需要调用login_page.login("tester", "123456")。页面结构变了,只改一个类,20条用例全都不用动。
PO还能进一步拆分业务层。比如下单流程里,把“选择地址、选择支付方式、提交订单”这些动作封装成OrderService,用例里直接表达业务意图,而不是操作一堆按钮。
4.2 封装一套登录、商品、购物车页面对象
简单写一个登录页的封装:
class LoginPage: def __init__(self, page): self.page = page def goto(self): self.page.goto("https://example.com/login") def login(self, username, password): self.page.get_by_placeholder("用户名").fill(username) self.page.get_by_placeholder("密码").fill(password) self.page.get_by_role("button", name="登录").click() self.page.wait_for_load_state("networkidle")商品页和购物车页类似,把搜索、点击商品、加入购物车、查看购物车数量都封装成方法。用例就变得很可读:
def test_order_flow(login_state, page): product_page = ProductPage(page) product_page.search("无线耳机") product_page.open_first_product() product_page.add_to_cart() cart_page = CartPage(page) expect(cart_page.cart_total).to_have_text("1")以前是给代码写注释,现在是代码自己会讲故事。
4.3 页面对象适配多业务的技巧
PO封装多了你会发现两个细节问题。
一是页面类里的定位器尽量用property懒加载,不要在__init__里创建一堆locator。这个坑在于如果页面重写了DOM,旧locator可能还在对象上挂着,不会自动更新,看起来是玄学问题。用property,每次访问都会重新查询,更可靠。
二是不要为了PO而PO。如果你的项目只有几条用例、页面非常简单,直接写成脚本反而更快。我见过有人为了模式强行把三个页面封装成八个类,最后自己都找不到逻辑在哪。封装的目标是降低维护成本,如果封装本身成了维护成本,就该做减法。
还有一个小技巧是给文案易变的元素加上正则匹配。比如按钮文案在“加入购物车”和“加购”之间变过,定位器可以写成name=re.compile("加入购物车|加购"),一次改动,长期稳定。
5. 数据驱动、接口联动与持续集成:让自动化真正融入流程
5.1 用API造数据,让UI用例更稳定
UI自动化的一个大痛点是前置条件太脆弱。下单用例需要已注册用户、需要商品库存、需要优惠券,如果这些都得靠UI去一步步准备,整个用例前置操作比真正要测的动作还多。
更靠谱的做法是接口联动,用httpx或requests直接调后台接口造数据。登录注册、创建订单、发放优惠券这些动作,都可以在fixture阶段通过API完成。
我经常在conftest里写一个fixture,先调用接口拿到认证凭证,再把它注入到浏览器上下文的Cookie中,这样UI用例直接从已登录状态开始,省掉UI登录步骤,整体执行时间能缩短三分之一不止。
def inject_auth(context): token = get_token_by_api("tester", "123456") context.add_cookies([{ "name": "session", "value": token, "domain": "example.com", "path": "/" }])这里要特别留意,接口返回的Cookie domain必须和你访问的Web站点域名一致,否则注入不生效。跨域时很多新手会在这卡半天,其实看下浏览器Application面板的Cookie列表就能定位。
5.2 数据驱动和多环境矩阵
pytest的parametrize非常适合数据驱动,一组测试数据对应执行一次用例:
@pytest.mark.parametrize("account,password,expected", [ ("tester01", "123456", "登录成功"), ("tester02", "123456", "登录成功"), ("tester03", "", "请输入密码"), ]) def test_login_cases(account, password, expected, page): LoginPage(page).login(account, password) expect(page.locator(".login-tip")).to_have_text(expected)多浏览器矩阵也类似,但建议分两级:冒烟跑一个浏览器就够,完整回归再跑Chromium加Firefox。全浏览器矩阵跑一遍太慢,在早期没必要,等平台稳定了再逐步扩展。
环境矩阵建议通过命令行参数控制,比如pytest --env=staging,保证“同一条用例,多环境执行”成为可能。跨环境的一致性正是自动化测试体系化的标志。
5.3 持续集成:Jenkins定时任务与Allure报告
用例写得再好,如果只在本地跑,价值有限。把它挂到CI里,才算真正进入研发链路。
以Jenkins为例,构建步骤一般是这样:
git pull pip install -r requirements.txt pytest test_cases --headless --env=staging --html=report.html报告建议用Allure,历史趋势、失败截图、步骤日志都比pytest-html更清楚,团队回看也方便。
还要考虑定时策略。建议每天凌晨跑一次完整回归,工作日早上一上班先看报告,有问题直接修复。稳定之后,再考虑接入发布流水线,做到“自动化不绿不发布”。
失败重试可以加,但不建议依赖重试。重试能掩盖偶发问题,也会让失败日志变得不干净。先跑三遍,统计一下真实通过率,再决定哪些场景值得加重试。
5.4 一个自动化测试平台应该具备的核心能力
聊到“自动化测试平台”,我先泼一盆冷水:平台只是壳,核心是里面那套框架和积累的用例。但我确实也见过不少公司把自动化测试平台做成了四不像。
一个合格平台至少要有这些能力:
- 用例管理:用例树、标签、编辑、版本记录。
- 任务调度:定时任务、手动触发、按环境圈选用例集。
- 环境管理:dev、test、staging配置中心,切换环境不需要改代码。
- 报告中心:通过率、失败截图、日志、Trace回放。
- 通知机制:失败主动推送给负责人,基于webhook集成到企业微信或钉钉。
- 权限审计:谁能改脚本、谁能发布任务,必须留痕。
接口自动化平台也类似,核心不外乎接口配置、数据隔离、加密签名处理、断言机制、任务编排。能做好这些的团队,UI和接口可以共用一套调度和报告模块。
5.5 面试中被问得最多的几个问题
如果你正在准备自动化测试相关的面试,下面这几个问题几乎是必问:
第一,“Web自动化测试如何定位动态元素?”回答要点是指向稳定属性,比如data-testid、role、文本特征,尽量不用绝对路径,再用显式等待处理动态加载。
第二,“Selenium和Playwright的区别是什么?”重点说自动等待、网络拦截、多标签页的差异,最好结合具体项目里踩过的坑讲。
第三,“如何保证自动化测试的稳定性?”答稳定来自三点:稳定定位器、接口造数据、合理的等待策略,而不是盲目加sleep和重试。
第四,“请解释PO模式的好处。”说清楚封装、复用、页面变化时只改一处的维护收益。
第五,“什么时候不适合做UI自动化?”比如一次性页面、频繁重构的页面、短周期活动页,手工反而更快。
第六,“你在项目中如何衡量自动化测试的投入产出比?”可以用数据说话:每周节省多少人时、线上漏测率变化、回归频率提升。
这些问题没有一个需要背标准答案,能把真实项目思路讲清楚,比背十页八股管用。
6. 疑难场景实录:PDF打印、iframe、实时视频、认证与重定向
6.1 PDF打印场景
Web页面经常有“打印成PDF”或“导出PDF”的功能,自动化测试时很多人会栽在有头模式弹出来的系统打印对话框上。那个对话框里的按钮根本不走页面,Playwright操作不到。
我实测下来的稳定方案是:用headless模式触发打印,然后监听下载事件,把PDF保存下来再校验。
with page.expect_download() as download_info: page.get_by_role("button", name="导出PDF").click() download = download_info.value download.save_as("report.pdf") # 校验文件 assert download.suggested_filename.endswith(".pdf")然后读取PDF文件,校验页数和关键内容是否正常。PDF生成的正确性才是这个测试想验证的东西,打印对话框本身跟我们没关系。
如果一定要在有头模式验证,可以尝试把打印目标改成“另存为PDF”,但不同浏览器差异很大,不值得为此增加复杂度。
6.2 iframe、多窗口和Shadow DOM
现代前端到处都是iframe,特别是第三方支付、客服系统、地图组件。处理iframe有一个原则:先进入框架,再操作元素。
Playwright的写法是:
frame = page.frame_locator("#payment-iframe") frame.get_by_placeholder("卡号").fill("6222000000000000") frame.get_by_role("button", name="确认支付").click()Selenium则要先切switch_to.frame(),再操作,再切回来,iframe一多容易绕晕。
多窗口的写法前面提过,context.expect_page()监听新标签页,拿到新页面对象后继续操作。
Shadow DOM在Playwright里基本是自动穿透的,直接定位影子节点内部元素就行,这在Selenium里几乎要跪,也证明了Playwright在处理现代前端结构上的优势。
6.3 web端实时视频和下载文件
测实时视频页面,不能只断言页面上有个video元素就完事,更靠谱的是验证数据是否真的在传。
我常用的两个思路:一是用page.route拦截视频分片请求,持续统计请求是否返回200;二是通过JavaScript检查video.readyState,如果大于等于3,说明浏览器已经缓冲到可以播放的数据了。
video_state = page.evaluate("document.querySelector('video').readyState") assert video_state >= 3下载文件的场景在6.1里也有,page.expect_download()是核心。记住下载目录不要依赖系统默认下载路径,headless模式下必须给保存路径,否则文件会落在临时目录里找不到。
6.4 认证拦截、插件加载失败、临时重定向三个坑
先讲认证拦截。我在某个内部业务系统上跑自动化时,会话过期后,跑到一半弹出一句“web authentication required; reopen the url printed by dsh web”,整个用例卡死。这类提示的本质是认证网关在会话失效后拒绝了当前请求,要求重新打开指定URL完成认证。之前本地测不出来的原因是调试期间登录态一直新鲜,但CI里跑时间长,会话就会失效。
对策有三个方向:一是在用例开始时通过API刷新token并注入Cookie;二是定时在脚本里重新认证;三是在用例里监听认证跳转页面,一旦出现就自动执行一次登录流程再继续。最靠谱的是第一种,接口层拿token注入,UI永远从有效会话开始。
再讲插件加载失败。日志里出现“failed to load plugins web boot: 2 entries did not activate”,这类信息多半是浏览器启动时尝试加载某个业务插件失败,页面缺失组件,后续脚本自然跟着报错。排查时先区分是插件导致页面真缺元素,还是插件报错但页面可用。如果是前者,在启动浏览器时禁用无关插件,只保留业务必需的那个,能减少大量偶发问题。
最后是临时重定向。做接口类断言时,page.goto()会自动跟随301/302重定向,你可能根本注意不到中间跳了一次。如果你要校验“重定向之后落在哪个URL”,需要加上响应监听:
with page.expect_response("**/api/v1/login") as resp: page.get_by_role("button", name="登录").click() assert resp.value.status == 302这类问题线上才暴露、本地难发现的玄学,多半就藏在这三类场景里。
7. AI辅助:用LangChain做一个“用例转脚本”Agent的落地思路
7.1 为什么值得做这个Agent
现在每个团队里,测试用例大量存放在Excel、Jira、或者用例管理平台上,写得清清楚楚:“打开登录页,输入用户名,输入密码,点击登录,断言页面显示登录成功”。但QA的自动化脚本还得照着这些文本一行行去翻定位器,这是一份枯燥且低效的重复劳动。
LangChain这类大模型工具,非常适合做两件事:第一,把自然语言步骤转化为结构化动作序列;第二,把动作序列映射到Playwright或Selenium的代码片段。本质上这就是一个“自然语言转测试脚本”的Agent。它能降低写脚本的门槛,也能让不懂Python的QA参与一部分基础用例生成。
7.2 架构拆解:读取用例、提示词工程、代码生成、回归执行
整个Agent的链路大概是这样的:
先读取用例数据。如果用例在Excel表格里,用pandas或openpyxl读取,字段可能包括用例编号、标题、前置条件、操作步骤、预期结果。把这些内容清洗成标准结构。
然后做提示词工程。我踩过很多坑之后发现,不要让大模型直接生成完整Python文件,它生成的代码重则语法错、轻则拿不到定位器。更稳妥的方式是让它输出结构化的JSON动作序列:
请将以下测试步骤转换为JSON动作列表,每个动作包含: - action:goto/fill/click/expect_text/wait - target:语义化定位描述 - value:操作值 步骤:打开登录页,输入用户名tester,输入密码123456,点击登录按钮,断言页面出现“欢迎回来”输出是这样的:
[ {"action": "goto", "target": "登录页", "value": "https://example.com/login"}, {"action": "fill", "target": "用户名输入框", "value": "tester"}, {"action": "fill", "target": "密码输入框", "value": "123456"}, {"action": "click", "target": "登录按钮", "value": ""}, {"action": "expect_text", "target": "欢迎提示", "value": "欢迎回来"} ]然后建立动作到代码的映射表,这种映射关系是固定的,比如fill动作映射到page.get_by_placeholder...fill(),click映射到page.get_by_role...click()。最后再用模板把JSON拼成pytest用例,生成到指定目录。
最后让pytest收集这些生成用例执行一遍,把通过和失败的结果反馈给Agent,失败的用例可以再次交给大模型做修正建议。这个闭环才是Agent的完整形态,单纯的“一次性生成”用处不大。
7.3 生成方案的关键细节与落地建议
AI生成脚本这件事,至少要有一个清醒的认知,大模型并不了解你页面的真实结构,它生成的定位器是无源之水,只能根据常识猜,所以生成内容一定存在定位器不准的问题。
我建议把定位器交给人来做微调。AI先负责步骤逻辑生成,跑通流程之后,人工把定位器替换成准确的语义定位器。整体效率依然能提升,至少省掉了没日没夜敲“打开登录页、填用户名、填密码”这种流水账代码的工时。
另一个可以考虑的方向是结合DOM快照。Agent在执行步骤前先让浏览器把当前页面的可访问性树保存下来,把它作为上下文喂给模型,这样定位器生成的准确率会有明显提升。不过实现复杂度和Token成本都不低,适合团队已经有较强开发能力的阶段。
千万不要在团队里宣传“AI全自动生成测试脚本”,这会造成预期爆炸,然后失望更大。比较务实的目标是:让AI把30%到50%的通用用例自动生成并维护基础的步骤逻辑,剩下的定位器、断言、异常处理还是由人来完成。这已经能带来实打实的效率提升。
我在实际做这个Agent时的体会是:真正的瓶颈不在代码生成,而在用例本身的规范程度。如果团队用例写得像“进入页面随便点点”,那再强的模型也无从下手。反过来,用例写得足够结构化,AI生成的脚本质量会超出预期。所以,先把团队的用例文档规范起来,比急着上大模型更重要。
从选型、搭建、定位器、PO模式,到接口联动、持续集成、疑难排查,再到AI辅助生成脚本,这个链条走完之后,你手里的Web自动化测试就不再是几十条会跑的用例,而是一套能应对变化、能支撑发布决策的体系。这些东西刚开始只影响你自己,跑通之后影响的是整个团队的交付节奏。