专栏文章 使用 cypress 之前需要知道的

孙高飞 · 2020年07月03日 · 最后由 Ark 回复于 2020年07月03日 · 492 次阅读

前言

观望 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 在一次测试中只执行一次的要求(它只能是一个线程或一个进程内保证只执行一次)。

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

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册