Kubernetes e2e test and test framework
前言
Kubernetes的成功少不了大量工程师的共同参与,而他们之间如何高效的协作,非常值得我们探究。最近研究和使用了他们的e2e测试和框架,还是挺有启发的。
怎样才是好的e2e测试?
不同的人写出的测试用例千差万别,尤其在用例,可能由开发人员编写的情形下,其情形可想而知。要知道,绝大多数开发人员,可能并没有经历过大量测试用例场景的熏陶。所以如何持续输出高质量的e2e测试用例,确实是一个挑战。不过,Kubernetes社区非常聪明,他们抽象出来了一些共性的东西,来希望大家遵守。比如说
- 拒绝“flaky”测试 - 也就是那些偶尔会失败,但是又非常难定位的问题。
- 错误输出要详细,尤其是做断言时,相关信息要有。不过也不要打印太多无效信息,尤其是在case并未失败的情况。
- make case run in anywhere。这一点很重要,因为你的case是提交到社区,可能在各种环境下,各种时间段内运行。面对着各种cloud provider,各种系统负载情况。所以你的case要尽可能稳定,比如APICall,能异步的,就不要假设是同步; 比如多用retry机制等。
- 测试用例要执行的足够快。超过两分钟,就需要给这种测试打上[SLOW]标签。而有这种标签的测试用例,可以运行的场景就比较有限制了。谁又不希望自己写的用例都被尽可能的执行呢?很有激励性的一条规则。
另外,社区不过定下规则,还开发和维护了一系列的基础设施,来辅助上面规则的落地。我们接下来要讲的e2e框架就是其中之一。
e2e 验收测试
搞过测试的应该都知道,在面对复杂系统测试时,我们通常有多套测试环境,但是测试代码通常只有一份。所以为了能更好的区分测试用例,通常采取打标签的方式来给用例分类。这在Kubernetes的e2e里,这也不例外。
Kubernetes默认将测试用例分为下面几类,需要开发者在实际开发用例时,合适的使用。
- 没标签的,默认测试用例是稳定的,支持并发,且运行足够快的
- [Slow] 执行比较慢的用例.(对于具体的时间阈值,Kubernetes不同的文档表示不一致,此处需要修复)
- [Serial] 不支持并发的测试用例,比如占用太多资源,还比如需要重启Node的
- [Disruptive] 会导致其他测试用例失败或者具有破坏性的测试用例
- [Flaky] 不稳定的用例,且很难修复。使用它要非常慎重,因为常规CI jobs并不会运行这些测试用例
- [Feature:.+] 围绕特定非默认Kubernetes集群功能或者非核心功能的测试用例,方便开发以及专项功能适配
当然除了以上标签,还有个比较重要的标签就是[Conformance], 此标签用于验收Kubernetes集群最小功能集,也就是我们常说的MAT测试。所以如果你有个私有部署的k8s集群,就可以通过这套用例来搞验收。方法也很简单,通过下面几步就可以执行:
# under kubernetes folder, compile test cases and ginkgo tool
make WHAT=test/e2e/e2e.test && make ginkgo
# setup for conformance tests
export KUBECONFIG=/path/to/kubeconfig
export KUBERNETES_CONFORMANCE_TEST=y
export KUBERNETES_PROVIDER=skeleton
# run all conformance tests
go run hack/e2e.go -v --test --test_args="--ginkgo.focus=\[Conformance\]"
注意,kubernetes的测试使用的镜像都放在GCR上了,如果你的集群在国内,且还不带翻墙功能,那可能会发现pod会因为下载不了镜像而启动失败。
Kubernetes e2e test framework
研究Kubernetes的e2e测试框架,然后类比我们以往的经验,个人觉得,下面几点特性还是值得借鉴的:
All e2e compiled into one binary, 单一独立二进制
在对服务端程序进行API测试时,我们经常会针对每个服务都创建一个ginkgo suite来框定测试用例的范围,这样做的好处是用例目标非常清晰,但是随着服务数量的增多,这样的suite会越来越来多。从组织上,看起来就稍显杂乱,而且不利于测试服务的输出。
比如,我们考虑这么一个场景,QA需要对新机房部署,或者私有机房进行服务验证。这时候,就通常需要copy所有代码到指定集群在运行了,非常的不方便,而且也容易造成代码泄露。
kubernetes显然也会有这个需求,所以他们改变写法,将所有的测试用例都编译进一个e2e.test的二进制,这样针对上面场景时,就可以直接使用这个可执行文件来操作,非常的方便。
当然可执行文件的方便少不了外部参数的自由注入,以及整体测试用例的精心标记。否则,测试代码写的不规范,需要频繁的针对特定环境修改,也是拒不方便的。
Each case has a uniqe namespace, 每个case拥有唯一的空间
为每条测试用例创建一个独立的空间,是kubernetes e2e framework的一大精华。每条测试用例独享一个空间,彼此不冲突,从而根本上避免并发困扰,借助ginkgo的CLI来运行,会极大的提高执行效率。
而且这处代码的方式也非常优美,很有借鉴价值:
func NewFramework(baseName string, options FrameworkOptions, client clientset.Interface) *Framework {
f := &Framework{
BaseName: baseName,
AddonResourceConstraints: make(map[string]ResourceConstraint),
Options: options,
ClientSet: client,
}
BeforeEach(f.BeforeEach)
AfterEach(f.AfterEach)
return f
}
利用ginkgo 的BeforeEach的嵌套特定,虽然在Describe下就定义framework的初始化(如下),但是在每个It执行前,上面的BeforeEach才会真正执行,所以并不会有冲突:
var _ = framework.KubeDescribe("GKE local SSD [Feature:GKELocalSSD]", func() {
f := framework.NewDefaultFramework("localssd")
It("should write and read from node local SSD [Feature:GKELocalSSD]", func() {
...
})
})
当然e2e框架还负责case执行完的环境清理,并且是按需灵活配置。比如你希望,case失败保留现场,不删除namespace,那么就可以设置flag 参数 delete-namespace-on-failure为false来实现。
Asynchronous wait,异步等待
几乎所有的Kubernetes操作都是异步的,所以不管是产品代码还是测试用例,都广泛的使用了这个异步等待库:kubernetes/vendor/k8s.io/apimachinery/pkg/util/wait。这个库,实现简单,精悍,非常值得学习。
另外,针对测试的异步验证,其实ginkgo(gomega)本身提供的Eventualy,也是非常好用的。
Suitable logs,打印合适的log
Kubernetes e2e 主要使用两种方式输出log,一个是使用glog库,另一个则是framework.Logf方法。glog本身是golang官方提供的log库,使用比较灵活。但是这里主要推荐的还是Framework.Logf。因为使用此方法的log会输出到GinkgoWriter里面,这样当我们使用ginkgo.RunSpecsWithDefaultAndCustomReporters方法时,log不光输出到控制台,也会保存在junit格式的xml文件里,非常方便在jenkins里展示测试结果。
Clean code, 测试代码也可以很干净,优美
很多时候大家会觉得测试代码比较low,其实却不然。代码无所谓优劣,好坏还是依赖写代码的人。而且我想说,测试代码也是可以,并且应该写的很优美的,不然如何提升逼格?!。
我们从Kubernetes e2e能看到很多好的借鉴,比如:
- 抽取主干方法,以突出测试用例主体
- 采用数据驱动方式书写共性测试用例
- 注释工整,多少适宜
- 不输出低级别log
- 代码行长短适宜
- 方法名定义清晰,可读性强
Kubernetes环境普适性的e2e测试框架
现实中,如果需要围绕k8s工作,你可能需要一套,自己的测试框架。不管是测试各种自定义的controller or watcher,还是测试运行在k8s里运行的私有服务。这套框架都适用于你:
https://github.com/CarlJi/golearn/tree/master/src/carlji.com/experiments/k8s_e2e_mat_framework
逻辑改动很小,只是在原有kubernetes e2e 框架基础上抽取了最小集合。以方便快速使用。
是不是很贴心?
童鞋,点个赞吧(⊙o⊙)?
参考文档
- https://github.com/thtanaka/kubernetes/blob/master/docs/devel/writing-good-e2e-tests.md
- https://github.com/thtanaka/kubernetes/blob/master/docs/devel/e2e-tests.md
Contact me ?
Email: jinsdu@outlook.com
Blog: http://www.cnblogs.com/jinsdu/
Github: https://github.com/CarlJi
Kubernetes e2e test and test framework的更多相关文章
- kubernetes高级之动态准入控制
系列目录 动态准入控制器文档介绍了如何使用标准的,插件式的准入控制器.但是,但是由于以下原因,插件式的准入控制器在一些场景下并不灵活: 它们需要编译到kube-apiserver里 它们仅在apise ...
- kube-scheduler的调度上下文
前一章节了解到了kube-scheduler中的概念,该章节则对调度上下文的源码进行分析 Scheduler Scheduler 是整个 kube-scheduler 的一个 structure,提供 ...
- windows类书的学习心得
原文网址:http://www.blogjava.net/sound/archive/2008/08/21/40499.html 现在的计算机图书发展的可真快,很久没去书店,昨日去了一下,真是感叹万千 ...
- 第24 章 : Kubernetes API 编程利器:Operator 和 Operator Framework
Kubernetes API 编程利器:Operator 和 Operator Framework 本节课程主要分享以下三方面的内容: operator 概述 operator framework 实 ...
- [E2E] Robot Framework introduction
We will use demo project as an example, go though QuickStart repo. Install: First you should have py ...
- Kubernetes系统架构简介
1. 前言 Together we will ensure that Kubernetes is a strong and open container management framework fo ...
- angular 调试 js (分 karms protractor / test e2e unit )
首页订阅 Protractor端到端的AngularJS测试框架教程 2014年01月18日 分类:教程, JavaScript, AngularJS Protractor是一个建立在WebDrive ...
- Kubernetes系统架构简介--转
原文地址:http://www.infoq.com/cn/articles/Kubernetes-system-architecture-introduction?utm_campaign=infoq ...
- 【云计算】Kubernetes、Marathon等框架需要解决什么样的问题?
闲谈Kubernetes 的主要特性和经验分享 Capitalonline全球云主机.全球私有网络,免费试用进行时 » 主要介绍 Kubernetes 的主要特性和一些经验.先从整体上 ...
随机推荐
- 原生JSdom节点相关(非原创)
节点属性 Node.nodeName //返回节点名称,只读 Node.nodeType //返回节点类型的常数值,只读 Node.nodeValue //返回Text或Comment节点的文本值,只 ...
- ASP.NET底层封装HttpModule实例---FormsAuthentication类的分析
HttpModule是用来注册HttpApplication事件的,实现IHttpModule接口的托管代码模块可以访问该请求管道的所有事件.那么对于我们最常用的ASP.NET Forms身份验证模块 ...
- 回味Python2.7——笔记1
一.基本知识 1.一个值可以同时赋给几个变量: >>> x = y = z = 0 # Zero x, y and z >>> x 0 >>> y ...
- WPF转换器之通用转换器
WPF中的转换器是一个非常好的数据类型转换解决方案,实用和强大, 它的作用是将源数据转换为WPF自身需要的类型,对数据实体没有侵略性,会在项目工程中频繁使用.所以掌握转换器是WPF开发的必备技能. 我 ...
- JVM GC(整理)
1 GC类型 1 )YGC 一般情况下,当新对象生成,并且在Eden申请空间失败时,就好触发YGC ,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区.然后整理S ...
- 【设计模式】Bridge模式(桥接模式)
最近的一次面试中,被问到桥接模式,以前呢并没有很仔细的研究过这个设计模式,借此机会剖析一下. 先给出自己对这个模式理解后的源码: interface A{ void methodA(); } inte ...
- Linux系统运维工程该具备哪些素质
记得在上高中时,物理老师总是会对我们一句话:"学习是件苦差事."工作后发现,其实做运维也是件苦差事.最为一名运维工程师,深知这一行的艰辛,但和IT行业其他职务一样,那就是付出的越多 ...
- 第一章之s5pv210启动顺序
我所使用的开发板是:友善之臂smart210,cpu为s5pv210.u-boot版本是:u-boot-2012-10 1,首先在u-boot中配置相对应的开发板的配置文件 #make s5p_gon ...
- 华为软件开发云对比Jenkins-JavaWeb项目持续部署方式
一.前言:Jenkins介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成和持续部署变成可能. 本文 ...
- Spark No FileSystem for scheme file 解决方法
在给代码带包成jar后,放到环境中运行出现如下错误: Exception in thread "main" java.io.IOException: No FileSystem f ...