高效测试框架推荐之Ginkgo

自2015年开始,七牛工效团队一直使用Go语言+Ginkgo的组合来编写自动化测试用例,积累了大约5000+的数量。在使用和维护过程当中,咱们以为Ginkgo的不少设计理念和功能很是赞,所以特分享给你们。git

本篇不是该框架的入门指导。若是您也编写或维护过大量自动化测试用例,但愿能得到一些共鸣.github

BDD(Behavior Driven Development)

要说Ginkgo最大的特色,笔者认为,那就是对BDD风格的支持。好比:正则表达式

Describe("delete app api", func() {
        It("should delete app permanently", func() {...})
        It("should delete app failed if services existed", func() {...})

It's about expressiveness。Ginkgo定义的DSL语法(Describe/Context/It)能够很是方便的帮助你们组织和编排测试用例。在BDD模式中,测试用例的标题书写,要很是注意表达,要能清晰的指明用例测试的业务场景。只有这样才能极大的加强用例的可读性,下降使用和维护的心智负担。express

可读性这一点,在自动化测试用例设计原则上,很是重要。由于测试用例不一样于通常意义上的程序,它在绝大部分场景下,看起来都像是一段段独立的方法,每一个方法背后隐藏的业务逻辑也是细小的,不具通识性。这个问题在用例量少的状况下,还不明显。但当用例数量上到必定量级,你会发现,如国能快速理解用例究竟是能作什么的,真的很是重要。而这正是BDD能补足的地方。api

不过仍是要强调,Ginkgo只是提供对BDD模式的支持,你的用例最终呈现的效果,仍是依赖你本身的书写。服务器

进程级并行,稳定高效

相应的咱们知道,BDD框架,由于其DSL的深度嵌套支持,会存在一些共享上下文的资源,如此的话想作线程级的并发会比较困难。而Ginkgo巧妙的避开了这个问题,它经过在运行时,运行多个被测服务的进程,来达到真正的并行,稳定性大大提升。其使用姿式也很是简单,ginkgo -p命令就能够。在实践中,咱们一般使用32核以上的服务器来跑集测,执行效率很是高。并发

这里有个细节,Ginkgo虽然并行执行测试用例,但其输出的日志和测试报告格式,仍然是整齐不错乱的,这是如何作到的呢?原来,经过源码会发现,ginkgo CLI工具在并行跑用例时,其内部会起一个监听随机端口的本地服务器,来作不一样进程之间的消息同步,以及日志和报告的聚合工做,是否是很巧妙?app

其余的一些Tips

Ginkgo框架的功能很是强大,对常见测试场景的都有比较好的支持,即便是一些略显复杂的场景,好比:框架

  • 在平时的代码中,咱们常常会看到须要作异步处理的测试用例。可是这块的逻辑若是处理很差,用例可能会由于死锁或者未设置超时时间而异常卡住,很是的恼人。好在Ginkgo专门提供了原生的异步支持,能大大下降此类问题的风险。相似用法:异步

    It("should post to the channel, eventually", func(done Done) {
        c := make(chan string, 0)
        go DoSomething(c)
        Expect(<-c).To(ContainSubstring("Done!"))
        close(done)
    }, 0.2)
  • 针对分布式系统,咱们在验收一些场景时,可能须要等待一段时间,目标结果才生效。而这个时间会由于不一样集群负载而有所不一样。因此简单的硬编码来sleep一个固定时间,很明显不合适。这种场景下如果使用Ginkgo对应的matcher库GomegaEventually功能就很是的贴切,在大大提高用例稳定性的同时,最大可能的减小无用的等待时间。
  • 笔者一直认为,自动化测试用例不该该仅仅是QA手中的工具,而应该尽量多的做为业务验收服务,输出到CICD,灰度验证,线上验收等尽量多的场景,以服务于整个业务线。一样利用Ginkgo咱们能够很容易作到这一点:
    • CICD: 在定义suite时,使用RunSpecWithDefaultReporters方法,可让测试结果既输出到stdout,还能够输出一份Junit格式的报告。这样就能够经过相似Jenkins的工具方便的呈现测试结果,而不用任何其余的额外操做。
    • TaaS(Test as a Service): 经过ginkgo build或者原生的go test -c命令,能够方便的将测试用例,编译成package.test的二进制文件。如此的话,咱们就能够方便的进行测试服务分发。典型的,如交付给SRE同窗,辅助其应对线上灰度场景下的测试验收。因此在测试用例的组织上,这里有个小建议,过往我会看到有同窗会习惯一个目录就定义一个suite文件,这样编译出的二进制文件就很是多,不利于分发。因此建议不要定义太多的suite,能够一条产品就一个suite入口,其余的用例包经过_导入进来。好比:

另外,值得说道的是,Ginkgo框架在提供强大功能和灵活性的同时,有些地方也须要使用者特别留心:

  • DescribeTable功能是对TableDriven模式的友好支持,但它的原理是经过Entry在用例执行以前,经过反射机制来自动生成It方法,因此若是指望相似BeforeEach+It的原生组合来使用BeforeEach+Entry的话,可能在值类型的变量传递上,会不符合预期。其实,相较于DescribeTable+Entry的模式,我我的更倾向于经过方法+多个It的原生组合来写用例,虽然代码量显得有点多,可是用例表达的逻辑主题会更清晰,可读性较高。相似以下:
  • Ginkgo CLI的focus和skip命令很是好用,可以灵活的指定想执行或者排除的测试用例。不过要注意的是,focus和skip传入的是正则表达式,而适配这个正则的,是组成用例的全部的Container标题的组合(Suite+Describe+Context+It), 这些标题从外到里拼接成的完整字符串,因此使用时当注意。

都有谁在用Ginkgo?

Ginkgo的官方文档很是详细,很是利于使用。另外,咱们看到著名的容器云项目Kubernetes也是使用Ginkgo框架来编写其e2e测试用例。

最后,若是您也使用Go语言来编写测试用例,不妨尝试下Ginkgo。

Contact me ?

Email: jinsdu@outlook.com
Blog: http://www.cnblogs.com/jinsdu/
Github: https://github.com/CarlJi

相关文章
相关标签/搜索