如果您搜索什么是页面对象的描述,就会发现页面对象模式为我们提供了一种以可重用和可维护的方式对内容建模的常识方法。
还要指出:在Web应用程序的UI中,您的测试与某些区域交互。 Page Object只是将它们建模为测试代码中的对象。
这减少了重复代码的数量,并且意味着如果UI更改,则仅需要在一个地方应用此修复程序。
如您所见, Page Object适用于UI元素。 我们( Arquillian社区)在Page Object模式逻辑之后创造了一种新模式,称为Container Object模式。
您可以将“ 容器对象”视为您的测试可能与之交互的容器区域(现在为Docker容器)。 例如,其中一些领域可能是:
- 获取运行容器的主机IP。
- 给定暴露端口的有界端口。
- 在配置文件(Dockerfile)中配置的任何参数,例如用于访问容器公开的服务的用户或密码。
- 容器的定义。
一个容器对象内部可能包含多个容器对象的集合。 这有效地在容器之间建立了关系船(链接)。
例如,在容器中运行MySQL数据库的情况下,配置参数的示例可能是访问数据库的用户和密码。
请注意,没有什么可以阻止您生成用于从测试访问服务的正确URL,或阻止针对容器执行命令,例如检索内部文件。
当然,就像Page Object一样, Container Object为您提供了一种构建模型内容的方法,该模型内容可用于多个项目。
在研究如何在Arquillian Cube中实现此模式之前,我们先来看一个示例:
假设您所有的应用程序都需要将文件发送到FTP服务器。 要编写集成/组件测试,您可能需要一个FTP服务器来发送文件并检查文件是否已正确发送。
一种方法是在执行测试之前使用Docker启动FTP服务器,然后使用该Docker容器用于FTP服务器执行测试,然后再停止容器以检查文件是否存在,最后停止容器。
因此,所有涉及FTP服务器和容器的所有操作都可以在Container Object中加入。 该容器对象可能包含以下信息:
- 使用哪个图像
- 运行此FTP服务器的主机的IP和绑定端口
- 访问FTP服务器的用户名和密码
- 断言文件存在的方法
然后从测试的角度来看,它仅与该对象通信,而不是直接对测试内部的所有信息进行硬编码。
再次与Page Object中一样 ,容器上的任何更改都只会影响Container对象,而不会影响测试本身。
现在,通过一个非常简单的示例,看看Arquillian Cube如何实现Container Object模式:
Arquillian多维数据集和容器对象
让我们看一个简单的示例,说明如何在Cube中实现Container Object 。 假设您要创建一个容器对象,该对象封装了在Docker内部运行的乒乓服务器。
容器对象将类似于带有特殊注释的简单POJO:
@Cube(value = "pingpong", portBinding = "5000->8080/tcp") // <1>
@CubeDockerFile
public class PingPongContainer {@HostIp // <2>String dockerHost;@HostPort(8080) // <3>private int port;public URL getConnectionUrl() { // <4>try {return new URL(“http://” + dockerHost + “:” + port);} catch (MalformedURLException e) {throw new IllegalArgumentException(e);}}
}
在前面的示例中,您必须注意以下几行:
- @Cube注释配置Container Object 。
- 容器对象可以使用Arquillian浓缩器进行浓缩。
- 为给定的裸露端口注入有界端口。
- 容器对象隐藏了如何连接到PingPong服务器。
@Cube批注用于配置此Container对象 。 最初,您将启动的容器命名为pingpong,并设置容器实例的端口绑定信息,在本例中为5000→8080 / tcp 。
请注意,这可以是一个数组,用于设置多个端口绑定定义。
下一个注释是@CubeDockerFile ,它配置如何创建容器。 在这种情况下,请使用位于默认类路径位置的Dockerfile 。 默认位置是package + classname ,因此例如在以前的情况下, Dockerfile应该放置在org / superbiz / containerobject / PingPongContainer目录中。
当然,您可以通过将注解作为值传递来设置任何其他类路径位置。 CubeDockerFile批注设置找到Dockerfile的位置,而不是文件本身。
同样,该位置应该可以从ClassLoader到达,因此这意味着应该从类路径中加载它才能找到它。
任何多维数据集都可以使用任何客户端扩展器进行扩展 ,在这种情况下,可以使用@HostIp 优化器进行扩展 ,但是也可以使用@ArquillianResource通过DockerClient进行扩展 。
最后, @ HostPort用于将公开的端口转换为绑定的端口。
因此,在此示例中,端口值将为5000 。 您将简要了解为什么此批注很重要。
然后,您可以在测试中开始使用此容器对象:
@RunWith(Arquillian.class)
public class PingPongTest {@CubePingPongContainer pingPongContainer;@Testpublic void shouldReturnOkAsPong() throws IOException {String pong = ping();assertThat(pong, containsString("OK"));assertThat(pingPongContainer.getConnectionPort(), is(5000));}
}
这里最重要的是,您需要将Container Object设置为类的字段,并使用@Cube进行注释。
用Cube注释字段非常重要,因此Arquillian在运行测试之前,可以检测到它需要启动一个新的Cube (Docker容器),创建Container Object并将其注入测试中。
请注意,此批注与定义Container Object时使用的批注完全相同。
之所以这样,是因为您可以从测试端覆盖Container Object的任何属性。 这就是@HostPort批注很重要的原因,因为可以从测试定义中更改端口,所以您需要找到一种在容器对象内部注入正确端口的方法。
在这篇文章中,我介绍了容器对象模式以及如何在Arquillian Cube中使用 。 但这只是一个小尝试,您可以在以下位置阅读有关Arquillian Cube和Container Object集成的更多信息:
- https://github.com/arquillian/arquillian-cube#arquillian-cube-and-container-object
还可以在以下位置找到运行示例:
- https://github.com/arquillian/arquillian-cube/tree/master/docker/ftest-docker-containerobject
翻译自: https://www.javacodegeeks.com/2016/01/container-object-pattern-new-pattern-tests.html