现代Web应用程序不断变化。组件会被重新渲染,生成的属性在不同构建之间也可能不同。即使UI看起来完全相同,浏览器自动化也可能失败,因为它仍然依赖于页面变化之前捕获的假设。
在本文中,我使用Cursor配合BrowserAct CLI来测试一个动态项目筛选器。Cursor没有依赖不可靠的选择器,而是使用BrowserAct检查当前页面状态,并完成了任务,无需依赖脆弱的CSS选择器。
目标不是去除DOM或取代Playwright。目标是让AI代理拥有一个可靠的 检查 → 操作 → 重新评估 循环,使其能在现代、动态的网站上运行。
好了,让我们开始吧!🏎️
一个浏览器测试可能连续运行数周都成功,但在一次无害的前端更新后突然失败。
按钮依然可见。功能依然正常。但测试却失败了,因为它期望的元素不再存在。
<!-- 初始页面 -->
<div class="toolbar">
<button id="date-filter-btn">按日期筛选</button>
</div>
水合后:
<div class="toolbar toolbar--v2">
<div class="toolbar__indent"></div>
<button id="status-filter-btn" class="btn btn--active">
<span>⚙️</span>
<span>按日期筛选</span>
</button>
</div>
await page.click("#date-filter-btn")
这可能会失败,因为选择器不再匹配当前页面。
现代浏览器自动化在已知应用结构时效果最佳。工程师可以编写可靠的Playwright测试,因为他们预先了解页面结构,并在应用演变过程中维护这些测试。
// Playwright: 假设你知道页面结构
await page.click('#filter-button'); // 如果今天这个ID存在,就可以工作
await page.waitForTimeout(500); // 希望这段时间足够长
await page.fill('input[name="search"]', 'query'); // 如果DOM没有变化,就可以工作
对于AI代理来说,挑战有所不同。当Cursor操作一个不熟悉的网站时,它无法假设哪些元素存在或界面如何构建。每次有意义的交互之后,页面都可能发生变化,引入新的控件或替换现有控件。代理不是依赖之前捕获的选择器,而是需要检查当前页面状态,基于实际可用的元素选择下一个操作,并在UI更新后重新评估。 这正是BrowserAct旨在填补的空白。
BrowserAct不再要求Cursor记住之前捕获的选择器,而是让代理在决定下一步做什么之前,反复检查当前的浏览器状态。
工作流程变为:
它为Cursor提供了当前页面状态的一个紧凑表示,允许代理检查页面、基于当前可用的内容执行操作,并在每次有意义的UI变化后重新评估。Cursor不再依赖早期DOM快照中的假设,而是持续与当前实际存在的页面进行交互,这使得它面对动态界面时具备更强的适应性。
让我们从理论转向实践。为了演示一个可用的工作流程,我使用了一个可搜索的项目列表。
开始前,先安装 browser-act。
uv tool install browser-act-cli --python 3.12
你可以通过以下命令检查版本:
browser-act --version
我展示的是以下版本。你的版本可能更新的,但要点是一样的:
打开Cursor应用后,我们来测试获取我们应用的当前状态。
为此,我们向输入框中输入以下提示:
在Cursor中使用BrowserAct来测试EmbedCatalog上的搜索功能。在每次操作前读取当前页面状态。页面变化后,刷新页面状态,而不是重用之前的索引。搜索一个项目,打开其详情页面,并验证是否显示了正确的项目信息。
browser-act --session embedcatalog browser open https://embedcatalog.com
browser-act --session embedcatalog state
之后,测试过程就会开始。
请注意,Cursor在生成时可能会请求你允许执行命令。看起来会像这样:
点击运行按钮后,稍等片刻,我们的第一个命令应该会执行,打开浏览器。如果你是第一次使用自动化工具,浏览器可能会要求你确认操作。只需点击允许,然后网站就会打开:
在运行测试时,你可能会看到自动的浏览器操作。不用担心,这是BrowserAct在起作用。根据我们的命令,它可以点击按钮、滚动以及执行其他操作来获取当前页面状态。BrowserAct不是依赖之前捕获的选择器,而是生成了当前页面上可交互元素的一个紧凑表示。
不要在运行期间关闭页面,否则可能会遇到错误。
在我的Composer 2.5生成响应后,Cursor给出了以下结果:
我们没有指定任何选择器。Cursor在BrowserAct的帮助下,自动找到了所需的输入框,搜索了页面,并扫描了它。我们只是生成了一个简单的提示,完全没有查看DOM。
现在尝试一个更复杂的搜索选项。我将列出以下命令,并简要介绍工作流程:
browser-act --session embedcatalog click <CURRENT_INDEX>
browser-act --session embedcatalog wait stable
browser-act --session embedcatalog state
browser-act --session embedcatalog fill <CURRENT_INDEX> "BrowserAct"
browser-act --session embedcatalog wait stable
browser-act --session embedcatalog state
browser-act --session embedcatalog click <CURRENT_INDEX>
browser-act --session embedcatalog wait stable
browser-act --session embedcatalog get markdown
在这个工作流程中,Cursor首先打开搜索界面并等待页面稳定。然后它刷新页面状态,在搜索字段中输入"BrowserAct",等待结果加载,并再次读取更新后的状态,然后选择正确的结果。最后,它获取页面的Markdown内容,以验证预期的项目页面成功打开。
将相同内容输入Cursor并添加我们的命令后,稍等片刻我们得到了以下结果:
测试成功完成。每次交互后,Cursor都会刷新当前页面状态,然后继续下一步,从而使其能够适应更新后的界面。
验证步骤确认了正确的项目被打开。项目名称、描述、最后更新日期、星标数、标签和项目URL都与搜索结果匹配,因此工作流程以PASS的结果结束,没有依赖硬编码的选择器。
这里是一段更紧凑的版本。它保留了核心思想,但阅读起来明显更轻松。
BrowserAct并不会创建一个永远不会失效的选择器。相反,它为AI代理提供了一种更好的方式,通过反复检查当前页面状态来从UI变化中恢复,然后再决定下一步做什么。
代理不再依赖于早期捕获的ID、CSS选择器或XPath,而是与当前实际存在的页面进行交互。工作流程从:
记住 → 点击 → 希望
转变为:
检查 → 操作 → 等待 → 再次检查
使得浏览器自动化在动态网站上更具弹性。
这并非是Playwright的替代品。Playwright对于确定性浏览器测试仍然是一个优秀的选择,特别是当工程师可以使用稳定的角色定位器、文本定位器或测试ID时。
BrowserAct解决的是不同的问题:它帮助AI代理根据当前页面状态做出决策,而不是依赖先前捕获的选择器,从而操作不熟悉或不断变化的网站。这两个工具是互补的,而非竞争关系。
尽管BrowserAct处理了动态页面更新,我仍然明确验证了最终结果。一次成功的交互并不总是意味着任务已正确完成——加载问题、认证问题或应用状态仍然可能影响结果。
这就是为什么最后一步验证了页面内容,而不是假设之前的操作已经成功。这使得工作流程更加可靠,无论使用哪种浏览器自动化框架。
今天,借助于Playwright,你当然可以编写应用测试,但你应该明白,这种做法并不理想,尤其是对于长期的应用测试。使用新的id、class等重写代码会花费时间,而更简单的方法是使用BrowserAct配置浏览器层,并通过从浏览器页面读取交互性来直接与其工作。
你可以在评论中写下你对新功能的看法,我很有兴趣阅读!如果你想了解更多关于产品的信息,BrowserAct有 YouTube 频道和 Discord 账号,你可以在那里讨论这个工具的工作原理。
一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。