ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

使用 Testcontainers 的 k6 模块在 Java 测试中执行可靠性测试脚本

使用 Testcontainers 的 k6 模块在 Java 测试中执行可靠性测试脚本 使用 Testcontainers 的 k6 模块在 Java 测试中执行可靠性测试脚本【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java导读本文以 Testcontainers 官方 k6 模块org.testcontainers:testcontainers-k6为主题介绍如何在 JUnit 测试中一键拉起 Grafana 官方的grafana/k6容器、注入测试脚本与命令行参数并通过脚本变量与容器日志断言测试结果。读完本文你将掌握K6Container的完整构建 API、测试脚本的挂载与执行方式以及底层命令组装原理可直接把 k6 可靠性测试reliability testing接入自己的 Java 测试流水线。k6 模块概览k6 是 Grafana 出品的、以开发者体验为核心的扩展性可靠性测试工具。Testcontainers 为其提供了专门的模块封装使 k6 无需本地安装而是以容器实例的形式在测试期间按需启动和销毁。模块对应的镜像为 Grafana 官方提供的grafana/k6其默认镜像常量定义在 K6Container.java 中/** Standard image for k6, as provided by Grafana. */ private static final DockerImageName K6_IMAGE DockerImageName.parse(grafana/k6);注意INCUBATING该模块目前处于incubating孵化状态。根据官方声明它在当前版本的 Testcontainers 中已经可以正常使用但未来版本可能引入破坏性变更。Testcontainers 的孵化模块政策详见 docs/contributing.md#incubating-modules项目会定期评估孵化模块的可维护性与可用性并在合适时机移除该标记。环境准备使用本模块前需要保证测试运行环境具备可用的 Docker或兼容的容器运行时这是 Testcontainers 所有容器化模块的基础前提。关于运行环境的支持情况可参阅 docs/supported_docker_environment/index.md。添加项目依赖在pom.xmlMaven或build.gradleGradle中加入如下依赖{{latest_version}}请替换为你实际使用的 Testcontainers 版本当前仓库gradle.properties中标注的版本为2.0.5 Gradlegroovy testImplementation org.testcontainers:testcontainers-k6:{{latest_version}} Mavenxml dependency groupIdorg.testcontainers/groupId artifactIdtestcontainers-k6/artifactId version{{latest_version}}/version scopetest/scope /dependency 该依赖位于modules/k6目录下其核心实现只有一个类K6Container.java继承自 Testcontainers 核心的GenericContainer因此天然具备 GenericContainer 的全部能力端口映射、等待策略、文件复制、日志输出等。核心 API 一览K6Container提供了三类构建方法用于描述一次 k6 测试执行方法作用内部实现要点withTestScript(MountableFile testScript)指定要在容器内执行的 k6 测试脚本将脚本文件复制到容器内/home/k6/脚本文件名参见 K6Container.javawithCmdOptions(String... options)追加 k6 命令行选项追加到最终命令的run之后参见 K6Container.javawithScriptVar(String key, String value)注入脚本变量供测试脚本通过__ENV访问以--env keyvalue形式加入命令参见 K6Container.java构造方式有两种new K6Container(grafana/k6:0.49.0)字符串镜像名或new K6Container(DockerImageName)。无论哪种方式构造时都会执行dockerImageName.assertCompatibleWith(K6_IMAGE)进行镜像兼容性校验传入非grafana/k6系列的镜像名会直接抛出异常从源头避免镜像用错的问题。脚本变量withScriptVar与 k6 的--env机制值得强调的是withScriptVar注入的“脚本变量”在底层并不是 Docker 环境变量而是 k6 命令行中的--env keyvalue参数见下方configure()源码。k6 会将这类参数以__ENV对象暴露给测试脚本例如脚本中的__ENV.MY_SCRIPT_VAR就能读取到对应的值。这与 Docker 容器的ENV是不同的概念但效果上都让测试脚本获得了可配置的输入。基本脚本执行完整示例原文档给出的完整用法摘录自 K6ContainerTests.java 的k6StandardTest测试如下K6Container container new K6Container(grafana/k6:0.49.0) .withTestScript(MountableFile.forClasspathResource(scripts/test.js)) .withScriptVar(MY_SCRIPT_VAR, are cool!) .withScriptVar(AN_UNUSED_VAR, unused) .withCmdOptions(--quiet, --no-usage-report); container.start();各调用含义new K6Container(grafana/k6:0.49.0)指定 k6 镜像版本示例使用0.49.0withTestScript(...)将 classpath 下的scripts/test.js复制进容器并作为待执行脚本withScriptVar(MY_SCRIPT_VAR, are cool!)向脚本注入变量MY_SCRIPT_VAR脚本内通过__ENV.MY_SCRIPT_VAR读取withCmdOptions(--quiet, --no-usage-report)追加 k6 运行选项分别用于减少输出冗余和关闭使用报告上报container.start()启动容器并开始执行 k6 测试。配套的 k6 测试脚本对应的测试脚本位于 modules/k6/src/test/resources/scripts/test.js这是 k6 最基本的脚本形态——一个default导出函数k6 会按配置反复执行它// The most basic of k6 scripts. export default function(){ console.log(k6 tests ${__ENV.MY_SCRIPT_VAR}) }脚本通过__ENV.MY_SCRIPT_VAR读取此前注入的脚本变量因此容器日志中会出现k6 tests are cool!这正好与测试中的断言assertThat(container.getLogs()).contains(k6 tests are cool!)相呼应形成“注入变量 → 脚本消费 → 日志断言”的闭环验证。等待测试结果WaitingConsumer由于容器启动后测试脚本是异步执行的Testcontainers 提供了WaitingConsumer来跟踪容器输出并等待目标结果出现。原文档给出的等待逻辑同样来自 K6ContainerTests.javaWaitingConsumer consumer new WaitingConsumer(); container.followOutput(consumer); // Wait for test script results to be collected consumer.waitUntil( frame - frame.getUtf8String().contains(iteration_duration), 3, TimeUnit.SECONDS );工作原理拆解container.followOutput(consumer)把容器的标准输出与错误输出订阅到WaitingConsumerconsumer.waitUntil(predicate, timeout, unit)阻塞等待直到某条输出帧包含目标关键字这里以 k6 指标输出中的iteration_duration迭代耗时指标作为“测试结果已产生”的信号等待超时上限为 3 秒超过则抛出超时异常。完成等待后即可通过container.getLogs()获取完整日志做进一步断言例如确认脚本变量注入生效。若需要输出到宿主机文件、按行解析或引入更复杂的条件等待WaitingConsumer与followOutput的组合还可进一步扩展相关输出能力与 GenericContainer 一脉相承可参考 core/src/main/java/org/testcontainers/containers/GenericContainer.java。源码级原理命令是如何组装的要真正理解K6Container关键在于其重写的configure()方法K6Container.java它负责在容器启动前把上述所有构建参数拼装成一条完整的 k6 命令Override protected void configure() { ListString commandParts new ArrayList(); commandParts.add(run); commandParts.addAll(cmdOptions); for (Map.EntryString, String entry : scriptVars.entrySet()) { commandParts.add(--env); commandParts.add(String.format(%s%s, entry.getKey(), entry.getValue())); } commandParts.add(testScript); setCommand(commandParts.toArray(new String[] {})); }从源码结构可以清晰看到命令的固定拼装顺序固定子命令runk6 的执行入口所有withCmdOptions追加的命令行选项如--quiet、--no-usage-report每个withScriptVar展开为一对--env与keyvalue最后是测试脚本在容器内的路径。也就是说上述示例最终在容器内执行的命令等价于k6 run --quiet --no-usage-report --env MY_SCRIPT_VARare cool! --env AN_UNUSED_VARunused /home/k6/test.js对应的脚本文件则经由withTestScript中的withCopyFileToContainer复制到容器/home/k6/目录下K6Container.java该路径正是官方 k6 镜像运行时的工作目录。测试中注入的AN_UNUSED_VAR虽然未被脚本引用也仍然会以--env形式传递不影响执行。使用建议与注意事项版本锁定grafana/k6镜像使用latest标签时行为可能漂移建议在K6Container构造参数中显式指定镜像版本如grafana/k6:0.49.0保证测试的可复现性孵化期 API 风险模块处于 incubating 阶段升级 Testcontainers 时需关注 CHANGELOG.md 中 k6 模块相关变更网络与镜像拉取首次运行需要从 Docker Hub 拉取 k6 镜像可结合 docs/supported_docker_environment/image_registry_rate_limiting.md 了解镜像拉取限流的影响与应对方式断言时机k6 输出会先打印配置与脚本加载信息再打印指标汇总务必使用WaitingConsumer或类似的输出等待机制等待iteration_duration等指标出现后再做断言避免竞态更复杂的负载场景withCmdOptions可以传入--vus、--duration、--iterations、--out等任意 k6 标准命令行参数从而在测试中直接控制虚拟用户数、时长与结果导出无需额外编写配置。延伸阅读模块核心实现modules/k6/src/main/java/org/testcontainers/k6/K6Container.java端到端测试示例modules/k6/src/test/java/org/testcontainers/k6/K6ContainerTests.java测试脚本样例modules/k6/src/test/resources/scripts/test.jsTestcontainers 模块总览docs/modules/index.mdk6 文档见 docs/modules/k6.md孵化模块政策docs/contributing.md#incubating-modules【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进