问题简介
大多数时候,当您需要为Web UI编写功能测试/端到端测试时,您最终会使用Selenium ,它可以被视为Java世界中用于Web UI测试的事实上的工具。 我确定您已经将其用于此类测试。
但是可能同时,您遇到了功能测试中一些最常见的问题,有些与Web UI测试有关,而其他则没有。
例如,人们通常在功能测试中发现的主要问题之一是环境的准备,运行测试以启动服务器并部署应用程序,然后安装/启动数据库,还可能是缓存系统等等。在所有服务器上运行,使用户可以在本地安装每个服务。 可能会发生一些错误,例如安装生产版本中使用的服务器的错误版本,重新使用可能与该版本不同的另一本地数据库安装,或者例如在生产版本中使用的不同JDK版本中运行它们。
但是,还有一些其他更特定于Web UI测试的问题,例如浏览器安装或WebDriver属性的配置。
解决第一个问题
为了解决第一个问题,您可以想到的最简单的解决方案是使用Docker容器,并且当然可以使用Docker组合,因为您可以定义和运行多容器Docker应用程序。 因此,基本上,您在docker-compose文件中定义了运行测试可能需要的所有服务器,因此在运行测试时,所有服务器都在运行,并且使用固定版本更为重要,因此可以确保测试始终在已知/期望的特定版本的服务器上运行,相同的JDK,……,而不取决于开发人员/ CI机器中安装了什么。
但是这种方法有一个问题。 您需要专门运行docker-compose up , docker-compose down。 当然,您可以在构建脚本中自动执行此操作,这将解决CI环境中的问题,但是如果开发人员希望通过IDE执行测试,例如调试,那么他需要意识到这一点。
这就是Arquillian Cube解决的问题。 Arquillian Cube是Arquillian扩展,它使用docker -compose文件启动和配置在那里定义的所有容器,执行测试并最终关闭所有这些容器。 好消息是,由于Arquillian使用JUnit(以及TestNG和Spock),您可以从IDE运行测试,而不必担心启动和停止容器,因为Docker生命周期由Arquillian Cube管理。
因此,定义测试环境的问题的第一部分已由Arquillian Cube修复。 让我们看看如何解决第二个问题。
解决第二个问题
Selenium项目为Docker映像提供了Selenium独立或带有浏览器(Firefox或Chrome)的Selenium节点以及已安装的VNC服务器。
因此,似乎很适合解决必须在本地安装具有具体版本或具体配置的浏览器的问题,因为您可以将docker映像与为测试配置的浏览器一起使用。
使用Docker进行测试时的新问题
那很酷,但是有一些问题。 第一个是您需要创建一个专门用于测试目的的docker-compose文件,尽管这本身并不是一件坏事,但是它需要开发人员进行更多的管理才能维护该文件,并且当然要一遍又一遍地重复在要使用它的所有项目中,定义要使用的浏览器和VNC客户端映像以获取记录以供将来检查。
第二个问题是WebDriver的配置。 针对远程浏览器运行WebDriver时,您需要设置浏览器的位置(IP)并根据需要的功能配置RemoteWebDriver。
因此,您必须一次又一次地在所有测试中编写WebDriver配置。 您可以创建一个工厂类,该类可以在所有项目中重用,这很好,但是仍然存在一个问题,一些开发人员可能会使用Docker计算机,因此IP不会是静态的并且可能每次都会更改,其他人可能正在使用本机Docker(例如,CI管道的某些阶段)可能会针对远程完整环境(如生产前环境)运行测试,因此在执行测试之前,您需要手动指定Docker主机容器的IP。
第三个问题是您需要指示WebDriver打开页面: webdriver.get(“ http://www.google.com”);
问题在于,在这种情况下,浏览器位于Docker基础架构内部,因此您需要设置服务器容器的内部IP,因此,您不仅需要知道用于连接远程Web驱动程序的Docker主机IP,还需要了解内部IP地址。使用以下命令在远程浏览器中打开页面的服务器容器的IP
获取方法。 同样,这可能很难以自动方式获得。
但是,使用Arquillian Drone和Arquillian Cube之间的新集成解决了所有这些问题。
解决新问题
Arquillian Drone是Arquillian扩展,它将Selenium WebDriver集成到Arquillian。 此扩展程序管理WebDriver的配置,因此您不需要在所有测试中都重复它,也不需要在浏览器的生命周期中重复它。
因此,如您所见,这对扩展似乎很适合解决这些问题。 无人机负责配置,而Cube负责正确配置Selenium / VNC容器并启动和停止它们。
如您所见,您无需担心创建用于测试目的的docker-compose文件。 您只需要创建一个用于部署的数据库,其余的将由Arquillian负责。
例
首先要做的是创建一个具有必需依赖项的项目。 对于此示例,我们使用Maven,但您可以使用其他构建工具来实现相同的目的。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.lordofthejars.helloworld</groupId><artifactId>dronecube</artifactId><version>1.0-SNAPSHOT</version><dependencyManagement><dependencies><!-- Use BOMs to set same versions in all dependencies --><dependency><groupId>org.jboss.arquillian</groupId><artifactId>arquillian-bom</artifactId><version>1.1.11.Final</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.jboss.arquillian.extension</groupId><artifactId>arquillian-drone-bom</artifactId><version>2.0.0.Final</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.jboss.arquillian.selenium</groupId><artifactId>selenium-bom</artifactId><version>2.53.1</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!-- Use standalone mode in Arquillian (no @Deployment) --><dependency><groupId>org.jboss.arquillian.junit</groupId><artifactId>arquillian-junit-standalone</artifactId><scope>test</scope></dependency><!-- Cube dependencies --><dependency><groupId>org.arquillian.cube</groupId><artifactId>arquillian-cube-docker</artifactId><version>1.0.0.Alpha13</version><scope>test</scope></dependency><dependency><groupId>org.arquillian.cube</groupId><artifactId>arquillian-cube-docker-drone</artifactId><version>1.0.0.Alpha13</version><scope>test</scope></dependency><dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><version>3.5.2</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- Drone dependencies --><dependency><groupId>org.jboss.arquillian.extension</groupId><artifactId>arquillian-drone-webdriver-depchain</artifactId><type>pom</type><scope>test</scope></dependency></dependencies></project>
需要注意的重要一点是,您正在使用BOM表定义来设置组件的版本。 然后我们设置Arquillian Standalone依赖项,因为我们的测试不会
@Deployment方法,因为已经在应用程序中使用的Docker映像内创建了部署文件。 最后,添加Arquillian Cube和Arquillian Drone依赖项。
下一步是在src / test / resources创建一个名为arquillian.xml的文件,该文件用于配置扩展。
<?xml version="1.0"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://jboss.org/schema/arquillian"xsi:schemaLocation="http://jboss.org/schema/arquillianhttp://jboss.org/schema/arquillian/arquillian_1_0.xsd"><extension qualifier="docker"><!-- Not required if native docker or only one docker machine installed --><property name="machineName">dev</property><!-- Not required if file is in root of classpath --><property name="dockerContainersFile">docker-compose.yml</property></extension></arquillian>
您可以看到:
- 如果使用docker机器,则需要指定docker机器名称来启动容器。 如果使用本地Docker,则无需设置此属性。
- 您需要设置相对于docker-compose文件所在项目的根文件夹的位置。 请注意,您可以使用任何其他名称。
您可以自定义WebDriver以及配置Arquillian Drone( https://docs.jboss.org/author/display/ARQ/Drone ),但是对于此测试,默认值就足够了。 请注意,现在默认浏览器是firefox 。
重要信息 :如果您正在使用本机Linux Docker安装,请注释machineName的配置行。 如果您使用的是docker机器,并且与dev叫不同,那么请适应
arquillian.xml中的 machineName也是如此。
下一步是在根目录下创建docker-compose文件。
helloworld:image: lordofthejars/helloworldgoports:- "8080:80"
简单的撰写文件,仅定义一个容器。 该容器公开了80端口,但随后绑定到8080端口。此容器启动Go程序,侦听根上下文并返回
HTML格式的Hello World 。
最后是测试:
package org.lordofthejars.cubedrone;import org.arquillian.cube.CubeIp;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;import java.net.MalformedURLException;
import java.net.URL;import static org.assertj.core.api.Assertions.assertThat;@RunWith(Arquillian.class)
public class HelloWorldTest {public static final int EXPOSED_PORT = 80;// Enrich with webdriver configured to connect to remote browser@DroneWebDriver webDriver;// Enrich with helloworld container ip@CubeIp(containerName = "helloworld")String ip;@Testpublic void shouldShowHelloWorld() throws MalformedURLException, InterruptedException {// Constructs url that browser should connectURL url = new URL("http", ip, EXPOSED_PORT, "/");// Typical test using WebDriverwebDriver.get(url.toString());final String message = webDriver.findElement(By.tagName("h1")).getText();assertThat(message).isEqualTo("Hello World");}}
此测试中有一些有趣的部分。
- 从使用Arquillian跑步程序的意义上来说,这是标准的Arquillian测试。
- 使用Arquillian Drone提供的@Drone注入机制,通过配置为连接到远程浏览器的WebDriver来丰富测试。
- 使用@CubeIp注释使用容器helloworld的内部IP丰富测试。 由于浏览器在Docker主机中运行,因此我们可以使用内部IP来实现此目的。 同样重要的是,您需要使用裸露的端口而不是绑定端口。
- 其他所有内容都由Arquillian Cube管理,例如Docker容器的启动和停止(在本例中为helloworld ),但也包含浏览器和VNC客户端的容器。 如果将调试点放入测试方法中,然后在终端上执行docker ps ,您将看到启动了三个容器,而不仅仅是helloworld 。
- 如果在运行测试后检查了target / reports / videos目录,则会找到该测试的录像。
您还可以观看此操作的截屏视频:
因此,如您所见,结合使用Arquillian Cube和Arquillian Drone可以使您的测试和docker -compose文件看起来非常整洁。 测试仅包含与测试相关的内容,而与WebDriver配置无关。 同样,您的docker-compose看起来也很清晰,它仅包含与业务相关的内容,与测试无关。
在本文中,您已经了解了如何使用Arquillian Cube + Arquillian Drone。 在下一个中,您将看到与Arquillian Graphene的集成,它将把测试简化为仅专注于测试而不是WebDriver调用。
翻译自: https://www.javacodegeeks.com/2016/08/making-web-ui-testing-great-arquillian-docker-selenium-part-1.html