- 测试
- 云原生
- 质量保障
【免费下载链接】origin
Conformance test suite for OpenShift
在 origin(OpenShift 的 Conformance 测试套件仓库)中,test/extended/目录承载着一套基于 Ginkgo/Gomega 的功能级扩展测试(extended tests)。这些测试通过程序化调用ocCLI 和 Kubernetes/OpenShift 客户端来验证构建、镜像、OAuth、路由等核心功能。读完本文,你将掌握 extended 测试的运行方式、测试标签规范、目录组织结构、独立测试组启动器的创建方法,以及如何用exutil.CLI在 Ginkgo 用例中精确模拟oc命令并断言结果。
一、前置条件
按照 test/extended/README.md 的说明,开发 extended 测试前需要满足两个前提:
- 在仓库中同时编译
oc与openshift-tests两个命令行工具:
$ make WHAT=cmd/openshift-tests- 设置环境变量
KUBECONFIG,使其指向你要测试的目标集群:
$ export KUBECONFIG=/path/to/kubeconfigopenshift-tests的入口源码位于 cmd/openshift-tests/openshift-tests.go,其子命令实现分散在pkg/cmd/openshift-tests/下,例如run、list、monitor、disruption等目录,覆盖了运行测试、列出套件、监控测试、扰动测试等场景。
二、运行 Extended 测试
按全名运行单个测试
$ openshift-tests run-test <FULL_TEST_NAME>查看可用套件列表
$ openshift-tests help run具体的测试前置依赖(prerequisites)会写在各测试的描述文字中,运行前先阅读被测用例的 Description。
用正则过滤子集运行
官方推荐的做法是先把全量测试列表以 dry-run 方式打印出来,再用grep -E过滤后通过-f -从标准输入喂给运行器:
$ openshift-tests run all --dry-run | grep -E "<REGEX>" | openshift-tests run -f -这种方式适合在本地只跑与某功能相关的测试子集,而不改动 CI 配置。
三、测试标签(Test Labels)规范
extended 测试的标签体系与 Kubernetes e2e 测试的标签约定一致(README 中引用了 k8s 社区的 e2e-tests 标签说明文档)。核心规则如下:
| 标签 | 含义与使用条件 |
|---|---|
| 无标签 | 测试应快速完成(5 分钟内)、可并行运行且结果一致 |
[Serial] | 不能与其他测试并行(例如占用大量资源或重启节点),必须作为独立套件串行运行 |
[Slow] | 单独或并行运行超过 5 分钟。把慢测试分到独立分区,可以让绝大多数测试快速并行跑完。特别注意:凡是涉及构建(builds)的 OpenShift extended 测试都应标记[Slow] |
[Conformance] | 覆盖集群核心关键功能且不与其它 conformance 测试重复覆盖的用例才算有效。README 给出的正例是“构建能否工作(Do builds work)”,反例是“设置 forcePull 标志后构建能否工作”——后者属于特殊配置,不属于 conformance |
[local] | 需要访问测试机本地资源(例如使用 docker socket)的测试;原则上 extended 测试应避免访问本地宿主,无法避免时才打此标签 |
四、Extended 测试的目录结构
扩展测试统一位于 test/extended/ 目录,其组织结构为:
- test/extended/util:提供 extended 测试共用的辅助函数与工具。它封装了对 OpenShift CLI 的易用接口(前文提到的
exutil),同时提供对 Kubernetes E2E framework 的访问,以及跨多个测试用例共享的 OpenShift 辅助逻辑,让测试用例保持 DRY。其核心文件 test/extended/util/client.go 定义了CLI类型。 - test/extended/testdata:存放 extended 测试用到的 JSON/YAML 等 fixture 文件(当前约 400 个 manifest 文件)。
- test/extended/[images,builds,...]:每个 Go 包包含一组相关联的 extended 测试。例如
images目录存放验证容器镜像使用场景的用例,builds存放构建相关用例。
从当前仓库实际目录看,除了util与testdata,还有apiserver、authentication、authorization、builds、etcd、networking、oauth、operators、router、storage等数十个功能包,每个包对应一类被测功能域。
五、包(Package)与测试组(Group)的区别
README 给出的组织原则是:每一类功能测试都应当放在自己的 Go 包里;但如果你的测试包需要以不同于标准路径的方式专门配置服务端,则要在test/extended目录下创建一个与包同名的 launcher 脚本(shell 启动器)。
典型的例子是 LDAP 认证测试:你需要先把 OpenShift server 配置成启用 LDAP 认证,才能测认证流程。做法是:
- 新建测试组
ldap,并提供 shell 启动器./test/extended/ldap.sh,用于以所需配置启动 OpenShift; - 把测试源码放到对应功能包的 Go 目录下,例如
./test/extended/ldap; - 在顶层 suite 上给你的用例加组前缀:
var _ = g.Describe("[ldap] Authenticate using LDAP", func() { # ... })创建新的测试组 Runner
如果你的测试需要与其它 extended 用例不同的配置,应在test/extended下新建执行脚本,并注意用 Ginkgo 的 focus 机制只选中你自己的测试。如果你的测试无法作为默认组的一部分运行,务必确保该包不被test/extended的默认入口包含。
当前仓库中仍保留了这种 shell runner 的范例——test/extended/cmd.sh。它演示了一个完整的组 runner 生命周期:
source "$(dirname "${BASH_SOURCE}")/../../hack/lib/init.sh" os::util::environment::setup_time_vars os::build::setup_env # 以默认配置启动 OpenShift server(无 registry/router) os::util::environment::use_sudo os::cleanup::tmpdir os::util::environment::setup_all_server_vars os::start::configure_server os::start::server export KUBECONFIG="${ADMIN_KUBECONFIG}" # 注册 junit suite 并执行 oc 命令断言 os::test::junit::declare_suite_start "extended/cmd/new-app" os::cmd::expect_success "oc new-app test/scratchimage~https://github.com/openshift/ruby-hello-world.git --strategy=docker" ... os::test::junit::declare_suite_end可以看到 launcher 脚本负责环境准备(setup_env、use_sudo)、服务端配置与启动(configure_server、server),并用os::test::junit::declare_suite_start/end向 JUnit 报告注册测试套件;测试断言则大量使用os::cmd::expect_success_and_text、os::cmd::try_until_text等对oc命令输出做正则验证的封装。
Bash 辅助函数
README 指出 extended 测试的通用函数位于./hack/util.sh,环境设置脚本位于 hack/lib/util/environment.sh,主要函数包括:
| 函数 | 作用 |
|---|---|
ginkgo_check_extended() | 检查 Ginkgo 二进制是否已安装 |
compile_extended() | 将 Go 测试编译为测试二进制 |
test_privileges() | 校验是否有权限启动 OpenShift server |
os::util::environment::setup_all_server_vars() | 设置 OpenShift server 所需的全部环境变量 |
os::start::configure_server() | 生成 OpenShift server 的所有配置文件 |
os::start::server() | 启动 OpenShift master 与 node |
os::start::router() | 安装 OpenShift 路由服务 |
os::start::registry() | 安装 OpenShift 容器镜像 registry 服务 |
create_image_streams_extended() | 为所有 OpenShift 镜像创建 ImageStream |
从源码结构看,os::util::environment::setup_all_server_vars的实际定义在 hack/lib/util/environment.sh,os::start::configure_server与os::start::server定义在 hack/lib/start.sh——configure_server会生成 master 证书、node 配置与 OpenShift 配置,server则启动服务并等待端点可用。编写 launcher 时直接source这些库即可复用整套启动流程。
六、CLI 接口:在测试中模拟 oc 命令
extended 测试的核心能力是通过exutil.CLI(包路径 test/extended/util/client.go)调用 OpenShift CLI 与 Kubernetes/OpenShift 客户端,从而在 Ginkgo 用例中模拟oc命令。
顶层 Describe 中创建 CLI 实例
要在测试套件中模拟oc命令,必须先创建 CLI 实例,且应放在顶层 GinkgoDescribe容器中。顶层 Describe 的标签需要同时给出测试所属的 bucket 与简短描述,其它全局可访问变量(如 fixtures)也在此声明:
package extended import ( g "github.com/onsi/ginkgo/v2" o "github.com/onsi/gomega" ) var _ = g.Describe("[<test bucket>] <Testing scenario>", func() { defer g.GinkgoRecover() var ( oc = exutil.NewCLI("test-name") testFixture = filepath.Join("testdata", "test.json") ) })测试套件应进一步组织为更下层的Describe容器,用消息描述测试目标;每个下层容器内用单个It承载具体 spec,It共享上下文并说明如何达成测试目标:
var _ = g.Describe("[default] STI build", func() { defer GinkgoRecover() var ( stiBuildFixture = filepath.Join("testdata", "test-build.yaml") oc = exutil.NewCLI("build-sti", kubeConfigPath()) ) g.Describe("Building from a template", func() { g.It(fmt.Sprintf("should create a image from %q template", filepath.Base(stiBuildFixture)), func() { ... } } }源码层面,NewCLI() 会基于给定的 namespace 名称初始化 CLI 及 Kube framework 辅助结构,并注册g.BeforeEach(cli.SetupProject)在每条用例前创建项目、g.AfterEach(cli.TeardownProject)在用例后回收项目,因此测试用例无需自行管理项目生命周期。从 NewCLIWithoutNamespace() 的实现看,底层framework.Framework默认使用ClientQPS: 20、ClientBurst: 50的客户端限流参数,execPath固定为oc,kubeconfig 路径取自KubeConfigPath()——这与前置条件中要求设置KUBECONFIG环境变量相呼应。
命令动词与参数:Run / Args / Template
模拟oc命令时,先用Run()指定命令动词(get、create、start-build等),再用Args()追加参数,方法可以自由链式调用:
oc = oc.Run("create")oc = oc.Run("create").Args("-f", testFixture)Template()方法可给 CLI 命令附加 Go 模板参数,但前提是Run()中指定了get动词:
oc = oc.Run("get").Args("foo").Template("{{ .spec }}")它等价于命令行执行:
$ oc get foo -o template --template='{{ .spec }}'执行与断言:Execute / Output / By / Expect
执行命令有两种方式:Execute()执行命令并返回过程中发生的错误;Output()除返回错误外还返回命令输出:
err := oc.Run("create").Args("-f", testFixture).Execute()buildName, err := oc.Run("start-build").Args("test").Output()用 Ginkgo 的By函数打印下一组命令的意图,使测试日志可读:
g.By("starting a test build") buildName, err := oc.Run("start-build").Args("test").Output()用 Gomega 的Expect语法对错误做断言:
err = oc.Run("create").Args("-f", stiEnvBuildFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred())CLI类型本身的字段设计也印证了这一接口语义:从 client.go 中的结构体定义看,CLI分别维护verb(命令动词)、globalArgs、commandArgs、finalArgs(最终拼接参数)、stdin/stdout/stderr(进程标准流)以及adminConfigPath(kubeconfig)等字段,Run()/Args()只是往这些字段累积状态,真正的进程执行发生在Execute()/Output()调用时(源码中对应Run于 L984、Args于 L1032、Output于 L1048、Execute于 L1158 的实现)。此外CLI还提供了KubeFramework()访问 Kubernetes framework 助手、SetupProject()/TeardownProject()管理项目,以及NewCLIWithFramework()、NewHypershiftManagementCLI()等针对不同场景(绑定已有 framework、Hypershift 管理集群)的构造方式,编写特殊场景测试时可按需选用。
七、小结:一个新 Extended 测试的完整流程
综合以上内容,向 origin 仓库提交一个新 extended 测试的标准路径是:
- 确认测试归属的功能域,将用例放入对应的 Go 包(如
test/extended/builds/),fixture 放入 test/extended/testdata; - 若需要特殊服务端配置,在
test/extended/下新增同名 launcher 脚本,复用hack/lib中的环境与服务启动函数,并用 Ginkgo focus 圈定本组用例; - 在顶层
Describe中声明 bucket 前缀并创建exutil.NewCLI实例,按Run/Args/Template构造命令,用Execute/Output执行、o.Expect断言; - 按标签规范决定是否加
[Serial]、[Slow]、[Conformance]、[local]标签,避免慢测试拖慢并行分区; - 本地用
openshift-tests run-test <FULL_TEST_NAME>或正则过滤子集验证通过后再提交。
- 测试
- 云原生
- 质量保障
【免费下载链接】origin
Conformance test suite for OpenShift
相关推荐
OrcaSlicer 测试套件实战指南:Catch2 测试的组织、编写与构建运行全解析
OrcaSlicer 测试套件实战指南:Catch2 测试的组织、编写与构建运行全解析 本篇技术指南以 OrcaSlicer 仓库 tests/ 目录下的测试工
桌面应用3D渲染图形学Quick 测试组织指南:用 Example 与 Example Group 编写结构化测试
Quick 测试组织指南:用 Example 与 Example Group 编写结构化测试 本文是 Quick(Swift / Objective C 行为驱
测试开发工具Johnny-Five 扩展测试(Extended Tests)机制解析:时间敏感测试的隔离、编写与运行
Johnny Five 扩展测试(Extended Tests)机制解析:时间敏感测试的隔离、编写与运行 导读 Johnny Five 是面向 Arduino
IoT机器人嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考