我应该在Docker映像中包含测试吗?


19

关于测试,我可以想到两个选择:

  1. 将测试和应用程序放在一张图中。
  2. 在图像中仅包含应用程序代码。创建一个特定于测试的容器,该容器在主映像之后构建并向其添加一些层(测试代码,依赖项等)。

使用第一个选项,我可以测试容器并按照测试的要求完全运送它。明显的缺点是不必要的代码(以及潜在的测试数据)将包含在图像中。

使用第二种选项时,出厂的图像与测试的图像不太相同。

两者看起来都是错误的策略。有没有第三种更好的策略?


1
您基本上回答了自己。两者都是不好的主意。您将已经测试过的可运行流程运送到一个大小和根据需求定制的容器中。您既不需要开发依赖,也不需要src代码。在生产中将其视为风险。
Laiv

1
在容器化之前进行测试意味着不对环境进行测试,仅对代码进行测试。您只测试了所运输产品的一部分,而不是全部。
lfk

Answers:


10

对于运行构建时测试,首选方法是使用多阶段构建。多阶段Dockerfile允许您将具有所有依赖项的较大阶段用于构建和测试,然后将测试的确切工件复制到另一个阶段,以生成较小的运行时映像。

您还希望使用多个容器的外部接口而不是在容器中运行对它们进行系统级测试。由于这些测试涉及服务之间的协调,需要不同的依赖项(例如对业务流程的访问),不像构建时测试那样彻底,并且无论如何都是用完全不同的语言编写的,因此从单独的Docker运行它们并不重要专门用于系统测试的容器。


1
因此,这几乎是选项2-我在与生产非常相似但又不太相同的环境/容器中运行测试。那正确吗?
lfk

9

正如您自己所说的,还有第三种方式。我认为您正在混合开发,测试和部署。我建议从整体上看待整个SDLC,以了解您要实现的目标。这是一个很大的话题,但我会尽力总结一下。

TL; DR;

简而言之,您需要分开:

  • 您的代码,来自
  • 应用程序配置,来自
  • 系统环境配置。

每个都需要彼此独立并且适当地:

  • 版本控制
  • 经过测试
  • 可部署

较长的版本

首先,您有一个由代码和(单独的配置集)组成的应用程序。这需要针对构建功能和有意功能进行测试-这称为连续集成(CI)。在线和本地都有许多此类服务的提供程序,例如,用于云提供程序的CircleCI,它会链接到您的存储库并在您提交时进行构建和测试。如果您的存储库为本地存储,并且无法使用云提供商,则例如Jenkins将是等效的。如果您的应用程序相当标准,则可能存在CI服务可以使用的现有Docker映像。如果不是这样,您将必须创建一个或一个这样的集群,以便将您的应用程序代码和配置部署到其中。正确配置后,您将获得大量有关应用程序代码质量的统计信息。

接下来,一旦您对应用程序的功能和正确性感到满意,就应该为特定版本适当地标记代码库。然后应将此构建部署到测试环境。请注意,该代码将与在CI中测试的代码相同(如果正确执行,则可以证明是相同的),但是配置可能有所不同。同样,某些CI提供程序可以提供此步骤,以便您可以测试打包的应用程序和离散配置的部署。此阶段通常将包括用户功能测试(针对新功能)以及自动化测试(针对已知功能)。如果发行版通过了此阶段,则您有候选发行版用于集成测试。您可以从另一个Docker容器运行自动化测试,一些度量标准表明状态测试工作量与编码工作量是1:1(尽管我不确定自己是什么)。

倒数第二,下一步是在构建(系统)环境时就好像在生产环境一样。如果您在生产中使用Docker,则将在这里考虑安全性加强,网络和服务器优化等。您的Docker映像可能基于您在Development中使用的映像(理想情况下是这样),但可能会在缩放和安全性方面有所变化, 就像我说的。到现在,应用程序的功能测试应该已经完成​​,您将更加关注安全性和性能。根据功能测试,此处的测试可以从其他Docker映像进行开发,部署和运行。此步骤过去非常昂贵,很少这样做,因此您需要使用专用硬件来复制生产。如今,这完全可行,因为您可以按需站起来拆除几乎任何规模的整个环境。

最后,您应该发布一个发布版本,该发布版本应该仅具有集成测试中的一小部分配置增量(IP地址,数据库URI,密码等)。此时,您的代码库至少已在三个不同的环境中进行了测试点和大多数系统配置至少一次。


这是否意味着您的CI根本不会测试您的Dockerfile?例如,如果您的Dockerfile缺少依赖项,测试是否仍会通过?
lfk

1
一点也不。首先测试代码,然后测试应用程序配置,然后测试系统。我的意思是,这些活动是离散的。容器化的伟大之处在于,在与产品相同的环境中进行开发的梦想非常接近。但是,硬化会使开发变得太困难。
avastmick

0

我认为您正在混淆各种测试。基本上,您需要问自己:这里要测试的单元是什么?

当您作为开发人员工作时,最常见的情况是为您正在处理的某些代码编写单元/集成测试,其中该代码段是被测单元。您可以在本地和/或CI中运行这些测试。

构建新的Docker映像后,它将成为可以测试的新单元。您想为这张图片测试什么样的东西?它提供了什么API?您如何测试?

如果是Web应用程序,则可以基于图像启动容器,并执行一些HTTP请求,并检查响应是否符合您的期望。我认为您遇到的问题是,您非常习惯将测试框架与应用程序代码耦合在一起。在开发过程中很好,但是现在您想要测试docker映像,因此您需要一种新型的测试框架,该框架可以做到这一点,并且与应用程序代码无关。

因此,我认为您正在寻找的第三个选择是:

  • 在构建docker映像之前运行单元/集成测试。
  • 构建仅包含要分发的应用程序的docker映像。
  • 无需在该应用程序映像之上添加其他层,而是通过使用某些给定参数运行它并声明您的预期输出来对其进行原样测试。

因此,CI / CD步骤为:

设置开发环境->在代码上运行测试->构建最终映像->在映像上运行测试->部署映像。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.