将浏览器脚本迁移到 k6 v0.52
本指南概述了将现有 k6 实验性浏览器测试脚本迁移到捆绑在 k6 0.52 中的 最新 k6 浏览器模块版本时需要进行的主要更改。
主要变更
在 k6 的最新版本中,我们将 k6 浏览器模块从实验性阶段毕业,现在它位于导入路径 k6/browser
下。迁移到这个模块是一个破坏性更改,将影响使用实验性 k6 浏览器模块的 所有脚本。这些破坏性更改包括:
- 将大多数 k6 浏览器模块 API 转换为了异步 (async) API。这意味着它们将返回一个
promise
,该 promise 在 API 调用成功时将resolve
为一个值,或在发生错误时reject
。 - 进行此异步更改的一个副作用是,您需要使用 jslib.k6.io 中的
check
工具函数,而不是使用 k6 的 check API。 - 最后,值得重申的是,group API 仍然不适用于异步 API。
如果您对此次更改背后的原理感兴趣,请参阅 v0.51 发布说明。
注意
实验性导入 (
k6/experimental/browser
) 及相应的同步 API 将支持到 2024 年 9 月 23 日。
迁移到异步
为确保您的脚本在最新版本的 k6 浏览器模块中正常工作,您必须:
- 将导入路径从
k6/experimental/browser
更改为k6/browser
。 - 确保所有已迁移到异步的同步 (sync) API 都得到适当处理。在大多数情况下,您只需要在 API 调用前面添加
await
。
例如,之前
import { browser } from 'k6/experimental/browser';
...
export default async function () {
const page = browser.newPage();
...
}
现在
import { browser } from 'k6/browser';
...
export default async function () {
const page = await browser.newPage();
...
}
在使用浏览器模块时,您可能已经遇到过异步 API,例如 page.click,因此 async
和 await
关键字的使用对您来说可能并不陌生。
下面是 v0.51
和 v0.52
中通用浏览器测试的比较截图,以帮助您可视化此更改:
受影响的 API
类 | 方法 |
---|---|
Browser | closeContext |
Browser | context |
Browser | newContext |
Browser | newPage |
Browser | userAgent |
BrowserContext | addCookies |
BrowserContext | addInitScript |
BrowserContext | browser |
BrowserContext | clearCookies |
BrowserContext | clearPermissions |
BrowserContext | close |
BrowserContext | cookies |
BrowserContext | grantPermissions |
BrowserContext | newPage |
BrowserContext | setGeolocation |
BrowserContext | setOffline |
ElementHandle | $ |
ElementHandle | $$ |
ElementHandle | boundingBox |
ElementHandle | check |
ElementHandle | contentFrame |
ElementHandle | dblclick |
ElementHandle | dispatchEvent |
ElementHandle | fill |
ElementHandle | focus |
ElementHandle | getAttribute |
ElementHandle | hover |
ElementHandle | innerHTML |
ElementHandle | innerText |
ElementHandle | inputValue |
ElementHandle | isChecked |
ElementHandle | isDisabled |
ElementHandle | isEditable |
ElementHandle | isEnabled |
ElementHandle | isHidden |
ElementHandle | isVisible |
ElementHandle | ownerFrame |
ElementHandle | press |
ElementHandle | screenshot |
ElementHandle | scrollIntoViewIfNeeded |
ElementHandle | selectOption |
ElementHandle | selectText |
ElementHandle | setInputFiles |
ElementHandle | tap |
ElementHandle | textContent |
ElementHandle | type |
ElementHandle | uncheck |
ElementHandle | waitForElementState |
ElementHandle | waitForSelector |
Frame | $ |
Frame | $$ |
Frame | check |
Frame | content |
Frame | dblclick |
Frame | dispatchEvent |
Frame | evaluate<R, Arg> |
Frame | evaluateHandle<R, Arg> |
Frame | fill |
Frame | focus |
Frame | frameElement |
Frame | getAttribute |
Frame | hover |
Frame | innerHTML |
Frame | innerText |
Frame | inputValue |
Frame | isChecked |
Frame | isDisabled |
Frame | isEditable |
Frame | isEnabled |
Frame | isHidden |
Frame | isVisible |
Frame | press |
Frame | selectOption |
Frame | setContent |
Frame | setInputFiles |
Frame | tap |
Frame | textContent |
Frame | title |
Frame | type |
Frame | uncheck |
Frame | waitForLoadState |
Frame | waitForSelector |
Frame | waitForTimeout |
JSHandle | asElement |
JSHandle | dispose |
JSHandle | evaluate<R, Arg> |
JSHandle | evaluateHandle<R, Arg> |
JSHandle | getProperties |
JSHandle | jsonValue |
Keyboard | down |
Keyboard | insertText |
Keyboard | press |
Keyboard | type |
Keyboard | up |
Locator | check |
Locator | clear |
Locator | dblclick |
Locator | dispatchEvent |
Locator | fill |
Locator | focus |
Locator | getAttribute |
Locator | hover |
Locator | innerHTML |
Locator | innerText |
Locator | inputValue |
Locator | isChecked |
Locator | isDisabled |
Locator | isEditable |
Locator | isEnabled |
Locator | isHidden |
Locator | isVisible |
Locator | press |
Locator | selectOption |
Locator | tap |
Locator | textContent |
Locator | type |
Locator | uncheck |
Locator | waitFor |
Mouse | click |
Mouse | dblclick |
Mouse | down |
Mouse | move |
Mouse | up |
Page | $ |
Page | $$ |
Page | bringToFront |
Page | check |
Page | close |
Page | content |
Page | dblclick |
Page | dispatchEvent |
Page | emulateMedia |
Page | emulateVisionDeficiency |
Page | evaluate<R, Arg> |
Page | evaluateHandle<R, Arg> |
Page | fill |
Page | focus |
Page | getAttribute |
Page | hover |
Page | innerHTML |
Page | innerText |
Page | inputValue |
Page | isChecked |
Page | isDisabled |
Page | isEditable |
Page | isEnabled |
Page | isHidden |
Page | isVisible |
Page | on |
Page | opener |
Page | press |
Page | reload |
Page | screenshot |
Page | selectOption |
Page | setContent |
Page | setExtraHTTPHeaders |
Page | setInputFiles |
Page | setViewportSize |
Page | tap |
Page | textContent |
Page | throttleCPU |
Page | throttleNetwork |
Page | title |
Page | type |
Page | uncheck |
Page | viewportSize |
Page | waitForLoadState |
Page | waitForSelector |
Page | waitForTimeout |
Request | allHeaders |
Request | headerValue |
Request | headersArray |
Request | postData |
Request | resourceType |
Request | response |
Request | size |
Request | timing |
Response | allHeaders |
Response | body |
Response | headerValue |
Response | headerValues |
Response | headersArray |
Response | json |
Response | securityDetails |
Response | serverAddr |
Response | size |
Touchscreen | tap |
使用 k6 check
k6 的 check
API 不会 await
promises,因此在其中一个谓词内调用返回 Promise
的函数(例如 locator.textContent()
)将不起作用。相反,您可以使用 jslib.k6.io 的 check
工具函数。
例如,之前
check(page.locator('h2'), {
header: lo => lo.textContent() == 'Welcome, admin!',
});
现在
import { check } from 'https://jslib.k6.io/k6-utils/1.5.0/index.js';
// ...
await check(page.locator('h2'), {
'header': async lo => await lo.textContent() === 'Welcome, admin!'
});
Groups
关于 groups 的说明,它们也不适用于异步 API,目前还没有变通方案。您可以关注此 GitHub issue,以了解适用于异步 API 的 group API 的相关最新消息。
从 k6 v0.45 或更早版本迁移
如果您使用 k6 v0.45 或更早版本,请先查看 如何迁移到 v0.46。本指南详细介绍了 v0.46 中引入的针对 browser
API 的破坏性更改,并提供了如何迁移到这些更改的说明。
在哪里获取额外帮助
随着 k6 v0.52
的发布,您还可以找到最新的类型定义以及 k6 浏览器文档 的更新。有关如何在项目中处理类型定义文件的详细信息,请参阅 配置 k6 IntelliSense。
有关所有详细信息,请查阅 k6 0.52 版本 的 CHANGELOG。如果您需要帮助,也可以在社区论坛中提问。