测试开发之路 使用 cypress 之前需要知道的

孙高飞 · July 03, 2020 · Last by Ark replied at July 03, 2020 · 833 hits

前言

观望cypress有段时间了,因为在一个比较重视UI自动化的团队(2000+UI自动化测试用例)并持续有新项目需要UI自动化支持的环境下, 持续关注UI自动化的新动态也是比较有必要的。 前几天我们团队的一个同事也跟我提了cypress,说想在新项目里试试。 昨天我也花了半天时间搭建了一下cypress的各种环境,demo以及尝试在项目里简单用了用。 结合之前看github了解到的内容。 我大概明白了cypress的特点,优势和劣势。 本来这一篇是想做一个种草类型的文章, 但是又一想之前有人发过cypress种种优势和教程了。 我就不重复写了, 这一次我从另外一个角度来给大家分析一下cypress(有点类似拔草了)。 给大家做技术选型的时候提供一个参考。

在使用cypress之前你要问自己

这是一个很重要的事, 虽然cypress的种种优势和特性都很吸引人,但是如果你想在公司内大范围推广或者直接应用在一个大型的复杂的UI自动化项目中(多人协作),那么你需要好好考虑一下你的团队是否做好了如下的准备。

你们是否是一个以java script为主技术栈的团队

跟selenide支持多种语言不同的是,cypress只支持js或者type script(需要安装插件)。 这是标准前端工程师的技术栈, 实际上如果你了解了cypress的一些诸如插装,spy等功能以及它独特的Test runner的话你会发现这是一款主打面向前端开发工程师的自动化测试产品(实际上github上的文档上他们对自己的定位也是如此),如果你仔细观察的话会发现默认支持cssSelector而不支持xpath, 因为前端工程师用的都是cssSelector。 如果要使用xpath, 那么需要额外安装插件。 所以通过种种信息我们都知道其实他们主要面向的是前端开发工程师, 技术栈也是以JS为主的, 由于其这个特性以及其实现原理, 未来想支持其他语言的可能性几乎没有。 这个工具之所以诞生了挺长时间但是一直没有被国内重视的原因之一也是国内的研发尤其是前端工程师基本不做这种端到端的自动化测试的。 github上大量的starts其实有很多研发工程师的功劳。 测试领域中使用到这个工具的没有想象的那么多。 因为任何一个测试团队要全面使用cypress都要考虑一个问题, 就是让团队全面切换到JS技术栈上真的值得么? 实际上这也是我认为cypress很难在测试领域内推广起来的最主要原因。 测试领域里使用python和java是主流, 最近1,2年学golang的也慢慢增多。 但是使用JS的估计也是就只要开发测试平台需要写前端的时候才会去用。 也就是说必然是大部分测试人员都是不是这个技术栈的。 所以在团队内推广cypress第一个要考虑的事情就是, 为了一个UI自动化而让很多人开是学习JS是一件值得的事情么? 实际上很多博客上也说如果你的团队是一个以js为主技术栈的团队,那么是推荐你使用cypress的。 可能有些同学会说自己试用了一下cypress, 不需要很懂JS也可以用的,一共就没多少API。 但是当你面临更复杂的场景或者遇到相关问题的时候,你就不会这么想了。 当一个UI自动化场景变的复杂的时候, 你可以需要调用其他组件来完成测试目的。 比如在我的项目中, 在做数据处理相关逻辑的时候, 需要先调用kafka的producer 客户端去push一些消息, 或者在做应用管理的时候,需要调用k8s的客户端控制和查询应用状态, 或者你需要一些单例模式的数据准备的操作的时候(PS: 有些很费时和资源的操作我们希望只运行一次来节省时间和资源),你就会发现你需要多理解一些语言特性和相关生态才能够工作。 而这也是我一直推荐使用java来做大型和复杂的自动化项目的原因。 即便是python的pytest中有fixture这么个东西,但由于受限于python的并发模型的限制,它依然没办法通过fixture来解决刚才说的在并发场景下实现一个fixture在一次测试中只执行一次的要求(它只能是一个线程或一个进程内保证只执行一次)。 所以在你不是JS的粘性用户的时候,自己在小而简单的项目中使用cypress还可以, 贸然在复杂项目中使用就有点不理智了。

结论: 想要大范围推广cypyress, 做好团队切换为JS技术栈的准备。并且最起码你们团队内得有个对JS生态非常熟的人负责这个UI自动化工作。

你们是否有兼容性测试的需求

目前cypress还只支持chrome浏览器, 有兼容性测试需求的人需要hold一下了,如果UI项目很大而且有频繁的兼容性需求, 那cypress就不是一个好的选择了。 不过cypress团队正在解决这个问题, 有需要的人可以观望一下。

你们是否要构建多项目的大型的UI自动化项目

什么是大型UI自动化项目, 咱们就简单用case的数量来衡量吧。 如果大家面对的是我的项目一样构建了2000+UI自动化的项目的话,都要面临一个问题, 就是UI自动化的分布式执行问题。 它不是简单的并行化, 在一台机器上并行化跑数个浏览器的程度是不行的。 需要数台机器联合运行。 所以webdriver才提供了grid来提供浏览器集群服务。 一般来说我们这2000个UI自动化测试用例需要动辄几十上百的浏览器来运行。 为了不压垮某一台机器, gird提供了自己的负载均衡能力来保证机器的平均压力。 那么我们来看一下cypress是怎么做的。 cpgress本着开箱即用的优势, 它不需要你安装并维护任何的其他软件, 它在全球提供了Dashboard服务, 你只需要在上面注册自己的project, 然后在它自带的Testrunning上与这个project绑定, dashboard会提供报告展示和项目管理等工作。 同时我们在多台机器上,或者是同一台机器上运行多个cypress任务,并使用相同的--ci-build-id 的话, dashboard就会调度多个cypress 程序作并行化处理。也就是cypress团队在公网上提供的Dashboard服务会帮你做分布式的调度和测试结果的汇总。 这无疑是大大减轻了以前我们要自己构建维护gird和初始化remote webdriver的成本。 这一点其实我是非常喜欢的。 但是在没有了grid这样的浏览器集群调度机制, 你将面临另外一个问题。 那就是你如何决定在哪些机器上运行多少个cypress任务来达到并行化的目的。 这么说可能不太直观。 我们对比一下grid和cypress的并行化方案在使用上的区别。 在gird的方案里, 使用的remote webdriver, 程序的执行和浏览器的控制是分离的。 在我们的程序里只需要用多线程来调用测试用例即可。 remote webdriver 与grid hub通信, gird hub会自动的按策略分配多个节点下的浏览器执行。 并且我们可以多个项目,多个测试任务并行执行连接grid hub。 也就是grid已经变成了一个基础测试资源,作为一个浏览器集群向所有项目提供服务, gird 会按自己的策略去分配浏览器的资源。

而反观cypress, 它在运行的时候一定是在本地启动浏览器的, 只不过它连接到Dashboard上让dashboard在并行化任务中做统一的调度 ,你通过在不同的机器上运行多个cypress 任务来一起注册到dashbaord上让其调度来达到并行化的目的。 也就是说在什么机器上启动多少个浏览器是由你定的。 那么这时候问题就来了, 你怎么做这个处理呢? 比如你现在需要在这个测试任务中执行30个浏览器的并发度来进行测试,而你有6台机器, 你该怎么做? 如果是集成到jenkins上的话,你需要的是在jenkins中配置这6台机器为slave, 然后在jenkins pipeline 中挨个切换这6台机器并在每台机器上启动5个cypress任务。 类似下面这样

想想要写30个这样的stage,中间还要切换slave是不是很崩溃。 当然你可以使用jenkins sharelib来用groovy写几个函数来动态生成, 但是依然很麻烦。 而且前提是你必须要引入jenkins 2.0的pipeline和sharelib了。 你用普通的job都没办法搞这事,当然你也可以抛开jenkins用ssh shell 来远程调用这5台机器运行命令来管理。 总之就是你一定要开发一段程序来启动30个cypress。 虽然这样可以解燃眉之急, 但是我们在看这样一个场景, 如果这几台机器不是你一个人在用。 其他人也要执行UI自动化测试, 它也要在这几台机器上启动浏览器。 这时候你或者他怎么确定在哪台机器上启动几个浏览器是合适的? 因为如果启动多了机器扛不住任务都挂了甚至直接机器就崩了。 所以你看虽然cypress抛弃了类似grid这种浏览器集群调度的实现以让你使用起来更简单。 但是她也同时放弃了一些很重要的能力。 在使用grid的时候我们是不需要担心这些的, 因为不管多少人,多少个测试任务链接grid hub, 它有自己的负载均衡策略来保证压力平均分配, 限制浏览器总数不至于压垮机器以及更好的资源利用率。 所以gird更适合作为测试团队的基础设施来给所有项目提供浏览器服务。

所以基于以上的分析, 我们又知道了一个不利于cypress大规模推广的因素 ---- cypress缺少调度能力。 在有基础设施小组或者工程效能小组的质量团队里, 我们一般都要从整个团队的角度考虑资源问题,稳定性,资源利用率是我们要考虑的很大的因素。 gird的方案可以通过构建浏览器集群在保证稳定性的前提下最大化资源利用率。 而cypress 就让事情变的很棘手。 当然解法是有的, cypress自己没有调度能力的话,我们引入一个有强大调度能力的东西就可以了。 所以如果你的公司内本身就在使用一些调度系统的话,比如k8s, 那这个问题就可以解决了。 k8s本身就是一个调度能力很强的容器编排框架, 而cypress也提供了容器运行的能力。 我们可以利用k8s的batch job能力, 设置并行度(满足多机器的并发执行, k8s会在多个节点进行调度),设置申请的资源和限制(保证有足够的CPU和内存可以运行,限制能力也保证它消耗的资源不会撑爆机器)。 k8s的调度能力会帮我们完美的解决上面说的cypress在调度能力上的不足。

总结:cypress原生不利于大规模的并行UI自动化也不适合多人,多项目协作工作。 需要额外引入k8s这种调度系统。

回过来说说技术选型的事。

上面主要从JS技术栈和并行化分析了cypress的缺点, 但是其实cypress本身是非常优秀的自动化测试框架的。 我试用了之后其实是非常喜欢的。 只不过它目前为止并不适合大范围推广以及在大型的复杂的UI自动化项目中使用。 其主要原因在于JS技术栈很难推广到所有做UI自动化的人以及浏览器兼容性问题, 次要原因在于调度能力不足, 当然我本身就是k8s的深度用户,所以这个问题对于我来说不算什么事, 但是对于普通的同学来说这就是个比较大的问题。 当然还有一个不可忽视的问题, 就是测试领域里用这个的人太少了, 相应的文档和问题的积累在github和 其他网站上都不够多, 如果碰到比较诡异的坑的话,也有点担心找不到解决方案,尤其是我们还不是JS专家的时候。 所以对于cypress还在观望的同学, 最好还是谨慎一些。 别要一下子就大规模推广。

当然了如果你面对的是一个不那么复杂也没那么大的场景, 你本身也对js比较了解,那么cypress将会是不错的选择。 它的很多特性都能在研发效率和运行效率上表现的比webdriver好。 如果你因为种种原因无法使用cypress, 那么我推荐selenide作为替代品, selenide在webdriver的基础上也封装了很多和cypress一样的能力。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 2 条回复 时间 点赞

cypress对前端知识的要求还是有比较高的

即便是python的pytest中有fixture这么个东西,但由于受限于python的并发模型的限制,它依然没办法通过fixture来解决刚才说的在并发场景下实现一个fixture在一次测试中只执行一次的要求(它只能是一个线程或一个进程内保证只执行一次)。

加个分布式锁不就解决了么

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up