运行浏览器测试
按照以下步骤学习如何
- 运行测试
- 与网页上的元素交互
- 等待页面导航
- 在单个脚本中同时运行浏览器级别和协议级别测试
运行测试
运行一个简单的本地脚本
复制以下代码,将其粘贴到您喜欢的编辑器中,并保存为
script.js
。请注意,提供
executor
并将浏览器场景选项的type
设置为chromium
是强制性的。请参阅选项和场景文档了解更多信息。import { browser } from 'k6/browser'; export const options = { scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium', }, }, }, }, thresholds: { checks: ['rate==1.0'], }, }; export default async function () { const page = await browser.newPage(); try { await page.goto('https://test.k6.io/'); await page.screenshot({ path: 'screenshots/screenshot.png' }); } finally { await page.close(); } }
上面的代码导入了 browser 模块,并使用其
newPage
方法打开一个新页面。获取页面后,您可以使用 Page 方法与其交互。此示例访问一个测试 URL 并截取页面屏幕截图。
随后,页面被关闭。这可以释放分配的资源,并有助于准确计算 Web Vital 指标。
注意
从 v0.52.0 开始,browser 模块 API 已转换为异步 API。这意味着大多数方法现在返回 Promise。请参阅迁移指南,了解有关更改以及如何更新脚本的更多信息。
然后,在您的终端中使用此命令运行测试
k6 run script.js
# WARNING! # The grafana/k6:master-with-browser image launches a Chrome browser by setting the # 'no-sandbox' argument. Only use it with trustworthy websites. # # As an alternative, you can use a Docker SECCOMP profile instead, and overwrite the # Chrome arguments to not use 'no-sandbox' such as: # docker container run --rm -i -e K6_BROWSER_ARGS='' --security-opt seccomp=$(pwd)/chrome.json grafana/k6:master-with-browser run - <script.js # # You can find an example of a hardened SECCOMP profile in: # https://raw.githubusercontent.com/jfrazelle/dotfiles/master/etc/docker/seccomp/chrome.json. docker run --rm -i -v $(pwd):/home/k6/screenshots grafana/k6:master-with-browser run - <script.js
k6 run script.js
k6 run script.js
您还可以使用浏览器模块选项来自定义浏览器进程的启动。例如,您可以使用之前的测试脚本通过此命令启动一个有界面的浏览器。
K6_BROWSER_HEADLESS=false k6 run script.js
# WARNING! # The grafana/k6:master-with-browser image launches a Chrome browser by setting the # 'no-sandbox' argument. Only use it with trustworthy websites. # # As an alternative, you can use a Docker SECCOMP profile instead, and overwrite the # Chrome arguments to not use 'no-sandbox' such as: # docker container run --rm -i -e K6_BROWSER_ARGS='' --security-opt seccomp=$(pwd)/chrome.json grafana/k6:master-with-browser run - <script.js # # You can find an example of a hardened SECCOMP profile in: # https://raw.githubusercontent.com/jfrazelle/dotfiles/master/etc/docker/seccomp/chrome.json. docker run --rm -i -v $(pwd):/home/k6/screenshots -e K6_BROWSER_HEADLESS=false grafana/k6:master-with-browser run - <script.js
set "K6_BROWSER_HEADLESS=false" && k6 run script.js
$env:K6_BROWSER_HEADLESS=false ; k6 run script.js
注意
使用 Docker 运行 k6 browser 测试时,请确保您已拉取内置 Chromium 的正确镜像。请参阅通过 Docker 安装 k6 了解更多信息。
可选步骤:在配备 Apple Silicon 芯片的 Mac 电脑上使用 Docker 运行浏览器测试
确保您正在运行最新版本的 Docker。
更新 Rosetta 并导出以下环境变量
softwareupdate --install-rosetta && export DOCKER_DEFAULT_PLATFORM=linux/amd64
在设置 > 通用 > VirtuoFS 中选择 VirtuoFS。
在设置 > 开发功能 > 在 Apple Silicon 上使用 Rosetta 进行 x86/amd64 模拟 中启用 Rosetta 模拟。
重启 Docker。
使用以下命令运行浏览器镜像(添加
--platform
标志)docker run --rm -i --platform linux/amd64 -v $(pwd):/home/k6/screenshots -e K6_BROWSER_HEADLESS=false grafana/k6:master-with-browser run - <script.js
与网页上的元素交互
您可以使用 page.locator()
并传入要在页面上查找的元素选择器。page.locator()
将创建并返回一个 Locator 对象,您稍后可以使用它与元素交互。
要了解浏览器模块支持哪些选择器,请查看选择元素。
注意
您也可以使用
page.$()
代替page.locator()
。您可以在 Locator API 文档中找到page.locator()
和page.$
之间的区别。
import { browser } from 'k6/browser';
export const options = {
scenarios: {
ui: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
},
},
thresholds: {
checks: ['rate==1.0'],
},
};
export default async function () {
const page = await browser.newPage();
try {
await page.goto('https://test.k6.io/my_messages.php');
// Enter login credentials
await page.locator('input[name="login"]').type('admin');
await page.locator('input[name="password"]').type('123');
await page.screenshot({ path: 'screenshots/screenshot.png' });
} finally {
await page.close();
}
}
上面的代码创建并返回一个 Locator 对象,并将登录和密码的选择器作为参数传入。
在 Locator API 中,可以使用 type()
等各种方法与元素交互。type()
方法将文本输入到输入字段中。
异步操作
由于许多浏览器操作是异步发生的,并且为了更紧密地遵循 Playwright API,我们正在努力将大部分浏览器模块方法也迁移为异步方法。
目前,page.goto()
、page.waitForNavigation()
和 Element.click()
等方法返回 JavaScript Promise,并且必须编写脚本以正确处理此情况。
为了避免脚本中的时序错误或其他竞态条件,如果您的操作会加载其他页面,则需要确保在继续之前等待该操作完成。
import { browser } from 'k6/browser';
import { check } from 'https://jslib.k6.io/k6-utils/1.5.0/index.js';
export const options = {
scenarios: {
ui: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
},
},
thresholds: {
checks: ['rate==1.0'],
},
};
export default async function () {
const page = await browser.newPage();
try {
await page.goto('https://test.k6.io/my_messages.php');
await page.locator('input[name="login"]').type('admin');
await page.locator('input[name="password"]').type('123');
const submitButton = page.locator('input[type="submit"]');
await Promise.all([page.waitForNavigation(), submitButton.click()]);
await check(page.locator('h2'), {
header: async (lo) => (await lo.textContent()) == 'Welcome, admin!',
});
} finally {
await page.close();
}
}
上面的代码使用 Promise.all([])
来等待这两个 Promise 解析完成后再继续。由于点击提交按钮会导致页面导航,因此需要使用 page.waitForNavigation()
,因为在导航完成之前页面不会准备好。这是必需的,因为如果这两个操作不是同时发生,可能会出现竞态条件。
然后,您可以使用 k6 API 中的 check
来断言特定元素的文本内容。最后,关闭页面和浏览器。
在单个脚本中同时运行浏览器级别和协议级别测试
browser 模块的真正强大之处在于它与 k6 现有功能的结合。您可以尝试的一种常见场景是将少量浏览器级别测试与大量协议级别测试混合进行,后者可以模拟您的网站对各种性能事件的响应。我们称这种方法为混合负载测试,它具有以下优势:
- 在生成更高后端负载的同时测试前端真实用户流
- 在同一测试执行中测量后端和前端性能
- 后端和前端团队之间的协作增强,因为可以使用相同的工具
要同时运行浏览器级别和协议级别测试,您可以使用场景。
注意
请记住,启动浏览器 VU 会产生额外的性能开销,并且资源使用情况取决于被测系统。
import { browser } from 'k6/browser';
import { check } from 'https://jslib.k6.io/k6-utils/1.5.0/index.js';
import http from 'k6/http';
export const options = {
scenarios: {
browser: {
executor: 'constant-vus',
exec: 'browserTest',
vus: 1,
duration: '10s',
options: {
browser: {
type: 'chromium',
},
},
},
news: {
executor: 'constant-vus',
exec: 'news',
vus: 20,
duration: '1m',
},
},
};
export async function browserTest() {
const page = await browser.newPage();
try {
await page.goto('https://test.k6.io/browser.php');
await page.locator('#checkbox1').check();
await check(page.locator('#checkbox-info-display'), {
'checkbox is checked': async (lo) =>
(await lo.textContent()) === 'Thanks for checking the box',
});
} finally {
await page.close();
}
}
export function news() {
const res = http.get('https://test.k6.io/news.php');
check(res, {
'status is 200': (r) => r.status === 200,
});
}
上面的代码包含两个场景。一个用于浏览器级别测试,名为 browser
;一个用于协议级别测试,名为 news
。这两个场景都使用 constant-vus 执行器,该执行器引入固定数量的虚拟用户在指定时间内执行尽可能多的迭代。
由于所有内容都在一个脚本中,这增强了团队间的协作。