下午好
根据上一篇文章的说明,在安装和配置CI / CD后几乎立即,团队就如何正确进行集成测试提出了一个问题。 我们已经有在docker容器中运行测试依赖项的经验,但是自从程序集本身已在容器中启动以来,这已经成为问题。 在本文中,我想描述两种适合我团队的容器内集成测试的可能方法。
集成测试要求
根据定义,集成测试是一种测试应用程序及其相关组件的操作的测试。 示例包括数据库,队列和其他服务。
作为测试的一部分,我们希望:
- 在本地和詹金斯上平均运行测试
- 避免预安装和配置依赖应用程序
- 使用项目存储库中的文件声明和运行依赖项
- 能够并行运行多个程序集
- 建议将来能够添加新的依赖项
- 建议能够使用相同依赖项的不同版本进行测试
基于这些要求,由于程序集之间共享资源的问题,维护和更改此基础结构的困难,我们立即放弃了永久永久安装测试数据库和队列的想法。
选项1:嵌入式解决方案
java生态系统中有很多运行测试依赖项的库:
这种方法尽可能简单,并且可以满足前面描述的大多数要求,但是在添加新的测试依赖项(mysql?)或使用特定或多种版本的依赖项方面不是通用的。
非常适合具有1-2个依赖项的简单服务。
选项2:测试容器
Docker是解决以前方法缺点的合乎逻辑的方法:您可以查找(或创建Docker映像)任何版本的依赖项。 生产中的某些依赖项可能正在使用相同的映像运行。
如果本地启动映像(或使用docker-compose多次启动)不是问题,则CI会遇到困难,因为程序集本身是在容器中进行的。 尽管可以在docker中运行docker,但dind creator不建议这样做 。 解决此问题的首选方法是重用已经运行的docker进程,通常称为同级docker。 为此,您需要子Docker进程使用父级的/var/run/docker.sock
。 在上一篇文章中,这已用于通过已编译的应用程序发布Docker映像。
由于以下原因,决定使用testcontainers库:
- 提供良好的依赖管理API
- 与最流行的数据库和队列集成
- 在容器中运行时使用同级docker方法
- 在本地和ci上工作相同
- 组装后停止容器
非常适合于更复杂的服务或具有特殊依赖性要求的服务。
资源管理
接下来,您应注意项目组装的资源消耗(添加集成测试后,资源消耗可能会显着增加)。
目前,程序集未指示所需的内存和cpu份额数量,这可能是两个潜在的问题:
- 首先是同一台机器上的并行装配过多,这将导致较高的负载系数。 大会可能会过去,但是他们将花费更多的时间。
- 第二个是OOM杀死。 Kubernetis可能会决定您占用了太多内存,并且只会在程序集完成之前将其杀死。
您可以使用以下结构限制炉膛中容器的资源:
resources: requests: cpu: 1 memory: 512Mi limits: cpu: 1 memory: 512Mi
Jdk9及更高版本已经支持在容器中工作(-XX:+ UseContainerSupport(默认情况下启用),与-XX:InitialRAMPercentage / -XX:MaxRAMPercentage结合使用)
一个完整的例子可以在这里找到。
为了使Jdk8正常工作,需要使用-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
更新131或更高版本,该-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
从cgroup而不是从主机读取可用内存,或者每次使用Xmx
手动指定可用堆大小。
这里有一个例子。
值得注意的是,kubernetes对使用testcontainer或同级docker运行的容器所花费的资源一无所知。 为了在这种情况下正常工作,可以考虑所有测试依赖项,在maven容器中保留资源。
结论
在容器中启动构建时进行集成测试是可行的,而不是一项艰巨的任务。
您可以在此处找到使用testcontainer进行集成测试的示例应用程序,以及在kubernetes上运行Jenkins的配置。