helm 单元测试
使用YAML为_helm chart_编写单元测试,保持您的chart一致性和稳健性!
特性:
- 使用纯YAML编写测试文件
- 本地渲染
- 在集群上不创建任何内容
- 模板的通配符选择
- 定义值和发布选项
- 快照测试
- 测试套件代码补全和验证
文档
如果您准备编写测试,请查看文档了解YAML中的测试API。
安装
$ helm plugin install https://github.com/helm-unittest/helm-unittest.git
它将安装最新版本的二进制文件到helm插件目录。
Docker用法
# 运行最新helm与最新helm unittest插件的帮助
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest
# 运行特定helm版本与特定helm unittest插件版本的帮助
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest:3.11.1-0.3.0
# 运行helm 3 chart的单元测试
# 确保将本地文件夹挂载到容器的/apps
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest:3.11.1-0.3.0 .
# 运行helm 3 chart的单元测试,并输出Junit格式用于CI验证
# 确保将本地文件夹挂载到容器的/apps
# test-output.xml将在本地文件夹中可用
docker run -ti --rm -v $(pwd):/apps helmunittest/helm-unittest:3.11.1-0.3.0 -o test-output.xml -t junit .
Docker容器包含完全安装的helm客户端,包括helm-unittest插件。
入门
在chart的.helmignore中添加tests
,并在$YOUR_CHART/tests/deployment_test.yaml
创建以下测试文件:
suite: 测试部署
templates:
- deployment.yaml
tests:
- it: 应该正常工作
set:
image.tag: latest
asserts:
- isKind:
of: Deployment
- matchRegex:
path: metadata.name
pattern: -my-chart$
- equal:
path: spec.template.spec.containers[0].image
value: nginx:latest
然后运行:
$ helm unittest $YOUR_CHART
现在你有了第一个测试!;)
测试套件文件
测试套件文件使用纯YAML编写,默认放在chart的tests/
目录下,文件名后缀为_test.yaml
。您也可以使用cli的-f, --file
选项设置测试套件文件相对于chart目录的glob模式,来自定义套件文件布局,例如:
$ helm unittest -f 'my-tests/*.yaml' -f 'more-tests/**/*.yaml' my-chart
查看文档了解更多编写测试的详细信息。
模板化测试套件
您可能会发现需要设置大量测试,这些测试是单个测试的参数化。例如,假设您部署到3个环境env = dev | staging | prod
。
为此,您实际上也可以将测试编写为helm chart。如果您采用这种方式,必须设置--chart-tests-path
选项。设置后,helm unittest将针对您指定目录中的values.yaml运行标准helm渲染。
/my-chart
/tests-chart
/Chart.yaml
/values.yaml
/templates
/per_env_snapshots.yaml
/Chart.yaml
/values.yaml
/.helmignore
/templates
/actual_template.yaml
在上面的示例文件结构中,您将维护一个helm chart,该chart将根据提供的Chart.yaml和values.yaml进行渲染。对于渲染的charts,任何生成的测试套件都会自动运行,我们不寻找文件后缀或glob。
注意: 由于您可以在单个模板文件中创建多个套件,因此必须提供套件名称,因为我们不能再有意义地使用测试套件文件名。
注意2: 由于您可以针对子charts和多个charts运行,因此需要确保不要将--chart-tests-path
指定为与其他测试相同的文件夹。这是因为我们会尝试渲染那些非helm测试文件夹并在单元测试期间失败。
注意3: 对于快照测试,您需要提供一个helm ignore,忽略*/__snapshot__/*
。否则,后续运行将尝试渲染这些快照。
上述chart和测试配置的命令将是:
helm unittest --chart-tests-path tests-chart my-chart
用法
$ helm unittest [flags] CHART [...]
这将本地渲染您的charts(无需tiller),并运行测试套件文件中定义的测试。
标志
--color 强制打印彩色输出,即使stdout不是tty。设置为false以禁用颜色
--strict 严格解析测试套件(默认为false)
-d --debugPlugin 启用调试日志记录(默认为false)
-v, --values stringArray 覆盖helmchart值的值文件的绝对路径或glob路径
-f, --file stringArray 测试文件位置的glob路径,默认为tests\*_test.yaml (默认 [tests\*_test.yaml])
-q, --failfast 测试失败时直接退出测试(默认为false)
-h, --help unittest的帮助
-t, --output-type string 写入测试结果的文件格式,接受的类型为(JUnit, NUnit, XUnit)(默认为XUnit)
-o, --output-file string 写入指定格式测试结果的文件,默认不将输出写入文件
-u, --update-snapshot 如果需要,更新缓存的快照,请确保在更新之前查看更改
-s, --with-subchart charts 包括charts文件夹内子charts的测试(默认为true)
--chart-tests-path string 相对于chart的文件夹位置,用于渲染测试套件的helm chart所在位置
YAML JsonPath支持
现在支持针对映射和数组的JsonPath。
这使得可以基于JsonPath在数组中查找项目。
有关jsonPath
语法的更多详细信息。
由于更改为JsonPath,现在支持path
中包含句点(.
)或特殊字符(/
)的map键,使用""
:
- equal:
path: metadata.annotations["kubernetes.io/ingress.class"]
value: nginx
在下一个版本中,当JsonPath结果为多个结果时,将可以验证多个路径。
DocumentSelector
测试作业或断言也可以指定documentSelector而不是documentIndex。请注意,如果找到匹配项,documentSelector将始终覆盖documentIndex。当helm生成多个模板且顺序不能保证时,此字段特别有用。
documentSelector中的path
支持YAML JsonPath,使用JsonPath表达式可以过滤多个字段。
documentSelector中的value
可以验证完整的yaml对象。
...
tests:
- it: 应该通过
values:
- ./values/staging.yaml
set:
image.pullPolicy: Always
resources:
limits:
memory: 128Mi
template: deployment.yaml
documentSelector:
path: metadata.name
value: my-service-name
asserts:
- equal:
path: metadata.name
value: my-deploy
示例
查看 test/data/v3/basic/
目录获取一些简单图表的基本用例。
快照测试
有时你可能只想在变更之间保持渲染的清单不变,而无需断言每个细节。这就是快照测试的原因!查看以下测试:
templates:
- templates/deployment.yaml
tests:
- it: pod规格应该匹配快照
asserts:
- matchSnapshot:
path: spec.template.spec
# 或者你可以对整个清单进行快照
- it: 清单应该匹配快照
asserts:
- matchSnapshot: {}
matchSnapshot
断言验证渲染的内容与上次缓存的内容相同。如果内容发生变化,它会失败,你应该使用 CLI 的 -u, --update-snapshot
选项检查并更新缓存。
$ helm unittest -u my-chart
缓存文件存储为 __snapshot__/*_test.yaml.snap
,位于测试文件所在的目录,你应该将它们与图表一起添加到版本控制中。
依赖子图测试
如果你在 charts
目录中有硬依赖子图(通过 helm dependency
安装,它们不需要被提取),可以从根图表对这些子图进行单元测试。这个功能可以帮助验证默认的 helm 图表中是否意外覆盖了良好的默认值。
# $YOUR_CHART/tests/xxx_test.yaml
templates:
- charts/postgresql/templates/xxx.yaml
tests:
- it:
set:
# 这次需要加上 "postgresql." 前缀
postgresql.somevalue: should_be_scoped
asserts:
- ...
注意1:如果依赖子图使用别名,请在模板中使用别名。 注意2:在模板中使用文件夹结构也可以用于对放置在子文件夹中的模板进行单元测试,或从根图表对子图进行单元测试。
查看 test/data/v3/with-subchart/
作为示例。
子图内的测试
如果你在 charts
目录中有自定义的硬依赖子图(不是通过 helm dependency
安装,而是手动添加),默认情况下也会执行其中的测试。你可以通过在 CLI 中设置 --with-subchart=false
标志来禁用此行为,从而只执行根图表中的测试。请注意,子图测试中定义的值将自动作用域化,你不需要自己添加依赖作用域:
# with-subchart/charts/child-chart/tests/xxx_test.yaml
templates:
- templates/xxx.yaml
tests:
- it:
set:
# 不需要加上 "child-chart." 前缀
somevalue: should_be_scoped
asserts:
- ...
查看 test/data/v3/with-subchart/
作为示例。
测试套件代码补全和验证
大多数流行的 IDE(IntelliJ、Visual Studio Code 等)支持使用 JSON Schema 将 schema 应用到 YAML 文件。这在编辑测试套件文件时提供了全面的文档以及代码补全:
此外,在编辑时可以对测试套件文件进行验证,以便在编辑时检测错误添加的附加属性或不正确的数据类型:
Visual Studio Code
使用 VSCode 开发时,非常流行的 YAML 插件(由 RedHat 创建)允许通过在文件顶部添加注释行来添加对 schema 的引用:
# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json
suite: http-service.configmap_test.yaml
templates: [configmap.yaml]
release:
name: test-release
namespace: TEST_NAMESPACE
或者,你可以使用定义良好的模式将 schema 全局添加到 IDE:
"yaml.schemas": {
"https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json": ["charts/*/tests/*_test.yaml"]
}
IntelliJ
与 VSCode 类似,IntelliJ 允许通过首选项将文件模式映射到 schema:语言和框架 -> Schema 和 DTD -> JSON Schema 映射
常见问题
随着越来越多的人使用单元测试插件,会出现更多问题。因此创建了一个常见问题页面来回答最常见的问题。
如果你发现缺少对某个问题的回答,请随时提出问题。
相关项目/命令
这个插件受到 helm-template 的启发,快照测试的想法和一些打印格式来自 jest。
还有一些你可能想要使用的其他 helm 命令:
-
helm template
:渲染图表并打印输出。 -
helm lint
:检查图表中可能存在的问题,对验证图表依赖关系很有用。 -
helm test
:使用图表中定义的测试 pod 测试发布。请注意,这确实会在集群上创建资源以验证你的发布是否正确。查看文档。
或者,你也可以使用通用测试框架:
许可证
MIT
贡献
欢迎提出问题和 PR! 在开始开发这个插件之前,你必须安装 Go >= 1.21,并运行:
git clone git@github.com:helm-unittest/helm-unittest.git
cd helm-unittest
请确保在请求 PR 时通过 CI,它将检查以下内容:
gofmt
不需要更改。请在提交之前运行gofmt -w -s .
。go test ./pkg/unittest/...
通过。
在某些情况下,你可能需要手动修复 *_test.go
中的测试。如果快照测试(插件的测试代码)失败,你需要运行:
UPDATE_SNAPSHOTS=true go test ./...
这会更新快照缓存文件,请在提交之前添加它们。