从k8s的e2e测试中使用ginkgo
本篇博客将分析k8s e2e(端到端测试的)流程,从而实际的说明ginkgo的使用方法
Ginkgo测试框架
ginkgo作为k8s本身的测试框架对gotest进行了进一步的封装。支持测试用例的并行,串行,充实,过滤等等机制。下面简单介绍一下ginkgo的相关概念。
核心概念
- suite: 一整个测试工程,测试工程包含很多测试用例(spec)
- spec: 一个测试用例,通常表现为
1
2It("description", func{
实际的测试逻辑}) - container node: 组织spec的层级系统,spec类似于文件而container node类似于文件夹。具体有如下几类。当然这些container node在用法上没什么不同,只是名字不一样。用来提示在测试过程走到了那个分支
- Describe
- Context
- When
- setup node:在实际执行spec/suite之前或者之后的操作过程,具体有如下几类:
- BeforeEach
- JustBeforeEach
- BeforeSuite
- AfterEach
- JustAfterEach
- AfterSuite
- subject nodes:具体的spec测试用例
下面是一个典型的包含各种node和spec的样例
1 | func TestExample(t *testing.T) { |
建树和运行阶段
gingkgo将执行测试分为两个阶段,构建树(决定节点的执行顺序,可以理解为编译)以及实际运行节点。下面是两阶段的具体说明
- Tree Construction Phase(构建树阶段)
- Ginkgo 会解析所有 Describe、Context、When、It 等声明,注册所有节点,把它们组织成一棵测试树
- 该阶段发生于go test运行时,实际执行测试之前,在这个阶段,不会执行实际的测试逻辑,只是建立测试结构
- Run Phase (运行阶段)
- Ginkgo假设所有spec是独立的,这是并行运行测试,随机运行测试的基础
- 由于spec是独立的,故而当spec测试抛出错误时则立即中止,执行其他的spec
- Ginkgo使用修饰符(如Ordered、Serial,Flake,Filtering,Timeout等)来进行spec运行的串行化,重试,过滤,中断与超时机制的实现,例如如下的样例实现了再并行spec运行过程中某一进程串行运行spec的过程
K8s gingko framework
K8s e2e 对ginkgo做出一次封装,写了自己的framework。该framework拓展了如下的功能
- 针对每个测试spec(此部分由framework维护)
- 自动管理对k8s集群的链接(k8s e2e是使用集群外部来控制集群的测试过程,所以要对目标k8s集群进行链接)
- 创建并回收命名空间(譬如测试schedule的相关功能,则会创建一个k8s-e2e-schedule[名称可能不准确]的ns,在这个ns中进行测试)
- 针对整个e2e测试套件suite(此部分由testcontext维护)
- 重定向k8log至GinkgoWriter,整合错误日志
- 设置 Gomega 的默认超时和轮询间隔
- 检测集群配置并生成Beartoken
- 设置云提供商配置
- 设置报告目录和 并输出Json 报告
- 针对k8s各个模块做了测试方法的封装(譬如创建pod,volume,进行网络联通测试等)。
代码在这里
下面将以代码中schedule这一个组件(或者说功能)来进行framework的解释。先来看看这个文件夹中都测了点啥吧
- predicate测试:本地临时存储资源限制测试,Pod 开销计算测试,NodeAffinity 不匹配测试,NodeAffinity 匹配测试,NodeAffinity 匹配测试,Taints-Tolerations 不匹配测试,HostPort 冲突测试,Pod 拓扑分布测试,SchedulingGates 测试
- priority测试:Pod 反亲和性调度测试,Pod 容忍度优先级测试,Pod 拓扑分布评分测试
- preemption测试: Pod 中断条件验证测试,Pod 拓扑分布抢占测试,抢占执行路径测试,PriorityClass 端点测试
- limit_range测试:LimitRange 默认值应用测试,LimitRange 集合操作测试
- nvdia-gpu测试:基础 NVIDIA GPU 设备插件测试,GPU 设备插件节点重建测试
下面介绍一下framework是怎么拉起测试的
- 在framework中解析命令行参数,大部分ginkgo 测试都会以
ginkgo test -flags来进行,这些flags掌控了测试的细节 - 根据这些命令行参数初始化testcontext,testcontext维护整个e2e测试框架的具体参数
- 进入reportBeforeSuite节点,该节点指定并初始化report模块的功能
- 主测试函数所在文件通过导入schedule包从而自动注册schdule包下的container和context节点
- 针对每套测试,这里就是指上述的predicate、priorty…的测试。都初始化framework,设置并创建namespace,连接目标集群
- 执行测试点
- 测试点执行完毕,执行reportAfterEach节点,收集信息
- framework将namespace 清理并删除
- 执行reportAfterSuite节点,输出测试结果
K8s e2e 测试流程
在上面的介绍中我们知道了k8s是如何执行e2e 测试的。但我们还需要关心k8s是如何发起e2e测试,以及测试完成之后的种种处理。
简单来说,在提交pr至k8s仓库时会自动触发e2e测试流程
具体的流程如下
- 提交 RR 到 kubernetes
- Prow 监听到 PR webhook
- Prow 触发 pre-submit Job(如 pull-kubernetes-e2e-kind
- Job 执行测试脚本:
- 在目标集群中创建 Pod,在 Pod 内使用 DIND 启动 kind 集群
- 执行 e2e-k8s.sh 脚本,该脚本完成编译 e2e.test,启动 kind 集群,执行 E2E 测试
- 测试开始执行:ginkgo-e2e.sh
- 使用 Ginkgo 运行 test/e2e/**.go 中的测试用例
- 示例测试包括 DNS、Pod 创建、Deployment 滚动更新等
- job测试通过,等待approver和reviewer审批后由Tide合并;失败则通过 bot 注释反馈 GitHub。
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.



