尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

k6 v1.2.0 深度解析:自动扩展解析、gRPC 健康检查与 Browser 模块 getBy* 选择器全解析

k6 v1.2.0 深度解析:自动扩展解析、gRPC 健康检查与 Browser 模块 getBy* 选择器全解析 k6 v1.2.0 深度解析自动扩展解析、gRPC 健康检查与 Browser 模块 getBy* 选择器全解析【免费下载链接】k6A modern load testing tool, using Go and JavaScript项目地址: https://gitcode.com/GitHub_Trending/k6/k6k6 v1.2.0 是一次显著提升可扩展性与测试体验的发布自动扩展解析Automatic Extension Resolution默认启用后脚本导入扩展即可自动装配二进制无需手工编译gRPC 模块新增client.healthCheck()方法并规范了NaN/Infinity的序列化Browser 模块则补齐了page.route、全套page.getBy*选择器、locator.all()与page.waitForURL。读完本文你将掌握 v1.2.0 各新特性的用法与适用边界并能对照开源仓库中的源码与示例脚本理解这些能力在 Go 侧的实际实现链路写出更健壮、可维护的 k6 测试脚本。一、本版本亮点总览与破坏性变更v1.2.0 的核心内容可归纳为三块自动扩展解析Automatic Extension Resolution原实验性的 Binary Provisioning 能力更名为“自动扩展解析”并对所有用户默认启用gRPC 增强NaN/Infinity浮点值的处理更合理并新增client.healthCheck()简化健康检查Browser 模块增强新增page.route、page.getBy*系列 API、locator.all()与page.waitForURL。破坏性变更仅限实验性特性按照 k6 的版本稳定性承诺次要版本minor release中的破坏性变更只允许发生在实验性特性上。v1.2.0 中的唯一破坏性变更是实验性的 OpenTelemetry 与 Prometheus 输出默认改用 TLSv1.3。发布说明认为这“本就应该”是默认值绝大多数用户不受影响只是让指标外发更加安全。这一点可以从源码中得到印证OpenTelemetry 输出的 TLS 配置直接写死了最低版本为 TLS 1.3internal/output/opentelemetry/tls.goMinVersion: tls.VersionTLS13,Prometheus Remote Write 输出同样默认tlsMinVersion为 1.3且仅允许通过tlsMinVersion配置项显式降回 1.2internal/output/prometheusrw/remotewrite/config.gotlsMinVersion : uint16(tls.VersionTLS13) if conf.TLSMinVersion.Valid conf.TLSMinVersion.String 1.2 { tlsMinVersion tls.VersionTLS12 }也就是说如果你此前依赖这两个实验性输出以 TLS 1.2 连接某些老旧后端需要显式配置降级否则从 v1.2.0 起默认最低为 TLSv1.3。二、自动扩展解析Automatic Extension Resolution不再手工编译 k6 二进制k6 扩展用于为测试增加自定义能力例如连接数据库、消息队列或专用网络协议。在 v1.2.0 之前使用扩展需要手动构建一个把扩展编译进去的定制 k6 二进制go build -tags executable等方式。v1.2.0 引入的自动扩展解析功能前身为实验性的 Binary Provisioning默认开启它会自动检测脚本中导入的扩展并替你处理“为脚本装配正确 k6 二进制”的复杂性。用法与以前一样直观——直接import即可import faker from k6/x/faker; export default function () { console.log(faker.person.firstName()); }社区扩展K6_ENABLE_COMMUNITY_EXTENSIONSv1.2.0 之前该实验能力只支持官方扩展。对应上游 PR #4922 之后可以通过环境变量启用任意社区扩展即官方社区扩展清单中列出的扩展K6_ENABLE_COMMUNITY_EXTENSIONStrue k6 run script.js需要特别注意适用边界社区扩展仅支持本地执行k6 run或k6 cloud run --local-execution在 Grafana Cloud k6 上运行时只允许官方扩展。源码视角k6 如何“认识”扩展k6 在 Go 侧维护了一个全局扩展注册表扩展实现方在初始化时调用ext.Register(name, typ, mod)注册自己。注册表区分四种扩展类型ext/ext.goconst ( JSExtension ExtensionType iota 1 OutputExtension SecretSourceExtension SubcommandExtension )Extension结构体记录了扩展名、导入路径、版本与模块实例注册时会通过extractModuleInfo结合debug.ReadBuildInfo()反查出该扩展所属 Go module 的路径和版本ext/ext.go——这正是自动扩展解析能够“按 import 路径识别脚本需要哪些扩展、再去装配/下载对应二进制”的基础信息。换言之脚本里import faker from k6/x/faker这一行最终会被映射为注册表中某个Path为扩展 module 路径的JSExtension条目再由解析器据此决定是否使用本地二进制、还是需要额外装配。仓库中k6/x/faker、k6/x/secrets、k6/x/totp等k6/x/前缀模块即为随官方二进制分发的内置扩展examples/secrets 目录下的 secrets.test.js、totp.test.js 等脚本展示了这类扩展的典型用法。三、gRPCNaN/Infinity 序列化修复与 client.healthCheck()3.1 NaN 与 Infinity 的字符串化此前请求消息中的NaN或Infinity浮点值会被 JSON 序列化时丢成null服务端拿到的是错误数据。v1.2.0 改为使用其字符串表示NaN、Infinity、-Infinity与其他 gRPC API 生态保持一致脚本本身无需任何修改。该行为在源码中体现于buildInvokeRequest调用normalizeNumberStrings的递归处理遍历请求对象遇到float64类型时按math.IsNaN/math.IsInf分别替换为字符串值internal/js/modules/k6/grpc/client.go// Handle special float values. if v.ExportType().Kind() reflect.Float64 { f : v.ToFloat() switch { case math.IsNaN(f): return runtime.ToValue(NaN), nil case math.IsInf(f, 1): return runtime.ToValue(Infinity), nil case math.IsInf(f, -1): return runtime.ToValue(-Infinity), nil } return v, nil }对应的 Go 端测试用例会校验服务端收到的值与 JS 端respNaN.message NaN、respInfinity.message Infinityinternal/js/modules/k6/grpc/client_test.go可以作为该行为契约的直接证据。3.2 client.healthCheck()一行完成 gRPC 就绪检查此前要做健康检查必须手写样板代码直接 invoke 标准健康检查方法import grpc from k6/grpc; const client new grpc.Client(); // ... const response client.invoke(grpc.health.v1.Health/Check, { service: my-service });现在可以直接使用client.healthCheck()特别适合就绪检查readiness check与服务发现场景import grpc from k6/grpc; const client new grpc.Client(); client.connect(grpc.test.k6.io:443); // Check the health of a specific service const response client.healthCheck(my-service); // Check the health of the overall gRPC server const overallResponse client.healthCheck(); client.close();仓库自带可运行的示例脚本 examples/grpc_healthcheck.js它连接本地示例服务并用check断言状态为Servingconst response client.healthCheck() check(response, { healthcheck status is OK: (r) r r.status grpc.HealthCheckServing });从源码链路看JS 侧的healthCheck最终调用 Go 侧的HealthCheck方法svc参数以指针传入nil表示查询整个服务器否则查询指定服务名internal/js/modules/k6/grpc/client.go// HealthCheck checks if the server side is up and ready to serve responses func (c *Client) HealthCheck(svc *string) (*grpcext.HealthCheckResponse, error) { var service string if svc ! nil { service *svc } return c.conn.HealthCheck(c.vu.Context(), service) }模块还会把标准健康检查的枚举状态暴露为 JS 常量grpc.HealthCheckUnknown、grpc.HealthCheckServing、grpc.HealthCheckNotServing、grpc.HealthCheckServiceUnkown等见 internal/js/modules/k6/grpc/grpc.go因此断言时可以按枚举值比较而不是硬编码字符串。仓库测试用例还覆盖了SERVING/NOT_SERVING/UNKNOWN三种状态在 JS 侧的返回internal/js/modules/k6/grpc/client_test.go。另外v1.2.0 还对 gRPC 模块做了两处配套改进支持authority伪请求头UX 增强项并修复了从远程服务器获取 protobuf 定义时的潜在竞态bug fixes 项对反射式加载服务定义的用户是实质性的稳定性提升。四、Browser 模块getBy* 语义选择器全家桶v1.2.0 为 Browser 模块一次性补齐了 Playwright 风格的getBy*系列 API。它们共同的优点是语义化相比 CSS 类名或 XPath这类选择器更贴合用户实际交互方式在 UI 重构后更不容易失效。所有选择器在 JS 侧统一注册于page对象的 mapping 中internal/js/modules/k6/browser/browser/page_mapping.gogetByRole、getByAltText、getByLabel、getByPlaceholder、getByTitle、getByTestId、getByText。4.1 page.getByRole基于 ARIA 角色定位按元素的 ARIA 角色button、link、textbox、heading 等定位可结合可访问名称name支持字符串或正则、状态如checked、层级heading 的level等选项// Find elements by role await page.getByRole(button).click(); // Find elements by role and accessible name await page.getByRole(button, { name: Submit }).click(); // name works with regex too await page.getByRole(textbox, { name: /^Username$/ }).fill(admin); // Work with specific states await page.getByRole(checkbox, { name: Accept terms, checked: true }).click(); // Find headings by level await page.getByRole(heading, { level: 2, name: Section Title }).textContent();仓库示例 examples/browser/route.js 中就实际使用了page.getByRole(button, { name: /pizza/i }).click()来驱动页面操作。4.2 page.getByAltText按 alt 文本定位替代繁琐的 CSS/XPath 属性选择// 旧写法 const locator page.locator(img[altWorld Map]); const locator2 page.locator(//img[altWorld Map]); // 新写法支持正则 const locator page.getByAltText(World Map); const locator3 page.getByAltText(/^World/);4.3 page.getByLabel按标签文本定位表单元素同时兼容显式label元素与aria-label属性非常适合表单测试// 旧写法XPath 找 label 或 CSS 找 aria-label const locator page.locator(//label[text()Password]); // 新写法 const passwordInput page.getByLabel(Password); const usernameInput page.getByLabel(/^Username$/);4.4 page.getByPlaceholder / getByTitle / getByTestId / getByText这四个 API 的模式一致以前需要 CSS/XPath 属性选择或 XPath 文本匹配现在直接按语义属性定位且大多支持正则// 按 placeholder 定位输入框 const nameInput page.getByPlaceholder(Enter your name); const emailInput page.getByPlaceholder(/^Email/); // 按 title 属性定位tooltip、按钮等 const infoBox page.getByTitle(Information box); const saveButton page.getByTitle(/^Save/); // 按>// 1. Block all image requests await page.route(/(\.png$)|(\.jpg$)|(\.jpeg$)/, async (route) { await route.abort(); }); // 2. Mock API responses await page.route(**/api/users, async (route) { await route.fulfill({ status: 200, contentType: application/json, body: JSON.stringify([{ id: 1, name: Mock User }]) }); }); // 3. Continue with modified headers await page.route(**/api/**, async (route) { await route.continue({ headers: { ...route.request().headers(), Authorization: Bearer mock-token } }); });模式参数支持字符串 glob**/api/users与正则。仓库中的示例 examples/browser/route.js 展示了更完整的实战组合拦截并 abort 掉api/tools接口与图片请求同时用page.on(request/response)与waitForResponse观察真实请求流再配合getByRole点击按钮并验证 pizza API 返回 200await page.route(https://quickpizza.grafana.com/api/tools, function (route) { route.abort(); }); await page.route(/(\.png$)|(\.jpg$)/, function (route) { route.abort(); });page.route的落地是多个连续 PR 迭代完成的#4953、#4961、#4971、#4985说明该能力经历了模式匹配、fulfill、continue 等分阶段完善。六、Browser 模块locator.all() 与 page.waitForURL6.1 locator.all()拿到所有匹配元素locator.all()返回所有匹配元素的 locator 数组适合列表页、同构按钮组等多元素场景// Get all list items and iterate through them const items await page.locator(li).all(); for (const item of items) { console.log(await item.textContent()); }6.2 page.waitForURL等待导航到指定 URLwaitForURL同时加到了page和frame上源码中page的注册见 internal/js/modules/k6/browser/browser/page_mapping.go。其语义设计值得注意waitForURL会先检查当前页面 URL 是否已经匹配目标模式若已匹配则只等待 load state 完成否则才等待一次导航发生。这一设计避免了“页面在等待条件建立之前就已经完成导航”的竞态对多次重定向的页面尤其有用。配套地waitForNavigation也新增了url选项但官方建议优先使用waitForURL。支持字符串与正则两种模式典型写法是把“等待”与“触发点击”放进Promise.all// Wait for navigation to a specific URL await Promise.all([ page.waitForURL(https://quickpizza.grafana.com/my_messages.php), page.locator(a[href/my_messages.php]).click(), ]); // Using regex pattern await Promise.all([ page.waitForURL(/.*\/contacts\.php.*/), page.locator(a[href^/contacts.php]).click() ]);官方同时提醒URL 等待是便捷手段更可靠的测试仍推荐元素级等待与 locator API 的自动等待能力。七、断言库 Previewexpect() 与 fluent 断言风格v1.2.0 提供了一套断言库Preview引入expect函数与一组表达力强的 matcher用于验证应用行为是否符合预期同时覆盖协议测试HTTP/API与 Browser 测试两种场景。API 风格借鉴 Playwright 的断言语法import { expect } from https://jslib.k6.io/k6-testing/0.5.0/index.js; import { browser } from k6/browser; import http from k6/http; export function protocolTest() { // Get the home page of k6s Quick Pizza app const response http.get(https://quickpizza.grafana.com/); // Simple assertions expect(response.status).toBe(200); expect(response.error).toEqual(); expect(response.body).toBeDefined(); } export async function browserTest() { const page await browser.newPage(); try { await page.goto(https://quickpizza.grafana.com/); // Assert the Pizza Please button is visible await expect(page.locator(button[namepizza-please])).toBeVisible(); } finally { await page.close(); } } export const options { scenarios: { // Protocol tests protocol: { executor: shared-iterations, vus: 1, iterations: 1, exec: protocolTest, }, // Browser tests ui: { executor: shared-iterations, options: { browser: { type: chromium } }, exec: browserTest, }, }, };注意两点使用前提该库通过jslib URL 导入https://jslib.k6.io/k6-testing/0.5.0/index.js属于外部 JavaScript 库而非内置 Go 模块因此升级依赖的是库版本而非 k6 版本它处于Preview阶段不会计划或预期引入破坏性变更但功能可能不完整、边缘粗糙团队会持续补充 matcher 与覆盖面。配合 UX 增强项 #5040k6 官方脚本模板k6 new也已改用新的expect()语法仓库中模板源码见 internal/cmd/templates如 minimal.js、browser.js新创建的脚本会直接体现这一风格。八、UX 改进、Bug 修复与维护项速览UX 改进与增强测试结束汇总中当没有 check 时不再报告 NaN 百分比修复了误导性的NaN%输出Browser 模块的locator.selectOption支持字符串 labelgRPC 模块支持authority伪请求头错误打印行为更一致、更正确Browser 导航事件会向上暴露导航错误page.url()改为返回缓存值不再每次发起浏览器调用显著更快并与 Playwright 行为对齐Browser 模块中被 abort 的请求在输出上更明确新增 Prometheus 指标端点可用于观测 k6 自身运行状态汇总中指标列的对齐方式更紧凑减少圆点与横向空间占用。Bug 修复与版本主题强相关修复 Browser 模块中整型转换错误#4850修复创建Page之前请求BrowserContext导致的 panic#4973修复 Browser 模块潜在竞态条件#4975;修复waitForNavigation在未调用page.close时阻塞迭代结束的问题#5015修复 gRPC 模块从远程服务器获取 protobuf 定义时的潜在竞态#5017。维护与内部改进与自动扩展解析相关的关键项将 k6 的文件系统传递给 k6deps自动扩展解析的装配依赖#4958新增“禁用自动扩展解析时运行测试”的回归测试#5014并修复启用该能力后的内部测试#5016——说明该特性已经稳定到具备双向启用/禁用测试覆盖云端输出日志降噪、Docker 构建基础镜像更新至 Linux Alpine 3.22、依赖批量升级与 CI 稳定性加固等。九、升级指引与适用边界升级前建议关注以下几点TLS 默认值如果你使用实验性 OTel / Prometheus 输出且后端最高只支持 TLS 1.2请在 Prometheus 输出的tlsMinVersion中显式指定1.2或升级后端OpenTelemetry 输出的 1.3 下限目前为硬编码见 internal/output/opentelemetry/tls.go。社区扩展仅限本地执行K6_ENABLE_COMMUNITY_EXTENSIONStrue只对k6 run与k6 cloud run --local-execution生效Grafana Cloud k6 执行仅支持官方扩展。gRPC 脚本零改动NaN/Infinity 的字符串化与healthCheck()均为向后兼容变更旧脚本无需修改即可享受新行为依赖invoke(grpc.health.v1.Health/Check, ...)的老写法仍可用但建议迁移到client.healthCheck()以降低样板代码。断言库是外部 jslib 且处于 Preview升级 k6 到 v1.2.0 不会自动改变断言库版本需按需固定 jslib URL 中的版本号。waitForNavigation 行为其复杂度被内部降低#4960且与waitForURL的关系上官方明确推荐后者等待导航逻辑建议统一迁移。结合仓库资源快速上手的建议路径gRPC 健康检查可参考 examples/grpc_healthcheck.js 与本地示例服务 examples/grpc_server按注释用go run -modmod examples/grpc_server/*.go启动Browser 的 route 拦截与getByRole组合可参考 examples/browser/route.js扩展secrets/totp用法可参考 examples/secrets更细的选择器行为边界可阅读 internal/js/modules/k6/browser/tests/get_by_test.go 与 internal/js/modules/k6/grpc/client_test.go 中的对应测试用例。综上v1.2.0 的价值在于把“扩展装配、gRPC 服务检查、浏览器语义定位与请求拦截”这三类高频痛点一次性工程化扩展解析让你告别手工编译healthCheck()与getBy*让脚本样板代码大幅减少page.route则补齐了负载测试中“可控环境”的关键一环。对于升级到 v1.2.0 的项目除实验性输出的 TLS 下限外没有需要立即处理的迁移工作可以放心采用。【免费下载链接】k6A modern load testing tool, using Go and JavaScript项目地址: https://gitcode.com/GitHub_Trending/k6/k6创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表