mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-16 14:13:46 +08:00
mod
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
<audio id="audio" title="39 | 从小作坊到工厂:什么是Selenium Grid?如何搭建Selenium Grid?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f2/3b/f2518c17ede48c1e11261138ebe6243b.mp3"></audio>
|
||||
|
||||
你好,我是茹炳晟,今天我分享的主题是“从小作坊到工厂:什么是Selenium Grid?如何搭建Selenium Grid?”。
|
||||
|
||||
从今天开始,我们就要一起进入测试基础架构这个新的系列了。我将用四篇文章的篇幅,从0到1,为你深入剖析大型互联网企业的测试基础架构设计,以及其原始驱动力,和你探讨测试执行环境设计、测试报告平台设计以及测试基础架构与CI/CD的集成等内容。当然,在这其中还会涉及到很多具有前瞻性的设计创新。
|
||||
|
||||
虽说测试基础架构是资深测试开发人员的必备技能,但此时你可能还并不清楚测试基础架构到底指的是什么?没关系,当你阅读完这个系列的文章之后,相信你一定可以对测试基础架构,以及其关键设计有一个清晰、全面的认识。
|
||||
|
||||
所以,今天我就先和你分享一下,我眼中的测试基础架构到底是指什么?
|
||||
|
||||
## 什么是测试基础架构?
|
||||
|
||||
测试基础架构指的是,执行测试的过程中用到的所有基础硬件设施以及相关的软件设施。因此,我们也把测试基础架构称之为广义的测试执行环境。通常来讲,测试基础架构主要包括以下内容:
|
||||
|
||||
- 执行测试的机器;
|
||||
- 测试用例代码仓库;
|
||||
- 发起测试执行的Jenkins Job;
|
||||
- 统一的测试执行平台;
|
||||
- 测试用例执行过程中依赖的测试服务,比如提供测试数据的统一测试数据平台、提供测试全局配置的配置服务、生成测试报告的服务等;
|
||||
- …
|
||||
|
||||
**由于测试基础架构的核心是围绕测试执行展开的,所以我们今天就先来重点讨论一下“执行测试的机器”部分。**
|
||||
|
||||
这部分内容的展开,我会从早期最简单的方法谈起,然后探讨这个方法在实际执行中的弊端,并由此引出我们今天讨论的主角:Selenium Grid。
|
||||
|
||||
先试想一下:你要在一个典型测试场景中,基于某种浏览器去执行Web应用的GUI测试。这时,你首先要做的就是找到相应的机器,并确保上面已经安装了所需的浏览器。如果这台机器上,还没有安装所需浏览器的话,你需要先安装这个浏览器。一切准备就绪后,你就可以使用这台机器执行测试了。
|
||||
|
||||
如果你要执行的测试只需要覆盖一种浏览器的话,那就很简单了,你只要事先准备好一批专门的机器或者虚拟机,然后安装好所需的浏览器就可以了。同时,如果测试用例的数量也不是很多的话,你需要的这批机器或者虚拟机的数量也不会很多。执行测试时,你只要将需要使用的那台机器的地址提供给测试用例就可以了。
|
||||
|
||||
其实,这种模式就是典型的“小作坊”模式。“小作坊”模式的特点就是,人工维护一批数量不多(通常在30台以内)的执行测试的机器,然后按需使用。
|
||||
|
||||
对于小团队来讲,“小作坊”模式的问题并不大。但是,随着测试覆盖率要求的提升,以及测试用例数量的增加,这种“小作坊”模式的弊端就逐渐显现,并被不断放大了。其中,最主要问题体现在以下四个方面:
|
||||
|
||||
<li>
|
||||
当Web应用需要进行不同浏览器的兼容性测试时,首先你需要准备很多台机器或者虚拟机,并安装所需的不同浏览器;然后,你要为这些机器建立一个列表,用于记录各台机器安装了什么浏览器;最后,你在执行测试时,需要先查看机器列表以选择合适的测试执行机。
|
||||
</li>
|
||||
<li>
|
||||
当Web应用需要进行同一浏览器的不同版本的兼容性测试时,你同样需要准备很多安装有同一浏览器的不同版本的测试执行机,并为这些机器建立列表,记录各台机器安装的浏览器版本号,然后执行测试时先查看列表以选择合适的测试执行机。
|
||||
</li>
|
||||
<li>
|
||||
测试执行机的机器名或者IP发生变化,以及需要新增或者减少测试机时,都需要人工维护这些机器列表。很显然,这种维护方式效率低下,且容易出错。
|
||||
</li>
|
||||
<li>
|
||||
在GUI自动化测试用例的数量比较多的情况下,你不希望只用一台测试执行机以串行的方式执行测试用例,而是希望可以用上所有可用的测试执行机,以并发的方式执行测试用例,以加快测试速度。为了达到这个目的,你还是需要人工管理这些测试用例和测试执行机的对应关系。
|
||||
</li>
|
||||
|
||||
**这四种情况的问题,可以归结为:测试执行机与测试用例的关系是不透明的,即每个测试用例都需要人为设置测试执行机。**
|
||||
|
||||
为了改善这种局面,Selenium Grid就应运而生了。
|
||||
|
||||
- 一方面,使用Selenium Grid可以让测试机器的选择变得“透明”。也就是说,我们只要在执行测试用例时指定需要的浏览器版本即可,而无需关心如何找到合适的测试执行机。因为,这寻找符合要求的测试执行机的工作,Selenium Grid可以帮你完成。
|
||||
- 另一方面,Selenium Grid的架构特点,天生就能很好地支持测试用例的并发执行。
|
||||
|
||||
接下来,我就和你详细聊聊到底什么是Selenium Grid,Selenium Grid的架构是什么样的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/30/bf/3077a24abcd93f063c7510fb81ccf9bf.png" alt="" />
|
||||
|
||||
从本质上讲,Selenium Grid是一种可以并发执行GUI测试用例的测试执行机的集群环境,采用的是HUB和Node模式。这个概念有些晦涩难懂,我来举个例子吧。
|
||||
|
||||
假如,现在有个律师事务所要接受外来业务,那么就会有一个老大专门负责对外接受任务。收到任务后,这个老大会根据任务的具体要求找到合适的手下,然后将该任务分发给手下去执行。
|
||||
|
||||
那么,这个老大是怎么知道哪个手下最适合处理这个任务呢?其实,这个老大手下的每个人都会事先报备自己具备的技能,这样老大在分发任务的时候,就可以做到“有的放矢”了。
|
||||
|
||||
现在,我们再回到Selenium Grid。Selenium Grid由两部分构成,一部分是Selenium Hub,另一部分是Selenium Node。
|
||||
|
||||
将这个律师事务所的例子,与Selenium Grid做个类比,它们的对应关系是:
|
||||
|
||||
- 这个对外的老大对应的是Selenium Hub;
|
||||
- 具体执行任务的手下,对应的是Selenium Node;
|
||||
- 老大接到任务后分配给手下执行的过程,就是Selenium Hub将测试分配到Selenium Node执行的过程;
|
||||
- 老大的手下向他报备自己技能的过程,就是Selenium Node向Selenium Hub注册的过程。
|
||||
|
||||
也就是说,**Selenium Hub用来管理各个Selenium Node的注册信息和状态信息,并且接收远程客户端代码的测试调用请求,并把请求命令转发给符合要求的Selenium Node执行。**
|
||||
|
||||
现在,我们已经搞明白了什么是Selenium Grid,以及Selenium Grid的工作模式。Selenium Grid的功能是不是很酷炫呢?那么,Selenium Grid的搭建是不是很难?接下来,我们就看看如何搭建自己的Selenium Grid吧。
|
||||
|
||||
在这里,我会依次给你介绍传统的Selenium Grid和基于Docker的Selenium Grid的搭建方法。通过这部分内容我要达到的目的是,可以帮你搭建起属于自己的Selenium Grid。
|
||||
|
||||
## 传统Selenium Grid的搭建方法
|
||||
|
||||
我将通过一个实例,和你分享如何搭建一个传统的Selenium Grid。
|
||||
|
||||
现在,我们的需求是,搭建一个具有1个Node的Selenium Grid。那么通常来讲我们需要2台机器,其中一台作为Hub,另外一台作为Node,并要求这两台机器已经具备了Java执行环境。
|
||||
|
||||
<li>
|
||||
通过官网下载selenium-server-standalone-<version>.jar文件。这里需要注意的是,不管是Hub还是Node,都使用同一个JAR包启动,只是启动参数不同而已。
|
||||
</li>
|
||||
<li>
|
||||
将下载的selenium-server-standalone-<version>.jar文件分别复制到两台机器上。
|
||||
</li>
|
||||
<li>
|
||||
选定其中一台机器作为Selenium Hub,并在这台机器的命令行中执行以下命令:
|
||||
</li>
|
||||
|
||||
```
|
||||
java -jar selenium-server-standalone-<version>.jar -role hub
|
||||
|
||||
```
|
||||
|
||||
在这条命令中,“-role hub”的作用是将该机器启动为Selenium Hub。启动完成后,这台机器默认对外提供服务的端口是4444。
|
||||
|
||||
然后,你就可以在这台机器上通过[http://localhost:4444/grid/console](http://localhost:4444/grid/console)观察Selenium Hub的状态,也可以在其他机器上通过http://<Hub_IP>:4444/grid/console观察Selenium Hub的状态。其中,<Hub_IP>是这台Selenium Hub机器的IP地址。由于此时还没有Node注册到该Hub上,所以你看不到任何的Node信息。
|
||||
|
||||
启动过程和状态信息,分别如图2、3所示。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a2/98/a275424067255c72da249734a203ba98.png" alt="" />
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/3d/15/3d73539d2b14aa45d4f2b19334eb9a15.png" alt="" />
|
||||
|
||||
1. 在另一台作为Selenium Node的机器上执行以下命令:
|
||||
|
||||
```
|
||||
java -jar selenium-server-standalone-<version>.jar -role node -hub http:// <Hub_IP>:4444/grid/register
|
||||
|
||||
```
|
||||
|
||||
这条命令中,“-role node”的作用是,将该机器启动为Selenium Node,并且通过“-hub”指定了Selenium Hub的节点注册URL。
|
||||
|
||||
执行成功后,你可以再次打开http://<Hub_IP>:4444/grid/console观察Selenium Hub的状态。此时,你可以看到已经有一个Node挂载到了Hub上。这个Node,就是用来实际执行测试的机器了。并且,这个Node上已经缺省提供了5个Firefox浏览器的实例、5个Chrome浏览器的实例和1个IE浏览器的实例,同时默认允许的并发测试用例数是5个。
|
||||
|
||||
如果你想自己配置这些内容,可以在启动Node的时候提供不同的启动参数。具体可以指定哪些参数,你可以参考[Selenium Grid](https://github.com/SeleniumHQ/selenium/wiki/Grid2)的官方文档。
|
||||
|
||||
如图4所示为Node的启动过程,如图5所示为在Hub端注册Node的过程,如图6所示为挂载完Node后Selenium Hub的状态。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/db/96/db5edbf3d119ac17710a9640d905c596.png" alt="" />
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/3e/4b/3e4133f06d2cc5d812cef1f8f375c74b.png" alt="" />
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/58/06/58bf48cb7af0db82546902a3a5c99406.png" alt="" />
|
||||
|
||||
1. 完成上述操作后,在测试用例中通过以下代码将测试指向Selenium Hub,然后由Selenium Hub完成实际测试执行机的分配与调度工作。其中,最关键的部分是,创建RemoteWebDriver实例的第一个参数,这个参数不再是一个具体的测试执行机的IP地址或者名字了,而是Selenium Hub的地址。
|
||||
|
||||
```
|
||||
DesiredCapabilities capability = DesiredCapabilities.firefox();
|
||||
WebDriver driver = new RemoteWebDriver(new URL("http://<Hub_IP>:4444/wd/hub"), capability);
|
||||
|
||||
```
|
||||
|
||||
至此,我们就已经完成了Selenium Grid的搭建工作。正如上面的五个步骤所示,这个搭建过程非常简单。接下来,你就自己动手尝试一下吧。
|
||||
|
||||
## 基于Docker的Selenium Grid的搭建方法
|
||||
|
||||
目前,Docker技术的广泛普及,再加上它的轻量级、灵活性等诸多优点,使得很多软件都出现了Docker版本。当然,Selenium Grid也不例外。所以,我也会在这里和你简单介绍一下基于Docker的Selenium Grid搭建过程。
|
||||
|
||||
在这个搭建过程中,你将会发现基于Docker运行Selenium Grid的话,机器的利用率会得到大幅提高。因为,一台实体机或者虚拟机,往往可以运行非常多的Docker实例数量,而且Docker实例的启动速度也很快。因此,相对于虚拟机或者实体机方案而言,Docker方案可以更高效地创建Node。
|
||||
|
||||
接下来,我们就一起看看如何基于Docker来搭建Selenium Grid吧。
|
||||
|
||||
在基于Docker搭建Selenium Grid之前,你需要先安装Docker环境。具体安装方法,你可以参考[Docker的官方文](https://docs.docker.com/get-started/)[档](https://docs.docker.com/get-started/)。
|
||||
|
||||
接下来,你就可以通过以下命令分别启动Selenium Hub和Selenium Node了。
|
||||
|
||||
```
|
||||
#创建了Docker的网络grid
|
||||
$ docker network create grid
|
||||
|
||||
#以Docker容器的方式启动Selenium Hub,并且对外暴露了4444端口
|
||||
$ docker run -d -p 4444:4444 --net grid --name selenium-hub selenium/hub:3.14.0-europium
|
||||
|
||||
#以Docker容器的方式启动并挂载了Chrome的Selenium Node
|
||||
$ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome:3.14.0-europium
|
||||
|
||||
#以Docker容器的方式启动并挂载了Firefox的Selenium Node
|
||||
$ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox:3.14.0-europium
|
||||
|
||||
```
|
||||
|
||||
相比基于实体机或者虚拟机搭建Selenium Grid的方法,基于Docker的方式灵活性更大、启动效率也更高、可维护性也更好。而且,在更高级的应用中,比如当我们需要根据测试用例的排队情况,动态增加Selenium Grid中的Node数量的时候,Docker都将是最好的选择。关于这部分内容具体的细节,我会在后面两篇文章中详细展开。
|
||||
|
||||
## 总结
|
||||
|
||||
今天,我从测试基础架构的概念讲起,并和你分享了传统Selenium Grid 和基于Docker的Selenium Grid的搭建方法。
|
||||
|
||||
首先,测试基础架构指的是,执行测试的过程中用到的所有基础硬件设施以及相关的软件设施,包括了执行测试的机器、测试用例代码仓库、统一的测试执行平台等。而,今天我针对测试执行的机器这个主题展开了分享。
|
||||
|
||||
在最早起的测试执行场景中,采用的方法是由人工维护一批数量不多(通常在30台以内)的执行测试的机器,然后按需使用,完成整个测试过程,这也是典型的“小作坊”模式。随着测试需求日益复杂,“小作坊”模式的缺点也暴露无疑,其中最主要的问题在于:测试执行机和测试用例的对应关系不“透明”,以及由此带来的测试用例并发执行难以实施的问题。
|
||||
|
||||
于是,为了解决这个问题,就出现了Selenium Grid。简单地说,Selenium Grid就是一种可以并发执行GUI测试用例的测试执行机的集群环境。由于它采用的是Hub和Node的架构模式,所以很容易就解决了“小作坊”模式的测试用例与测试执行机间的不“透明”关系,以及测试用例并发执行的问题。
|
||||
|
||||
而Selenium Grid的搭建也是非常简单。其中,传统Selenium Grid搭建时只要在理解了Selenium Grid架构之后,通过Java命令分别启动Hub和Node即可;而基于Docker的Selenium Grid在搭建时,就更简单了,直接通过Docker命令运行已经封装好的Image就可以了。
|
||||
|
||||
这么来看,Selenium Grid功能强大,搭建方法更是简单,也因此已经广泛应用于测试执行环境的搭建中。
|
||||
|
||||
## 思考题
|
||||
|
||||
目前Selenium Grid已经有Docker的版本了,你有没有考虑过可以在云端,比如PCF、GCP、AWS上搭建Selenium Grid呢?在我看来,这将是未来的主流方案,你也是类似的看法吗?
|
||||
|
||||
感谢你的收听,欢迎你给我留言。
|
||||
|
||||
|
||||
129
极客时间专栏/软件测试52讲/测试基础架构篇/40 | 从小工到专家:聊聊测试执行环境的架构设计(上).md
Normal file
129
极客时间专栏/软件测试52讲/测试基础架构篇/40 | 从小工到专家:聊聊测试执行环境的架构设计(上).md
Normal file
@@ -0,0 +1,129 @@
|
||||
<audio id="audio" title="40 | 从小工到专家:聊聊测试执行环境的架构设计(上)" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b5/97/b506a52199f802152675a8bc6381eb97.mp3"></audio>
|
||||
|
||||
你好,我是茹炳晟,今天我和你分享的主题是“从小工到专家:聊聊测试执行环境的架构设计(上)”。
|
||||
|
||||
在上一篇文章中,我介绍了Selenium Grid的基础知识,以及如何搭建Selenium Grid。现在,你已经非常清楚,Selenium Grid的作用主要是承担了测试执行机器的角色,被用来执行实际的测试工作。但是,实际工程中的测试执行环境往往更复杂,而测试执行机器也只是其中的一个重要部分。
|
||||
|
||||
因此,我们还需要控制发起测试的Jenkins,并管理测试用例执行和结果显示的系统。同时,为了更方便地与CI/CD流水线集成,我们还希望不同类型的测试发起过程可以有统一的接口。
|
||||
|
||||
那么,从今天开始的两篇文章,我将由浅入深地和你聊聊测试执行环境中的基本概念,以及架构设计的思路。
|
||||
|
||||
## 什么是测试执行环境?
|
||||
|
||||
测试执行环境的定义有广义和狭义之分:
|
||||
|
||||
- 狭义的测试执行环境,单单指测试执行的机器或者集群。比如,我在上一篇文章[《从小作坊到工厂:什么是Selenium Grid?如何搭建Selenium Grid?》](https://time.geekbang.org/column/article/40468)中介绍的Selenium Grid就是一个最经典的测试执行集群环境。
|
||||
- 广义的测试执行环境,除了包含具体执行测试的测试执行机以外,还包括测试执行的机器或者集群的创建与维护、测试执行集群的容量规划、测试发起的控制、测试用例的组织以及测试用例的版本控制等等。
|
||||
|
||||
因此,**广义的测试执行环境也被称为测试基础架构。而,我在测试基础架构这个系列里,要和你讨论的是广义上的测试执行环境。也就是说,我会和你重点讨论测试基础架构的概念和设计。**
|
||||
|
||||
如果你是在一些小型的软件公司做测试工程师的话,可能并没有听说过“测试基础架构”这个概念,或者也只是停留在对其的一知半解上。但,实际情况是,无论小型的软件公司还是中大型的软件公司都存在测试基础架构。
|
||||
|
||||
只是,在小型的软件公司,由于自动化测试的执行量相对较小,测试形式也相对单一,所以测试执行架构非常简单,可能只需要几台固定的专门用于测试执行的机器就可以了。那么,此时测试基础架构的表现形式就是测试执行环境。
|
||||
|
||||
而对于中大型的软件公司,尤其是大型的全球化电商企业,由于需要执行的自动化测试用例数量非常多,再加上测试本身的多样性需求,测试基础架构的设计是否高效和稳定将直接影响产品是否可以快速迭代、发布上线。因此,中大型的软件公司都会在测试基础架构上有比较大的投入。
|
||||
|
||||
一般情况下,中大型企业在测试基础架构上的投入,主要是为了解决以下这几方面的问题:
|
||||
|
||||
- **简化测试的执行过程**。我们不用每次执行测试时,都必须先去准备测试执行机,因为测试执行机的获取就像日常获取水电一样方便了。
|
||||
- **最大化测试执行机器的资源利用率**,使得大量的测试执行机可以以服务的形式为公司层面的各个项目团队提供测试执行的能力。
|
||||
- **提供大量测试用例的并发执行能力**,使得我们可以在有限的时间内执行更多的测试用例。
|
||||
- **提供测试用例的版本控制机制**,使得测试执行的时候可以根据实际被测系统的软件版本自动选择对应的测试用例版本。
|
||||
- **提供友好的用户界面**,便于测试的统一管理、执行与结果展示。
|
||||
- **提供了与CI/CD流水线的统一集成机制**,从而可以很方便地在CI/CD流水线中发起测试调用。
|
||||
|
||||
以此类推,如果你想要设计出高效的测试基础架构,就必须要从以下几个方面着手:
|
||||
|
||||
**对使用者而言,测试基础架构的“透明性”**。也就是说,测试基础架构的使用者,无需知道测试基础架构的内部设计细节,只要知道如何使用就行。
|
||||
|
||||
我在上一篇文章中和你探讨的Selenium Grid,就是一个很好的案例。实际使用Selenium Grid时,你只需要知道Hub的地址,以及测试用例对操作系统和浏览器的要求就可以,而无需关注Selenium Grid到底有哪些Node,以及各个Node又是如何维护的技术细节。
|
||||
|
||||
**对维护者而言,测试基础架构的“易维护性”**。对于一些大型的测试而言,你需要维护的测试执行机的数量会相当大,比如Selenium的Node的数量达到成百上千台后,如果遇到WebDriver升级、浏览器升级、病毒软件升级的情况时,如何高效地管理数量庞大的测试执行机将会成为一大挑战。
|
||||
|
||||
所以,早期基于物理机和虚拟机时,这个执行机的管理问题就非常严重。但是,出现了基于Docker的方案后,这些问题都因为Docker容器的技术优势而被轻松解决了。
|
||||
|
||||
**对大量测试用例的执行而言,测试基础架构执行能力的“可扩展性”**。这里的可扩展性指的是,测试执行集群的规模可以随着测试用例的数量自动扩容或者收缩。
|
||||
|
||||
以Selenium Gird为例,可扩展性就是Node的数量和类型,可以根据测试用例的数量和类型进行自动调整。这里,建议你先记住这个概念,我还会在专栏的后续文章中详细展开。
|
||||
|
||||
**随着移动App的普及,测试基础架构中的测试执行机需要支持移动终端和模拟器的测试执行**。目前,很多的商业云测平台已经可以支持各种手机终端的测试执行了。其后台实现,基本都是采用的Appium + OpenSTF + Selenium Gird的方案。
|
||||
|
||||
很多中小企业,因为技术水平以及研发成本的限制,一般直接使用这类商业解决方案。但是,对于大型企业来说,出于安全性和可控制性的考量,一般会选择自己搭建移动测试执行环境。
|
||||
|
||||
理解了什么是测试执行环境后,我们再一起看看测试基础架构的设计吧。
|
||||
|
||||
但是,这里我需要说明的是,我并不会以目前业界的最佳实践为例,和你讨论应该如何设计测试基础架构。
|
||||
|
||||
为什么呢?因为这样做,虽然看似可以简单粗暴地解决实际问题,但是这中间涉及到的琐碎问题,将会淹没测试基础架构设计的主线,反而会让你更加困惑为什么我要这么做,而不能那么做。
|
||||
|
||||
因此,本着“知其所以然”的原则,我还是会以遇到问题然后解决问题的思路,由浅入深地从最早期的测试基础架构说起,带你一起去经历一次测试基础架构设计思路的演进。在我看来,这样的思路,才是深入理解一门技术的有效途径,也希望你可以借此将测试基础架构的关键问题吃得更透。
|
||||
|
||||
## 早期的测试基础架构
|
||||
|
||||
早期的测试基础架构,会将测试用例存储在代码仓库中,然后是用Jenkins Job来Pull代码并完成测试的发起工作。如图1所示。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f2/ba/f20e2df431199038d25e9cabcacc31ba.png" alt="" />
|
||||
|
||||
在这种架构下,自动化测试用例的开发和执行流程,是按照以下步骤执行的:
|
||||
|
||||
<li>
|
||||
**自动化测试开发人员在本地机器开发和调试测试用例**。这个开发和调试过程,通常是测试开发人员自己的工作电脑上进行。也就是说,他们在开发完测试用例后,会在本机执行测试用例。这些测试用例,会在本机打开指定的浏览器并访问被测网站的URL,然后发起业务操作,完成自动化测试。
|
||||
</li>
|
||||
<li>
|
||||
**将开发的测试用例代码,Push到代码仓库**。如果自动化测试脚本在测试开发人员本地的电脑上顺利执行完成,那么接下来,我们就会将测试用例的代码Push到代码仓库,至此标志着自动化测试用例的开发工作已经完成。
|
||||
</li>
|
||||
<li>
|
||||
<p>**在Jenkins中建立一个Job,用于发起测试的执行**。这个Jenkins Job的主要工作是,先从测试用例代码仓库中Pull测试用例代码,并发起构建操作;然后,在远端或者本地固定的测试执行机上发起测试用例的执行。<br />
|
||||
这个Jenkins Job通常会将一些会发生变化的参数作为Job自身的输入参数。比如,远端或者本地固定的测试执行机的IP地址或者名字;再比如,被测系统有多套环境,需要指定被测系统的具体名字等。</p>
|
||||
</li>
|
||||
|
||||
这种测试架构,对于测试用例数量不多、被测系统软件版本不太复杂的场景的测试需求,基本都可以满足。但在实际使用时,你总会感觉哪里不太方便。
|
||||
|
||||
比如,每次通过Jenkins Job发起测试时,你都需要填写测试用例需要在哪台测试执行机上执行。而此时,这台测试执行机是否处于可用状态,是否正在被其他测试用例占用都是不可知的,那么你就需要在测试发起前进行人为确认,或者开发一个执行机器环境检查的脚本帮你确认。并且,当远端测试执行机的IP或者名字有变化时,或者当远端测试执行机的数量有变动时,你都需要能提前获知这些信息。
|
||||
|
||||
所以,这些局限性,也就决定了这种架构只能适用于小型项目。
|
||||
|
||||
说到这里,你可能已经想到了,不是有Selenium Grid吗?我完全可以用Selenium Gird代替固定的测试执行机。没错,这就是测试基础架构的第一次的重大演进,也因此形成了目前已经被广泛使用的经典测试基础架构。
|
||||
|
||||
## 经典的测试基础架构
|
||||
|
||||
用Selenium Grid代替早期测试基础架构中的“远端或本地固定的测试执行机器”,就形成了经典的测试基础架构。其架构如图2所示。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8e/8c/8e9da1055a174071903c785fcabdf78c.png" alt="" />
|
||||
|
||||
这样,你在每次发起测试时,就不再需要指定具体的测试执行机器了,只要提供固定的Selenium Hub地址就行,然后Selenium Hub就会自动帮你选择合适的测试执行机。
|
||||
|
||||
同时,由于Selenium Grid中Node的数量可以按需添加,所以整体的测试执行任务比较重时,你就可以增加Grid中Node的数量。
|
||||
|
||||
另外,Selenium还支持测试用例的并发执行,可以有效缩短整体的测试执行时间。
|
||||
|
||||
所以,这种基于Selenium Grid的经典测试基础架构,已经被大量企业广泛采用。
|
||||
|
||||
但是,随着测试用例数量的继续增加,传统的Selenium Grid方案在集群扩容、集群Node维护等方面遇到了瓶颈,并且Jenkins Job也因为测试用例的增加变得臃肿不堪。因此,变革经典的测试基础架构的呼声,也越来越高。
|
||||
|
||||
为此,业界考虑将Selenium Grid迁移到Docker,并且提供便于Jenkins Job管理的统一测试执行平台。这也是我将在下一篇文章中,要和你继续讨论的话题。
|
||||
|
||||
拭目以待吧。
|
||||
|
||||
## 总结
|
||||
|
||||
从广义上讲,测试执行环境除了包括测试执行机以外,还包括测试执行机的维护、集群的容量规划、测试发起的控制、测试用例的组织以及测试用例的版本控制等等。这也就是我要和你的测试基础架构的定义。
|
||||
|
||||
从定义上,我们也可以看出在设计一个高效的测试基础架构,应该从这几个方面着手:
|
||||
|
||||
- 保证对使用者的“透明性”;
|
||||
- 需要具备对维护者而言的“易维护性”;
|
||||
- 做到对大量测试用例并发执行的“可扩展性”;
|
||||
- 兼顾移动App对测试执行环境的需求。
|
||||
|
||||
然后,我以遇到问题然后解决问题的思路,和你分享了早期的测试基础架构向经典的测试基础架构的演进。这个演变可以归纳为,用Selenium Grid代替早期测试基础架构中的“远端或本地固定的测试执行机器”,打破了因为需要人为指定并维护测试执行机,而只能适用于小型测试项目的局限性,从而形成了已被广泛使用的经典测试基础架构。
|
||||
|
||||
而经典的测试基础架构,在测试用例持续增加时,也会面临诸如集群扩容、Jenkins Job臃肿不堪等等问题,于是基于Docker的测试基础架构便应运而生了。
|
||||
|
||||
## 思考题
|
||||
|
||||
你所在的团队是否在使用Selenium Grid?在实际使用过程中,你是否有遇到过什么瓶颈,又是如何解决的呢?
|
||||
|
||||
感谢你的收听,欢迎你给我留言一起讨论。
|
||||
|
||||
|
||||
149
极客时间专栏/软件测试52讲/测试基础架构篇/41 | 从小工到专家:聊聊测试执行环境的架构设计(下).md
Normal file
149
极客时间专栏/软件测试52讲/测试基础架构篇/41 | 从小工到专家:聊聊测试执行环境的架构设计(下).md
Normal file
@@ -0,0 +1,149 @@
|
||||
<audio id="audio" title="41 | 从小工到专家:聊聊测试执行环境的架构设计(下)" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/9c/fc/9ce44d3ac8471b3f08c6295824d043fc.mp3"></audio>
|
||||
|
||||
你好,我是茹炳晟,今天我和你分享的主题是“从小工到专家:聊聊测试执行环境的架构设计(下)”。
|
||||
|
||||
在上一篇文章中,我介绍了测试基础架构的概念,以及早期的和经典的两种测试基础架构。在文章的最后,我提到经典的测试基础架构中采用的Selenium Grid方案,在测试用例的数量持续增加的情况下,会带来集群扩容、Jenkins Job臃肿不堪等诸多问题,因此我们考虑将Selenium Grid迁移到Docker,并且提供便于Jenkins Job管理的统一测试执行平台。
|
||||
|
||||
所以,今天的这篇文章,我就会围绕这些瓶颈以及对应的解决方案来展开。
|
||||
|
||||
## 基于Docker实现的Selenium Grid测试基础架构
|
||||
|
||||
随着测试基础架构的广泛使用,以及大量的浏览器兼容性测试的需求,Selenium Grid中Node的数量会变得越来越大,也就是说我们需要维护的Selenium Node会越来越多。
|
||||
|
||||
在Node数量只有几十台的时候,通过人工的方式去升级WebDriver、更新杀毒软件、升级浏览器版本,可能还不是什么大问题。但是,当需要维护的Node数量达到几百台甚至几千台的时候,这些Node的维护工作量就会直线上升。虽然,你可以通过传统的运维脚本管理这些Node,但维护的成本依然居高不下。
|
||||
|
||||
同时,随着测试用例数量的持续增长,Selenium Node的数量也必然会不断增长,这时安装部署新Node的工作量也会难以想象。因为,每台Node无论是采用实体机还是虚拟机,都会牵涉到安装操作系统、浏览器、Java环境,以及Selenium。
|
||||
|
||||
而目前流行的Docker容器技术,由于具有更快速的交付和部署能力、更高效的资源利用,以及更简单的更新维护能力,也就使得Docker相比于传统虚拟机而言,更加得“轻量级”。
|
||||
|
||||
因此,**为了降低Selenium Node的维护成本,我们自然而然地想到了目前主流的容器技术,也就是使用Docker代替原本的虚拟机方案。**
|
||||
|
||||
基于Docker的Selenium Grid,可以从三个方面降低我们维护成本:
|
||||
|
||||
<li>
|
||||
由于Docker的更新维护更简单,使得我们只要维护不同浏览器的不同镜像文件即可,而无需为每台机器安装或者升级各种软件;
|
||||
</li>
|
||||
<li>
|
||||
Docker轻量级的特点,使得Node的启动和挂载所需时间大幅减少,直接由原来的分钟级降到了秒级;
|
||||
</li>
|
||||
<li>
|
||||
Docker高效的资源利用,使得同样的硬件资源可以支持更多的Node。也就是说,我们可以在不额外投入硬件资源的情况下,扩大Selenium Grid的并发执行能力。
|
||||
</li>
|
||||
|
||||
因此,现在很多大型互联网企业的测试执行环境都在向Docker过渡。
|
||||
|
||||
而具体如何基于Docker搭建一套Selenium Grid,你可以参考我在第39篇文章[《从小作坊到工厂:什么是Selenium Grid?如何搭建Selenium Grid?》](https://time.geekbang.org/column/article/40468)中介绍的方法。由此可见,将原本基于实体机或者虚拟机实现的Selenium Grid改进成为基于Docker实现的过程也很简单、灵活。
|
||||
|
||||
如图1所示,就是一个基于Docker实现的Selenium Grid的测试基础架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/56/75/56142f87923aa3c2e27746b91e2c0f75.png" alt="" />
|
||||
|
||||
## 引入统一测试执行平台的测试基础架构
|
||||
|
||||
在实际的使用过程中,基于Docker的Selenium Grid使得测试基础架构的并发测试能力不断增强,也因此会有大量项目的大量测试用例会运行在这样的测试基础架构之上。
|
||||
|
||||
当项目数量不多,我们可以直接通过手工配置Jenkins Job,并直接使用这些Job控制测试的发起和执行。但是,当项目数量非常多之后,测试用例的数量也会非常多,这时新的问题又来了:
|
||||
|
||||
<li>
|
||||
管理和配置这些Jenkins Job的工作量会被不断放大;
|
||||
</li>
|
||||
<li>
|
||||
这些Jenkins Job的命名规范、配置规范等也很难实现统一管理,从而导致Jenkins中出现了大量重复和不规范的Job;
|
||||
</li>
|
||||
<li>
|
||||
当需要发起测试,或者新建某些测试用例时,都要直接操作Jenkins Job。而这个过程,对于不了解这些Jenkins Job细节的人(比如,新员工、项目经理、产品经理)来说,这种偏技术型的界面体验就相当不友好了。
|
||||
</li>
|
||||
|
||||
为此,我们为了管理和执行这些发起测试的Jenkins Job实现了一个GUI界面系统。在这个系统中,我们可以基于通俗易懂的界面操作,完成Jenkins Job的创建、修改和调用,并且可以管理Jenkins Job的执行日志以及测试报告。
|
||||
|
||||
这,其实就是统一测试执行平台的雏形了。
|
||||
|
||||
有了这个测试执行平台的雏形后,我们逐渐发现可以在这个平台上做更多的功能扩展,于是这个平台就逐渐演变成了测试执行的统一入口。
|
||||
|
||||
在这里,我列举了这个平台两个最主要的功能和创新设计,希望可以给你以及你所在公司的测试基础架构建设带来一些启发性的思考。
|
||||
|
||||
**第一,测试用例的版本化管理**。我们都知道,应用的开发有版本控制机制,即:每次提测、发布都有对应的版本号。所以,为了使测试用例同样可追溯,也就是希望不同版本的开发代码都能有与之对应的测试用例,很多大型企业或者大型项目都会引入测试用例的版本化管理。最简单直接的做法就是,采用和开发一致的版本号。
|
||||
|
||||
比如,被测应用的版本是1.0.1,那么测试用例的版本也命名为1.0.1。在这种情况下,当被测应用版本升级到1.0.2的时候,我们会直接生成一个1.0.2版本的测试用例,而不应该直接修改1.0.1版本的测试用例。
|
||||
|
||||
这样,当被测环境部署的应用版本是1.0.1的时候,我们就选择1.0.1版本的测试用例;而当被测环境部署的应用版本是1.0.2的时候,我们就相应地选择1.0.2版本的测试用例。
|
||||
|
||||
所以,我们就在这个统一的测试执行平台中,引入了这种形式的测试用例版本控制机制,直接根据被测应用的版本自动选择对应的测试用例版本。
|
||||
|
||||
**第二,提供基于Restful API的测试执行接口供CI/CD使用**。这样做的原因是,测试执行平台的用户不仅仅是测试工程师以及相关的产品经理、项目经理,很多时候CI/CD流水线才是主力用户。因为,在CI/CD流水线中,每个阶段都会有不同的发起测试执行的需求。
|
||||
|
||||
我们将测试基础架构与CI/CD流水线集成的早期实现方案是,直接在CI/CD流水线的脚本中硬编码发起测试的命令行。这种方式最大的缺点在于灵活性差:
|
||||
|
||||
- 当硬编码的命令行发生变化,或者引入了新的命令行参数的时候,CI/CD流水线的脚本也要一起跟着修改;
|
||||
- 当引入了新的测试框架时,发起测试的命令行也是全新的,那么CI/CD流水线的脚本也必须被一起改动。
|
||||
|
||||
因此,为了解决耦合性的问题,我们在这个统一的测试执行平台上,提供了基于Restful API的测试执行接口。任何时候你都可以通过一个标准的Restful API发起测试,CI/CD流水线的脚本也无须再知道发起测试的命令行的具体细节了,只要调用统一的Restful API即可。
|
||||
|
||||
如图2所示,就是引入了统一测试执行平台的测试基础架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/40/43/40be3cb1a925bbcf24c2a710f0711443.png" alt="" />
|
||||
|
||||
## 基于Jenkins集群的测试基础架构
|
||||
|
||||
这个引入了统一测试执行平台的测试基础架构,看似已经很完美了。但是,随着测试需求的继续增长,又涌现出了新的问题:单个Jenkins成了整个测试基础架构的瓶颈节点。因为,来自于统一测试执行平台的大量测试请求,会在Jenkins上排队等待执行,而后端真正执行测试用例的Selenium Grid中很多Node处于空闲状态。
|
||||
|
||||
为此,将测试基础架构中的单个Jenkins扩展为Jenkins集群的方案就势在必行了。如图3所示,就是基于Jenkins集群的测试基础架构。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/db/f5/db974bd10bf6146c2ad1afbdb310ccf5.png" alt="" />
|
||||
|
||||
因为Jenkins集群中包含了多个可以一起工作的Jenkins Slave,所以大量测试请求排队的现象就再也不会出现了。
|
||||
|
||||
而这个升级到Jenkins集群的过程中,对于Jenkins集群中Slave的数量到底多少才合适并没有定论。一般的做法是,根据测试高峰时段Jenkins中的排队数量来预估一个值。通常最开始的时候,我们会使用4个Slave节点,然后观察高峰时段的排队情况,如果还是有大量排队,就继续增加Slave节点。
|
||||
|
||||
## 测试负载自适应的测试基础架构
|
||||
|
||||
引入了Jenkins集群后,整个测试基础架构已经很成熟了,基本上可以满足绝大多数的测试场景了。但是,还有一个问题一直没有得到解决,那就是:Selenium Grid中Node的数量到底多少才合适?
|
||||
|
||||
- 如果Node数量少了,那么当集中发起测试的时候,就会由于Node不够用而造成测试用例的排队等待,这种场景在互联网企业中很常见;
|
||||
- 而如果Node数量多了,虽然可以解决测试高峰时段的性能瓶颈问题,但是又会造成空闲时段的计算资源浪费问题。当测试基础架构搭建在按使用付费的云端时,计算资源的浪费就是资金浪费了。
|
||||
|
||||
为了解决这种测试负载不均衡的问题,Selenium Grid的自动扩容和收缩技术就应运而生了。
|
||||
|
||||
Selenium Grid的自动扩容和收缩技术的核心思想是,通过单位时间内的测试用例数量,以及期望执行完所有测试的时间,来动态计算得到所需的Node类型和数量,然后再基于Docker容器快速添加新的Node到Selenium Grid中;而空闲时段则去监控哪些Node在指定时间长短内没有被使用,并动态地回收这些Node以释放系统资源。
|
||||
|
||||
通常情况下,几百乃至上千台Node的扩容都可以在几分钟内完成,Node的销毁与回收的速度同样非常快。
|
||||
|
||||
至此,测试基础架构已经演变得很先进了,基本可以满足大型电商的测试执行需求了。测试负载自适应的测试基础架构,具体如图4所示。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/da/a4/daeb20ac9fee266ecbabbfadfa2305a4.png" alt="" />
|
||||
|
||||
## 如何选择适合自己的测试基础架构?
|
||||
|
||||
现在,我已经介绍完了测试基础架构的演进,以及其中各阶段主要的架构设计思路,那么对于企业来说,应当如何选择最适合自己的测试基础架构呢?
|
||||
|
||||
其实,对于测试基础架构的建设,我们切忌不要为了追求新技术而使用新技术,而是应该根据企业目前在测试执行环境上的痛点,来有针对性地选择与定制测试基础架构。
|
||||
|
||||
比如,你所在的企业如果规模不是很大,测试用例执行的总数量相对较少,而且短期内也不会有大变化的情况,那么你的测试基础架构完全就可以采用经典的测试基础架构,而没必要引入Docker和动态扩容等技术。
|
||||
|
||||
再比如,如果是大型企业,测试用例数量庞大,同时还会存在发布时段大量测试请求集中到来的情况,那么此时就不得不采用Selenium Gird动态扩容的架构了。而一旦要使用动态扩容,那么势必你的Node就必须做到Docker容器化,否则无法完全发挥自动扩容的优势。
|
||||
|
||||
所以说,采用什么样的测试基础架构不是由技术本身决定的,而是由测试需求推动的。
|
||||
|
||||
## 总结
|
||||
|
||||
在今天这篇文章中,我从测试基础架构演进的视角,和你分享了测试基础架构发展的前世今生。
|
||||
|
||||
首先,为了降低测试用例过多时Selenium Grid的维护成本,我们用Docker容器代替了经典测试基础架构中的实体机/虚拟机,形成了基于Docker实现的Selenium Grid测试基础架构。
|
||||
|
||||
而后,我们发现测试用例的数量达到一定规模后,管理和执行发起测试的Jenkins Job成了问题。于是,我们引入了一个基于GUI界面的测试执行平台,并在其上扩展了诸如测试用例版本化、提供基于Restful API的测试执行接口等功能。从而,形成了由这个统一测试执行平台发起测试的测试基础架构形态。
|
||||
|
||||
而为了进一步解决由单个Jenkins带来的系统瓶颈问题,我们过渡到了基于Jenkins集群的测试基础架构,通过多个同时工作的Jenkins Slave,解决了大量测试请求排队的问题。
|
||||
|
||||
随后,为了解决Selenium Grid中Node的数量到底多少才合适的问题,我和你谈论了创新设计的Selenium Grid的自动扩容和收缩技术。至此,测试负载自适应的测试基础架构也终于“千呼万唤始出来”了。
|
||||
|
||||
最后,我谈论了不同企业该如何选择最适合自己的测试基础架构的问题。这里,我强调了一定要根据测试需求选择测试基础架构,而不能一味地追求最新的技术。
|
||||
|
||||
我希望通过这种授人以渔的方式,可以帮你拓宽思路,并将测试基础架构的设计思路、思想,运用到你的实际工作中去。
|
||||
|
||||
## 思考题
|
||||
|
||||
其实,在我讲述的这个测试基础架构的设计和搭建过程中,还有很多可以优化和创新的点。你觉得哪些部分可以再优化呢?你还有哪些想法呢?
|
||||
|
||||
欢迎你给我留言,我们一起讨论。
|
||||
|
||||
|
||||
146
极客时间专栏/软件测试52讲/测试基础架构篇/42 | 实战:大型全球化电商的测试基础架构设计.md
Normal file
146
极客时间专栏/软件测试52讲/测试基础架构篇/42 | 实战:大型全球化电商的测试基础架构设计.md
Normal file
@@ -0,0 +1,146 @@
|
||||
<audio id="audio" title="42 | 实战:大型全球化电商的测试基础架构设计" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d5/b0/d5a6e6737e1c124481bc29c23400ceb0.mp3"></audio>
|
||||
|
||||
你好,我是茹炳晟。今天我和你分享的主题是“实战:大型全球化电商的测试基础架构设计”。
|
||||
|
||||
在前面的两篇文章中,我和你分享了测试基础架构的设计以及演进之路,其中涉及到了统一测试执行平台、Selenium Grid和Jenkins等一系列的概念。
|
||||
|
||||
在掌握了这些基础内容之后,今天我就和你一起看看大型全球化电商的测试基础架构又是如何设计的。这其中除了我之前介绍过的概念以外,还会引入一些新的服务和理念,我都会和你一一道来。
|
||||
|
||||
因为我们已经掌握了测试基础架构设计的基础知识,所以今天我会采用一种不同于以往由浅入深的方式,直接给出大型全球化电商网站的全局测试基础架构的最佳实践,然后再依次解释各个模块的主要功能以及实现基本原理。
|
||||
|
||||
其实,**大型全球化电商网站全局测试基础架构的设计思路,可以总结为“测试服务化”**。也就是说,测试过程中需要用的任何功能都通过服务的形式提供,每类服务完成一类特定功能,这些服务可以采用最适合自己的技术栈,独立开发,独立部署。而至于到底需要哪些测试服务,则是在理解了测试基础架构的内涵后再高度抽象后得到的。从本质上来看,这种设计思想其实和微服务不谋而合。
|
||||
|
||||
根据在大型全球化电商网站工作的实际经验,我把一个理想中的测试基础架构概括为了一张图(如图1所示)。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d9/71/d9456825d8e9568e9453efe5207fb571.png" alt="" />
|
||||
|
||||
这个理想的测试基础架构,包括了6种不同的测试服务,分别是:统一测试执行服务、统一测试数据服务、全局测试配置服务、测试报告服务、测试执行环境准备服务,以及被测系统部署服务。
|
||||
|
||||
接下来,我们一起看看这6大测试服务,具体是什么,以及如何实现。
|
||||
|
||||
## 统一测试执行服务
|
||||
|
||||
从本质上看,统一测试执行服务,其实和统一测试执行平台(你可以再回顾一下第41篇文章[《从小工到专家:聊聊测试执行环境的架构设计(下)》](https://time.geekbang.org/column/article/40915))是一个概念。只不过,统一测试执行服务,强调的是服务,也就是强调测试执行的发起是通过Restful API调用完成的。
|
||||
|
||||
总结来说,以Restful API的形式对外提供测试执行服务的方式,兼具了测试版本管理、Jenkins测试Job管理,以及测试执行结果管理的能力。
|
||||
|
||||
统一测试执行服务的主要原理是,通过Spring Boot框架提供Restful API,内部实现是通过调度Jenkins Job具体发起测试。如果你对此还有疑惑,请参考第40篇文章[《从小工到专家:聊聊测试执行环境的架构设计(上)》](https://time.geekbang.org/column/article/40582)。
|
||||
|
||||
还记得我在前面一直提到的将测试发起与CI/CD流水线集成吗?这个统一测试执行服务采用的Restful API调用,主要用户就是CI/CD流水线脚本。我们可以在这些脚本中,通过统一的Restful API接口发起测试。
|
||||
|
||||
## 统一测试数据服务
|
||||
|
||||
统一测试数据服务,其实就是统一测试数据平台(你也可以再回顾一下第37篇[《测试数据的“银弹”- 统一测试数据平台(上)》](https://time.geekbang.org/column/article/40156)和第38篇[《测试数据的“银弹”- 统一测试数据平台(下)》](https://time.geekbang.org/column/article/40166)文章的内容)。
|
||||
|
||||
任何测试,但凡需要准备测试数据的,都可以通过Restful API调用统一测试数据服务,然后由它在被测系统中实际创建或者搜索符合要求的测试数据。而具体的测试数据创建或者搜索的细节,对于测试数据的使用者来说,是不需要知道的。也就是说,统一测试数据服务,会帮助我们隐藏测试数据准备的所有相关细节。
|
||||
|
||||
同时,在统一测试数据服务内部,通常会引入自己的内部数据库管理测试元数据,并提供诸如有效测试数据数量自动补全、测试数据质量监控等高级功能。
|
||||
|
||||
在实际工程项目中,测试数据的创建通常都是通过调用测试数据准备函数完成的。而这些函数内部,主要通过API和数据库操作相结合的方式,实际创建测试数据。
|
||||
|
||||
如果你对测试数据的准备还有疑问,或者想知道更多的细节内容,可以再回顾一下前面“测试数据准备”的系列的第35~38篇文章。
|
||||
|
||||
## 测试执行环境准备服务
|
||||
|
||||
测试执行环境准备服务,其实我也已经介绍过了。这里“测试执行环境”,是狭义的概念,特指具体执行测试的测试执行机器集群:对于GUI自动化测试来说,指的就是Selenium Grid;对于API测试来说,指的就是实际发起API调用的测试执行机器集群。
|
||||
|
||||
测试执行环境准备服务的使用方式,一般有两种:
|
||||
|
||||
- 一种是,由统一测试执行服务根据测试负载情况,主动调用测试执行环境准备服务来完成测试执行机的准备,比如启动并挂载更多的Node到Selenium Grid中;
|
||||
- 另一种是,测试执行环境准备服务不直接和统一测试执行服务打交道,而是由它自己根据测试负载来动态计算测试集群的规模,并完成测试执行集群的扩容与收缩。
|
||||
|
||||
## 被测系统部署服务
|
||||
|
||||
被测系统部署服务,主要被用来安装部署被测系统和软件。虽然这部分内容我以前没有提到过,但它很好理解。其实现原理是,调用DevOps团队的软件安装和部署脚本。
|
||||
|
||||
- 对于那些可以直接用命名行安装和部署的软件来说很简单,一般只需要把人工安装步骤的命名行组织成脚本文件,并加入必要的日志输出和错误处理即可。
|
||||
- 对于那些通过图形界面安装的软件,一般需要找出静默(Silent)模式的安装方式,然后通过命令行安装。
|
||||
|
||||
如果被测软件安装包本身不支持静默安装模式,我强烈建议给发布工程师提需求,要求他加入对静默安装模式的支持。其实,一般的打包工具都能很方能地支持Silent安装模式,并不会增加额外的工作量。
|
||||
|
||||
被测系统部署服务,一般由CI/CD流水线脚本来调用。在没有被测系统部署服务之前,CI/CD流水线脚本中一般会直接调用软件安装和部署脚本。而在引入了被测系统部署服务后,我们就可以在CI/CD流水线脚本中直接以Restful API的形式调用标准化的被测系统部署服务了。这样做的好处是,可以实现CI/CD流水线脚本和具体的安装部署脚本解耦。
|
||||
|
||||
## 测试报告服务
|
||||
|
||||
测试报告服务,也是测试基础架构的重要组成部分,其主要作用是为测试提供详细的报告。
|
||||
|
||||
测试报告服务的实现原理,和传统测试报告的区别较大。
|
||||
|
||||
传统的软件测试报告,通常直接由测试框架产生,比如TestNG执行完成后的测试报告,以及HttpRunner执行结束后的测试报告等等,也就是说测试报告和测试框架绑定在了一起。
|
||||
|
||||
对于大型电商网站而言,由于各个阶段都会有不同类型的测试,所以测试框架本身就具有多样性,因此对应的测试报告也是多种多样。而测试报告服务的设计初衷,就是希望可以统一管理这些格式各异、形式多样的测试报告,同时希望可以从这些测试报告中提炼出面向管理层的统计数据。
|
||||
|
||||
为此,测试报告服务的实现中引入了一个NoSQL数据库,用于存储结构各异的测试报告元数据。在实际项目中,我们会改造每个需要使用测试报告服务的测试框架,使其在完成测执行后将测试报告的元数据存入到测试报告服务的NoSQL数据库。这样,我们再需要访问测试报告的时候,就可以直接从测试报告服务中提取了。
|
||||
|
||||
同时,由于各种测试报告的元数据都存在了这个NoSQL数据库中,所以我们就可以开发一些用于分析统计的SQL脚本,帮助我们获得质量相关信息的统计数据。
|
||||
|
||||
测试报告服务的主要使用者是测试工程师和统一测试执行服务。对统一测试执行服务来说,它会调用测试报告服务获取测试报告,并将其与测试执行记录绑定,然后进行显示。而测试工程师则可以通过测试报告服务这个单一的入口,来获取想要的测试报告。
|
||||
|
||||
## 全局测试配置服务
|
||||
|
||||
全局测试配置服务是这6个服务中最难理解的部分,其本质是要解决测试配置和测试代码的耦合问题。这个概念有点抽象,我们一起看个实例吧。
|
||||
|
||||
大型全球化的电商网站在全球很多国家都有站点,这些站点的基本功能是相同的,只是某些小的功能点会有地域差异(比如,因当地法务、政策等不同而引起的差异;又比如,由货币符号、时间格式等导致的细微差异)。
|
||||
|
||||
假设,我们在测试过程中,需要设计一个getCurrencyCode函数来获取货币符号,那么这个函数中就势必会有很多if-else语句,以根据不同国家返回不同的货币符号。
|
||||
|
||||
比如,如图2所示的“Before”代码中,就有4个条件分支,如果当前国家是德国(isDESite)或者法国(isFRSite),那么货币符号就应该是“EUR”; 如果当前国家是英国(isUKSite),那么货币符号就应该是“GBP”;如果当前国家是美国(isUSSite)或者是墨西哥(isMXSite),那么货币符号就应该是“USD”;如果当前国家不在上述的范围,那么就抛出异常。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/af/46/af8414d9a311fd5b40e0d3b0abf84746.png" alt="" />
|
||||
|
||||
上述函数的逻辑实现本身并没有问题,但是当你需要添加新的国家和新的货币符号时,就需要添加更多的if-else分支,当国家数量较多的时候,代码的分支也会很多。更糟糕的是,当添加新的国家时,你会发现有很多地方的代码都要加入分支处理,十分不方便。
|
||||
|
||||
那么,有什么好的办法,可以做到在添加新的国家支持时,不用改动代码吗?
|
||||
|
||||
其实,仔细想来,**之所以要处理这么多分支,无非是因为不同的国家需要不同的配置值**(这个实例中,不同国家需要的不同配置值就是货币符号),那如果我们可以把配置值从代码中抽离出去放到单独的配置文件中,然后代码通过读取配置文件的方式来动态获取配置值,这样就可以做到加入新的国家时,不用再修改代码本身,而只要加入一份新国家的配置文件就可以了。
|
||||
|
||||
为此,我们就有了如图2所示的“After”代码以及图中右上角的配置文件。“After”代码的实现逻辑是:通过GlobalRegistry并结合当前环境的国家信息来读取对应国家配置文件中的值。比如,GlobalEnvironment.getCountry()的返回值是“US”,也就是说当前环境的国家是美国,那么GlobalRegistry就会去“US”的配置文件中读取配置值。
|
||||
|
||||
这样实现的好处是,假定某天我们需要增加日本的时候,getCurrencyCode函数本身不用做任何修改,而只需要增加一个“日本”的配置文件即可。
|
||||
|
||||
至此,我们已经一起了解了大型全球化电商网站的全局测试基础架构设计,以及其中的6个主要测试服务的作用及其实现思路。现在,我再和你分享一个实例,看看这样的测试基础架构是如何工作的,帮助你进一步理解测试基础架构的本质。
|
||||
|
||||
## 大型全球化电商网站测试基础架构的使用实例
|
||||
|
||||
这个实例,我会以CI/CD作为整个流程的起点。因为,在实际工程项目中,自动化测试的发起与执行请求一般都是来自于CI/CD流水线脚本。
|
||||
|
||||
**首先,CI/CD流水线脚本会以异步或者同步的方式调用被测系统部署服务**,安装部署被测软件的正确版本。这里,被测系统部署服务会访问对应软件安装包的存储位置,并将安装包下载到被测环境中,然后调用对应的部署脚本完成被测软件的安装。之后,CI/CD脚本中会启动被测软件,并验证新安装的软件是否可以正常启动,如果这些都没问题的话,被测系统部署服务就完成了任务。
|
||||
|
||||
这里需要注意的是:
|
||||
|
||||
- 如果之前的CI/CD脚本是以同步方式调用的被测系统部署服务,那么只有当部署、启动和验证全部通过后,被测系统部署服务才会返回,然后CI/CD脚本才能继续执行;
|
||||
- 如果之前的CI/CD脚本是以异步方式调用的被测系统部署服务,那么被测系统部署服务会立即返回,然后等部署、启动和验证全部通过后,才会以回调的形式通知CI/CD脚本。因此,CI/CD脚本也要为此做特殊处理。
|
||||
|
||||
**被测系统部署完成后,CI/CD脚本就会调用统一测试执行服务**。统一测试执行服务会根据之前部署的被测软件版本选择对应的测试用例版本,然后从代码仓库中下载测试用例的Jar包。
|
||||
|
||||
**接下来,统一测试执行服务会将测试用例的数量、浏览器的要求,以及需要执行完成的时间作为参数,调用测试执行环境准备服务。**
|
||||
|
||||
测试执行环境准备服务会根据传过来的参数,动态计算所需的Node类型和数量,然后根据计算结果动态加载更多的基于Docker的Selenium Node到测试执行集群中。此时,动态Node加载是基于轻量级的Docker技术实现的,所以Node的启动与挂载速度都非常快。
|
||||
|
||||
因此,统一测试执行服务通常以同步的方式调用测试执行环境准备服务。
|
||||
|
||||
测试执行环境准备好之后,统一测试执行服务就会通过Jenkins Job发起测试的执行。**测试用例执行过程中,会依赖统一测试数据服务来准备测试需要用到的数据,并通过全局测试配置服务获取测试相关的配置与参数。**
|
||||
|
||||
同时,**在测试执行结束后,还会自动将测试报告以及测试报告的元数据发送给测试报告服务进行统一管理。**
|
||||
|
||||
以上就是这套测试基础架构的执行过程了。
|
||||
|
||||
## 总结
|
||||
|
||||
通过前面几篇文章,我们已经掌握了测试基础架构的基础知识,所以今天我分享的主题就是,从实战的角度帮你夯实测试基础架构的基础。
|
||||
|
||||
其实,大型全球化电商网站全局测试基础架构的设计思路,可以总结为“测试服务化”。于是,我总结了一个比较理想的测试基础架构,应该包括6大服务:统一测试执行服务、统一测试数据服务、全局测试配置服务、测试报告服务、测试执行环境准备服务,以及被测系统部署服务。
|
||||
|
||||
其中,统一测试执行服务,本质上讲就是统一测试执行平台;统一测试数据服务,其实就是统一测试数据平台;测试执行环境准备服务,指的是狭义的测试执行环境准备。这几部分内容,我都已经在前面的文章中分享过了,如果你有任何问题,也可以再给我留言一起讨论。
|
||||
|
||||
而被测系统部署服务,主要是被用来安装部署被测系统和软件,这部分也很简单;测试报告服务,虽然和传统的测试报告区别较大,但也可以通过引入一个NoSQL数据库,以存储的测试报告元数据的方式去实现。
|
||||
|
||||
全局测试配置服务是这6个服务中最难理解的部分,其本质是要解决测试配置和测试代码的耦合问题。我通过一个具体的不同国家对应不同货币符号的例子,和你讲述了具体如何解耦。
|
||||
|
||||
## 思考题
|
||||
|
||||
除了我今天分享的6大服务以外,其实还有更多的服务可以帮助我们提升测试效能,比如全局Mock服务、工程效能工具链仓库等等。你还能想到有哪些与测试相关的服务吗?
|
||||
|
||||
感谢你的收听,欢迎你给我留言一起讨论。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user