12月14日,在圣彼得堡的一次集会上,我(Artem Sokovets)与我的同事Dmitry Markelov讨论了SberTech当前自动测试的基础设施。 这篇文章重述了我们的演讲。

什么是硒
Selenium是一个Web浏览器自动化工具。 如今,此工具已成为WEB自动化的标准。

有许多支持Selenium Webdriver API的编程语言客户端。 通过WebDriver API,通过JSON Wire协议,与所选浏览器的驱动程序发生了交互,而交互又与一个已经存在的浏览器一起工作,执行了我们所需的操作。
今天,客户端的稳定版本是Selenium3.X。

顺便说一句,西蒙·斯图尔特(Simon Stewart)承诺在
SeleniumConf Japan会议上介绍Selenium 4.0。
硒网格
2008年,Philippe Hanrigou宣布了Selenium GRID,以构建支持各种浏览器的自动测试基础结构。

硒GRID由集线器和节点(节点)组成。 Node只是一个Java进程。 它可以与集线器在同一台计算机上,也可以在另一台计算机上,也可以在Docker容器中。 集线器实质上是自动测试的平衡器,该平衡器确定应将特定测试的执行发送到的节点。 您可以将移动模拟器连接到它。
Selenium GRID允许您在不同的操作系统和不同版本的浏览器上运行测试。 当然,如果使用maven-surfire-plugin或其他并行化机制并行运行自动测试,则还可以大大节省运行大量自动测试的时间。
当然,硒GRID也有其缺点。 使用标准实现时,必须面对以下问题:
- 不断重启集线器和节点。 如果集线器和节点长时间不使用,则通过后续连接,可能会出现以下情况:在节点上创建会话时,同一会话的超时会减少。 要恢复工作,需要重启。
- 限制节点数。 很大程度上取决于测试和网格设置。 没有铃鼓跳舞时,随着数十个相连节点的出现,它开始变慢。
- 微薄的功能;
- 没有完全停止服务就不可能进行更新。
SberTech的初始自动测试基础架构
在SberTech的早期,有以下用于UI自动测试的基础结构。 用户在Jenkins上开始组装,然后他使用该插件转向OpenStack分配虚拟机。 使用特殊的“映像”和所需的浏览器选择了VM,然后才在此VM上运行自动测试。
如果您想在Chrome或FireFox浏览器中运行测试,则Docker容器非常出色。 但是,在使用IE时,您必须创建一个“干净”的VM,该过程最多需要5分钟。 不幸的是,Internet Explorer是我们公司的优先浏览器。

主要问题是在IE中运行自动测试时,这种方法花费了很多时间。 我必须对套件进行单独的测试,然后并行启动程序集,以至少节省一些时间。 我们开始考虑现代化。
新基础架构要求
参观了有关自动化,开发和DevOps的各种会议(Heisenbug,SQA Days,CodeOne,SeleniumConf等),我们逐渐形成了对新基础架构的要求列表:
- 减少运行回归测试的时间;
- 为自动测试提供一个入口,这将有助于自动化专家进行调试。 在少数情况下,一切都在本地运行,并且一旦测试进入管道,就会持续下降。
- 提供跨浏览器的兼容性和移动自动化(Appium测试)。
- 坚持银行的云架构:Docker容器应在OpenShift中进行管理。
- 减少内存和CPU消耗。
现有解决方案的简要概述
确定任务后,我们分析了市场上现有的解决方案。 我们检查的主要内容是
Aerokube团队(硒油和月亮),Alfalab解决方案(Alpha实验室),
JW-Grid (Avito)和
Zalenium的产品 。
Selenoid的主要缺点是缺乏对OpenShift(Kubernetes的包装)的支持。 关于Alfalab的决定,有
一篇关于哈布雷的文章 。 原来是相同的Selenium Grid。
文章中介绍了Avito的解决方案。 我们在Heisenbug会议上看到了有关该报告的报告。 它也有我们不喜欢的缺点。 Zalenium是一个开源项目,也不是没有问题。
下表总结了我们考虑的解决方案的优缺点:

因此,我们选择了Aerokube的产品-Selenoid。
子午线vs月亮
在四个月的时间里,我们使用Selenoid自动化了Sberbank生态系统。 这是一个很好的解决方案,但是银行正在向OpenShift迈进,在OpenShift中部署Selenoid并不是一件容易的事。 精妙之处在于Kubernetes中的Selenoid管理后者的docker,而Kubernetes对此一无所知,也无法正确地与其他节点开玩笑。 另外,Kubernetes中的Selenoid需要一个GGR(Go Grid Router),其中负载平衡是la脚的。
在试验了硒油化合物之后,我们对付费的Moon工具产生了兴趣,该工具专门用于Kubernetes,与免费的硒油树脂相比具有许多优势。 它已经开发了两年,可以让您部署Selenium测试UI的基础结构,而不必花钱在对如何在Kubernetes中部署Selenoid有所了解的DevOps工程师身上。 这是一个重要的优势-尝试在不停机的情况下升级Selenoid群集并在运行测试时减少容量?

月亮不是唯一的选择。 例如,您可以使用上面提到的Zalenium,但实际上它是相同的Selenium Grid。 它具有存储在其中的集线器内部会话的完整列表,如果集线器崩溃,则测试结束。 在这种背景下,月亮由于没有内部状态而获胜,因此通常不会察觉其中一个副本的掉落。 Moon拥有“优美”的一切-可以无忧无虑地重新启动,而无需等待会话结束。
Zalenium还有其他限制。 例如,它不支持配额。 您不能将它的两个副本用于负载均衡器,因为他不知道如何在两个或多个“头”之间分配状态。 通常,很难开始使用他的集群。 Zalenium使用PersistentVolume来存储数据:日志和录制的视频测试,但这主要涉及云中的磁盘,而不是容错性更高的S3。
自动测试基础架构
当前使用Moon和OpenShift的基础结构如下:

用户可以在本地和使用CI服务器(在我们的情况下为Jenkins,但可能还有其他服务器)上运行测试。 在这两种情况下,我们都使用RemoteWebDriver访问OpenShift,在其中部署了具有多个Moon副本的服务。 此外,在Moon中处理了指示我们需要的浏览器的请求,因此Kubernetes API使用该浏览器启动了壁炉的创建。 然后,Moon直接将请求代理到测试通过的容器。
运行结束时,会话结束,在删除下,释放资源。
启动Internet Explorer
当然,有一些困难。 如前所述,我们的目标浏览器是Internet Explorer-我们的大多数应用程序都使用ActiveX组件。 由于我们使用OpenShift,因此我们的Docker容器在RedHat Enterprise Linux上运行。 因此,出现了一个问题:当主机在Linux上时,如何在Docker容器中启动Internet Explorer?
Moon开发团队的成员分享了他们启动Internet Explorer和Microsoft Edge的决定。
该解决方案的缺点是Docker容器应以特权模式运行。 因此,在开始测试后,用Internet Explorer初始化容器需要10秒钟,这比使用以前的基础结构快30倍。
故障排除
总之,我们希望与您分享在集群部署和配置过程中遇到的一些问题的解决方案。
第一个问题是服务映像的分发。 当月亮启动浏览器的创建时,除了带有浏览器的容器外,还会启动其他服务容器-记录器,防御者,录像机。

所有这些都在一个吊舱中启动。 而且,如果这些容器的映像未在节点上缓存,则它们将从Docker集线器交付。 在此阶段,一切都归我们所有,因为使用了内部网络。 因此,来自Aerokube的人员迅速将此设置放入地图配置中。 如果您还使用内部网络,我们建议您将这些映像刷新到注册表中,并在moon-config配置图中指定它们的路径。 在service.json文件中,您需要添加images部分:
"images": { "videoRecorder": "ufs-selenoid-cluster/moon-video-recorder:latest", "defender": "ufs-selenoid-cluster/defender:latest", "logger": "ufs-selenoid-cluster/logger:latest" }
在测试开始时已经确定了以下问题。 整个基础架构是动态创建的,但是测试在30秒后崩溃,并显示以下错误:
Driver info: org.openqa.selenium.remote.RemoteWebDriver Org.openqa.selenium.WebDriverException: <html><body><h1>504 Gateway Time-out</h1> The server didn't respond in time.
为什么会这样呢? 事实是,通过RemoteWebDriver进行的测试最初是指路由层OpenShift,它负责与外部环境进行交互。 该层的作用是Haproxy,它将请求重定向到我们需要的容器。 在实践中,测试转到了这一层,它被重定向到了我们应该创建浏览器的容器。 但是随着资源用尽,他无法创建它。 因此,测试进入队列,并且30秒钟后,代理服务器通过超时将其丢弃,因为默认情况下是此时间间隔。

如何解决呢? 事实证明一切都很简单-您只需为我们的容器的路由器重新定义haproxy.router.openshift.io/timeout批注。
$oc annotate route moon --overwrite haproxy.router.openshift.io/timeout=10m
下一种情况是使用兼容S3的存储。 Moon可以使用浏览器记录容器中发生的情况。 在一个节点上,服务容器随浏览器一起上升,其中之一是录像机。 它记录容器中发生的所有事件,并在会话结束后将数据发送到S3兼容存储。 要将数据发送到此类存储,您需要在设置中指定url,投票密码和存储篮的名称。
似乎一切都很简单。 我们输入了数据并开始运行测试,但是存储库中没有文件。 在分析日志之后,我们意识到用于与S3进行交互的客户端发誓缺少证书,因为在url字段中,我们使用https指定了S3的地址。 解决方案是指定不受保护的http模式或将证书添加到容器中。 如果您不知道容器中有什么以及它们如何工作,则后一种选择会更加困难。
最后...
每个浏览器容器都可以独立配置-所有可用参数在Moon文档中。 让我们注意特权和nodeSelector之类的自定义设置。
为此需要它们。 如上所述,带有Internet Explorer的容器只能在特权模式下运行。 特权标志提供了在所需模式下的操作以及将这些容器启动到服务帐户的权限的颁发。
要在单独的节点上运行,您需要注册nodeSelector:
"internet explorer": { "default": "latest", "versions": { "latest": { "image": "docker-registry.default.svc:5000/ufs-selenoid-cluster/windows:7", "port": "4444", "path": "/wd/hub", "nodeSelector": { "kubernetes.io/hostname": "nirvana5.ca.sbrf.ru" }, "volumes": ["/var/lib/docker/selenoid:/image"], "privileged": true } } }
最后提示。 跟踪正在运行的会话数。 我们显示Grafana中的所有发射:

我们去哪里
我们对当前基础架构中的所有内容都不满意,因此该解决方案还不能称为完整解决方案。 在不久的将来,我们计划在Docker中稳定IE,在Moon中获得“丰富”的UI界面,并测试Appium的移动自动测试。