如何Dockerize您的端到端验收测试
本文作为使用Selenium Docker映像以及CodeceptJS和Express服务器的“操作方法”指南。
其中,我们将涵盖:
- 什么是E2E验收测试?
- 为什么要使用Docker?
- 松散耦合的测试工具
- 测试工具层
- 创建测试项目
E2E验收测试
验收测试是典型软件开发过程中的一个阶段。它涵盖了测试,以确定产品是否符合总体要求规格,以及是否“已接受”为准备交付。在将产品投入生产之前,这通常是测试的最后阶段。这可能包括基于用户的验收测试,基于业务的验收测试,甚至包括alpha / beta测试。
端到端(E2E)测试是验收测试的一种实现。这是验收测试的方法,但这些术语不是同义词。它允许从头到尾测试应用程序的流程,看它是否按设计执行。在Web应用程序的情况下,它将涉及确定用户场景并测试用户将按顺序采取的每个步骤。如果方案未成功完成,则测试失败。
存在各种工具来自动化该过程,模拟用户与应用程序的交互。
为何选择Docker?
创建和运行E2E测试通常被认为是一个片状和复杂的过程。它需要大量的设置,在不同的机器或CI(持续集成)环境中运行时仍然很容易失败。为本地测试和CI测试安装和维护不同的浏览器和WebDrivers需要时间。即使完成了,它仍然会因为简单的问题而失败,例如开发人员本地计算机或CI中的屏幕分辨率是否不同。
Docker的标准优势也适用:无需处理操作系统兼容性或安装了依赖项。要运行Selenium Server,您需要安装Java(或者至少要显式启动/停止)。要运行Express,您需要Node.js,而对于Chrome,您需要Chrome本身以及ChromeDriver。
使用Docker时,可以消除这些依赖性。您只需使用已包含这些容器的不同容器,无论它们在哪台机器上运行,它们的功能都完全相同。当您认为将Docker构建到CI中是多么容易时,Docker化您的测试过程将成为一个明显的选择。
松散耦合的测试工具
在编写E2E测试时有几个框架可用,而对于新手来说,很难知道选择哪个并投入时间。如果选错了,你就会浪费很多时间。
这就是CodeceptJS的用武之地。CodeceptJS是一个测试框架,采用场景驱动的行为驱动开发(BDD)方法,使用API语言,非工程师易于理解和使用。然而,或许更重要的是,它是后端不可知的。它是在几个流行的测试库(例如WebDriverIO或Puppeteer)之上编写的,它的单个高级API可以与您选择的任何一个进行通信。它的创作者认为这
您的测试不应该绑定到您的执行引擎。无论您选择Selenium还是Puppeteer,您的测试应该看起来几乎相同。如果您(稍后)感觉到一个引擎的限制,您可以轻松地将测试切换到其他引擎。
测试工具层
模拟用户与浏览器交互的每一层都有一些不同的产品
让我们采用自下而上的方法来研究每个层如何构建在最后一层上。
最初引用Selenium是值得的,Selenium是一个长期运行的项目,其中包含一组活跃使用的工具,它们现在由Selenium WebDriver,Grid,Server和IDE组成。在创建这些工具时,他们设定了许多行业标准,通常以他们来自Selenium产品的名字而令人困惑地命名。这可以在'Selenium WebDriver'和在其开发中建立的'WebDriver线协议'中看到。适用的那些将在下面更详细地显示。
浏览器
任何网络浏览器:Chrome,Firefox,Internet Explorer,Safari,Opera等。通常在文档中称为“用户代理”。
W3C的WebDriver线协议
WebDriver有线协议是一种与Web浏览器交互的平台和语言中立方式。它定义了一个在请求/响应对中使用JSON over HTTP 的通用RESTful Web服务。它允许从外部源操作DOM元素,同时还允许导航到网页,用户输入,JavaScript执行等。
最初由Selenium为Selenium WebDriver编写,该协议现已进入编辑草案阶段,成为官方的W3C标准。
其他协议确实退出,但这里不会详细介绍。所有解释都将假设一个实现WebDriver有线协议的后端。
另一个值得注意的协议是Puppeteer使用的Chrome DevTools协议。Puppeteer不使用Selenium Server,并捆绑了最新版本的Chromium,供本地使用。如果你想在Docker中运行Puppeteer,你可以使用CodeceptJS图像(Puppeteer和Nightmare附带)或者按照官方指南创建可以支持它的自定义图像。
浏览器WebDrivers
这些是金属丝的webdriver协议的浏览器的特定实现中,例如ChromeDriver用于Chrome或GeckoDriver用于Firefox。每个都充当一个独立的服务器,用于接收来自使用WebDriver API 的客户端的请求(通常是测试所在的位置)。为了与目标浏览器通信,必须安装正确的WebDriver实现。
Selenium Server
如果测试是在定义它们的同一台机器上运行,那么使用的客户端WebDriver API实现(如下所述)可以直接与浏览器WebDriver通信,并且不需要Selenium Server。
但是,如果要在不同的计算机上运行测试,无论是在CI中,在跨多个计算机或虚拟机(VM)的Selenium Grid设置中,在远程测试平台(如BrowserStack或SauceLabs)上,还是在Docker中,都要运行 Selenium使用服务器。它充当代理,将来自客户端WebDriver API的请求转发到正确的浏览器WebDriver,并从浏览器传回响应。
正如我们稍后将看到的,'machine'也可以换成'container'
客户端WebDriver实现
各种工具实现了客户端WebDriver有线协议。这里的协议可以看作是通过上述层向浏览器发送请求的API。使用该协议的许多工具都是完整的框架,例如WebDriverIO,它们包含自己的测试运行器。
其他实现包括:原始的 Selenium WebDriver,Protractor,Appium等。
每个库的目标都是为了获得相同的结果,但焦点和API实现略有不同。这可以像Protractor browser.get(url)
和WebDriverIO 一样基本browser.url(url)
。
一个API来统治它们
如本节开头所述,这是CodeceptJS发挥作用的地方。它将其他客户端WebDriver协议(或其他)实现称为“ 帮助程序 ”,并允许您在使用一种API语言时指定您喜欢的帮助程序。CodeceptJS并不关心所选帮助程序正在使用哪种协议。
WebDriverIO,Puppeteer,Protractor,Nightmare和Appium都是现有的助手。
在CodeceptJS中,I.amOnPage(url)
无论选择哪个帮助程序,上一个命令都是如此。这意味着如果您想将后端切换到支持的其他助手之一,则不必重新编写测试。它可以覆盖或添加到通过自定义类,你应该想的默认API方法。
创建测试项目
有这么多层,这开始听起来很复杂,但在CodeceptJS的初始化脚本和Docker镜像之间,我们可以快速找到一个有效的例子。
我们将生产什么
现在将使用两个容器,但这可以扩展
我们将在CodeceptJS中编写一个简单的测试,指定一个WebDriverIO后端帮助程序,它将与standalone-firefox Docker容器中的远程浏览器进行通信。我们将使用Express“hello world”应用程序,但这可以被您希望的任何应用程序取代。
很快,只需要两个命令来运行Dockerized应用程序和所有测试套件
一旦我们完成了所有设置,我们将只能运行两个命令来运行测试:
docker-compose up --build
docker exec -it app npm run test:e2e
通过在两个并排的终端窗口中运行,我们可以看到容器正在运行并且测试实时执行。
先决条件
- Docker,适用于您正在开发的任何一台机器。
- 您还可以安装Node.js,&npm进行本地开发和调试,但这些也可以在Docker中完全运行。
文件结构
我们将在下面生成文件结构。你可以在Github上看到一个工作示例。
|-- .gitignore
|-- output/
|-- Dockerfile
|-- app.js
|-- docker-compose.yml
|-- package.json
|-- package-lock.json
|-- e2eTests/
|-- common_test.js
|-- docker.conf.js
依赖
首先,我们将使用Express作为依赖项创建package.json,将CodeceptJS和WebDriverIO创建为dev依赖项。
{
"name": "example-standalone-firefox",
"version": "1.0.0",
"description": "Example of Dockerizing E2E testing",
"scripts": {
"start": "node app.js",
"test:e2e": "codeceptjs run --steps --verbose --config=./e2eTests/docker.conf.js"
},
"dependencies": {
"express": "^4.16.3"
},
"devDependencies": {
"codeceptjs": "^1.2.0",
"webdriverio": "^4.12.0"
}
}
我们还包括两个脚本,一个用于运行我们将添加的Express应用程序(npm run start
),另一个用于运行我们的CodeceptJS测试(npm run test:e2e
)。
codeceptjs run --steps --verbose --config=./e2eTests/docker.conf.js
--steps
非常适合在测试运行时在终端中显示输出,同时--verbose
进一步扩展详细程度。--verbose
可能不需要作为标准,但有利于查看示例的工作原理。--config
向我们展示了后端配置文件的路径,在这种情况下保存在一个单独的e2eTests
目录中。
我们的应用
接下来我们需要一个应用来测试。为此,我们将运行Express“ hello world ”应用程序app.js
。
const express = require('express'); const app = express(); app.get('/', (req, res) => res.send('Hello World!')); const server = app.listen(, () => {
const port = server.address().port
console.log(`Example app listening on port ${port}`)
})
您可以使用npm run start
然后localhost:3000
在浏览器中查看此内容。
测试配置
CodeceptJS需要两个文件,一个配置文件和一个测试文件。测试文件非常简单:它测试可以访问应用程序,保存屏幕截图,并检查页面上是否可以看到文本“Hello”。
Feature('Basic test'); Scenario('navigate to homepage', I => {
I.amOnPage('http://app:3000');
I.saveScreenshot('frontpageScreenshot.png');
I.see('Hello');
});
我们将使用多个Docker容器的第一个迹象显示在使用app:3000
而不是localhost:3000
。localhost
只能在一个容器内理解。如果正在从另一个容器运行命令(在本例中是我们的第二个Selenium容器中的Firefox),那么它需要更明确的引用。我们可以直接使用第一个容器的IP地址,但使用容器的名称更容易阅读。
在这种情况下,app
将是运行应用程序的容器的名称,因此我们可以使用app:3000
。不要担心,如果你还没有遵循这一点,看看我们docker-compose.yml
的结构将有所帮助。
我们还需要一个主配置文件。这可以用JSON或JS编写,但在这里我们使用JS。我们来看看这个:
exports.config = {
tests: './*_test.js', // how to know which files are test files
output: './output', // where to save screenshots
helpers: {
WebDriverIO: { // which backend helper to use
url: 'http://app:3000', // a base URL to start on
host: 'firefox-container', // identifying where selenium runs
browser: 'firefox', // a series of config options
smartWait: ,
waitForTimeout: ,
desiredCapabilities: { // for a demo app we do not want
acceptInsecureCerts: true, to worry about SSL certs
}
},
},
name: 'codeceptjs-docker',
};
设置Docker
回到上面“我们将要生成什么”部分中的图表,我们可以看到我们将使用两个Docker容器。他们必须彼此了解并能够沟通。一个将包含我们的应用程序和测试,一个包含Selenium Server,GeckoDriver和Firefox,因此我们不需要在本地计算机上安装Firefox。
Docker Compose是一个“定义和运行多容器Docker应用程序的工具。”它使用命令 启动Docker容器docker-compose up
,并使用它来阻止它们docker-compose down
。如果正在使用用户定义的Dockerfile,--build
则用于构建它,或者第一次docker-compose up
运行,或者如果对Dockerfile进行了更改。docker-compose.yml
是定义up
命令将执行的操作的文件。
我们的下一步是创建这个docker-compose.yml
。它严重依赖于缩进。
version: "" // which version of compose syntax you are using
services:
app:
container_name: app // explicit so we can use this for app:3000
build: . // a self defined Dockerfile, see below
ports: // exposes port 3000 (where express runs)
- "3000:3000" to other containers, and to our local
depends_on: browser
- firefox-container
volumes: // maps so changes to these can be seen
- ./e2eTests:/e2eTests
- ./package.json:/package.json
- ./package-lock.json:/package-lock.json
- ./.gitignore:/.gitignore
- ./app.js:/app.js firefox-container: // we'll look at this below
container_name: firefox-container
image: selenium/standalone-firefox:3.12.-americium
volumes:
- /dev/shm:/dev/shm
ports:
- "4444:4444"
对于我们的Selenium服务器,驱动程序和浏览器,我们使用可从公众预先定义的图像泊坞枢纽称为硒/独立Firefox的。我们指定我们想要的版本,3.12.0-americ。如果我们没有指定它,默认情况下将使用最新的图像(这不是一件坏事)。至于建议,我们将其配置为共享主机的内存,以防止浏览器崩溃中运行,并揭露4444端口,默认端口硒。我们还将此映射到本地计算机上的端口4444,允许我们localhost:4444/wd/hub/static/resource/hub.html
在浏览器中访问。
对于我们的app
容器,我们不只是使用由其他人构建的图像,而是编写Dockerfile来指定我们的应用程序的构建方式。与selenium-firefox
容器相同,我们在这种情况下公开了一个端口3000,因为Express是默认运行的地方。通过使用3000:3000
我们可以localhost:3000
在Docker中运行应用程序时访问它,以便在我们的本地浏览器中查看它。
我们的Dockerfile使用公共node:carbon
映像作为基础,设置工作目录,将一些文件从本地计算机复制到容器,运行npm install
以便容器具有所有需要的依赖项,然后运行npm start
我们指定的命令。
FROM node:carbon
WORKDIR ./
COPY ./package.json ./package-lock.json ./app.js ./
RUN npm install
CMD [ "npm", "start" ]
这意味着在docker-compose up --build
运行时,它将遵循这些步骤,从而使我们的应用程序准备好并在端口3000上运行。
注意:--build
只有在第一次docker-compose up
运行时,或者对Dockerfile或其中执行的步骤进行了更改时才需要该标志。例如,如果我们在我们中添加了另一个依赖项,package.json
那么如果我们没有重建我们的映像,那么Docker就不会知道它,就像npm install
在Dockerfile中运行一样。
运行测试
我们现在有一个简单的应用程序,为它编写的测试,以及将运行我们的应用程序,Selenium Server和Firefox的Docker Compose配置。
我们可以开始使用所有这些docker-compose up --build
。
要在正在运行的Docker容器中运行命令,docker exec
可以从另一个终端窗口使用。格式为:
docker exex <flags> <container_name> <command>
我们将使用的命令是:
docker exec -it app npm run test:e2e
我们现在可以看到我们的测试正在运行,并在执行时看到每个步骤!从这里我们可以扩展我们的测试,添加其他测试(结束文件名_test.js
),并使用相同的两个命令来运行它们。无需更多设置。
您现在拥有一个易于扩展的E2E测试设置,无论运行哪台计算机,都可以依赖该设置以相同的方式运行。它是用API命令编写的,开发人员和非开发人员都可以轻松理解。现在剩下的就是决定你的应用应该具备哪种行为,然后进行测试!
最后的话
SeleniumHQ还生成用于Chrome测试的 Docker 镜像,以及使用Selenium Grid一次运行多个Chrome和Firefox实例的图像。
CodeceptJS还有在Docker中运行CodeceptJS的说明,因此不需要在应用程序中将其指定为依赖项。
在我写的一篇名为“ 亚马逊弹性容器服务的初学者指南 ”的文章的第一部分中,可以看到关于Docker如何工作的更具技术性,但仍然是初级的描述。
感谢您阅读
如何Dockerize您的端到端验收测试的更多相关文章
- 脚手架vue-cli系列五:基于Nightwatch的端到端测试环境
不同公司和组织之间的测试效率迥异.在这个富交互和响应式处理随处可见的时代,很多组织都使用敏捷的方式来开发应用,因此测试自动化也成为软件项目的必备部分.测试自动化意味着使用软件工具来反复运行项目中的测试 ...
- Nightwatch——自动化测试(端对端e2e)
背景: 前端页面模拟仿真操作,目的是避免每次更新相关内容重复之前的测试操作,减少不必要的时间投入,以及校验功能的可用性.但是目前元素定位是个问题(每次页面有修改都要重设某些元素定位) 测试分类: 一. ...
- 利用Oracle RUEI+EM12c进行应用的“端到端”性能诊断
概述 我们知道,影响一个B/S应用性能的因素,粗略地说,有以下几个大的环节: 1. 客户端环节 2. 网络环节(可能包括WAN和LAN) 3. 应用及中间层环节 4. 数据库层环节 能够对各个环节的问 ...
- BPM端到端流程解决方案分享
一.需求分析 1.企业规模的不断发展.管理水平的不断提升,通常伴随着企业各业务板块管理分工更细.更专业,IT系统同样越来越多.越来越专 业化.不可避免的,部门墙和信息孤岛出现了,企业的流程被部门或者I ...
- Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键?
本文主要介绍WebRTC端到端监控(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信I ...
- 端到端 vs 点到点
比较(转自 百度经验) 端到端与点到点是针对网络中传输的两端设备间的关系而言的.端到端传输指的是在数据传输前,经过各种各样的交换设备,在两端设备问建立一条链路,就僚它们是直接相连的一样,链路建立后,发 ...
- 力软信息化系统快速开发框架 web端+winform端
力软信息化系统快速开发框架是一套集权限管理+快速开发+动态接口+通用组件+动态UI于一体的全新.net信息化快速开发框架.力软信息化系统快速开发框架的使用,大大地缩短了开发周期,提高了软件质量,同时也 ...
- 详解APM数据采样与端到端
高驰涛 云智慧首席架构师 据云智慧统计,APM从客户端采集的性能数据可能占到业务数据的50%,而企业要做到从Request到Response整个链路中涉及到的所有数据的准确采集,并进行有效串接,进而实 ...
- [Asp.net 开发系列之SignalR篇]专题二:使用SignalR实现酷炫端对端聊天功能
一.引言 在前一篇文章已经详细介绍了SignalR了,并且简单介绍它在Asp.net MVC 和WPF中的应用.在上篇博文介绍的都是群发消息的实现,然而,对于SignalR是为了实时聊天而生的,自然少 ...
随机推荐
- linux学习10 Linux目录结构和根文件系统全面讲解
一.回顾 1.如何获取使用帮助 help,--help,man,info 官方文档,自带文档(README,CHANGELOG,INSTALL),官方文档 发行版的文档 Google Linux Ke ...
- 4.学习springmvc的响应数据和结果视图
一.返回值分类: 字符串:返回值为需要展示的视图 void:返回为默认的页面(方法名.jsp) ModleAndView:存储对象并返回设置的页面 1.字符串: jsp: <a href=&qu ...
- 腾讯蓝鲸cmdb源码编译
腾讯蓝鲸 cmdb 源码编译环境依赖 环境包参考: golang >= 1.8 python >= nodejs >= (编译过程中需要可以连公网下载依赖包) Python 环境 w ...
- 可持久化0-1Trie树
我跟可持久化数据结构杠上了 \(QwQ\) .三天模拟赛考了两次可持久化数据结构(主席树.可持久化0-1Trie树),woc. 目录: 个人理解 时空复杂度分析 例题及简析 一.个人理解 可持久化0- ...
- pwd函数实现
/* * 文件名:mypwd.c * 描述: 实现简单的pwd命令 */ #include<stdio.h> #include<stdlib.h> #include<di ...
- 轮播模仿臭美APP,vue,swiper
介绍:轮播使用了swiper,重要用于移动端滑动,详情可查看官网 1.首先用npm安装 npm install swiper 2.main.js 中引入CSS import 's ...
- 享元模式(Flyweight Pattern)
定义: 采用一个共享来避免大量拥有相同内容对象的开销.这种开销中最常见.直观的就是内存的损耗.享元模式以共享的方式高效的支持大量的细粒度对象. 享元的英文是flyweight,是一个来自体育方面的专业 ...
- MIME类型和Java类型
MIME类型和Java类型 类型转换Spring Cloud Stream提供的开箱即用如下表所示:“源有效载荷”是指转换前的有效载荷,“目标有效载荷”是指转换后的“有效载荷”.类型转换可以在“生产者 ...
- [转]iview render函数常用总结(vue render函数)
原文地址:https://blog.csdn.net/weixin_43206949/article/details/89385550 iview 的render函数就是vue的render函数ivi ...
- pytorch 中conv1d操作
参考:https://blog.csdn.net/liujh845633242/article/details/102668515 这里我重点说一下1D卷积,2D卷积很好理解,但是1D卷积就不是那么好 ...