在为项目开发测试时,您迟早可能会遇到某些测试随机失败的情况。这些测试,也称为零散测试,非常令人不快,因为您永远不知道失败是随机的,还是代码中存在倒退。在最坏的情况下,您只是忽略这些测试,因为您知道它们是不靠谱的。大多数测试框架甚至有专门的注释或其他方法来表示测试是不可靠的,如果它失败了,应该忽略失败。这种测试的价值是很值得怀疑的。对于这样的测试,您能做的最好的事情当然是修复它,这样它就不会随机失败。说起来容易,做起来难。最困难的部分通常是使测试在开发环境中失败,以便您可以调试它,并了解它失败的原因以及失败的根本原因是什么。在这篇博客文章中,我将尝试展示一些技术,这些技术可以帮助您在本地机器上模拟随机测试失败。

根据我的经验,测试随机失败的最常见原因是没有正确清理环境或环境缓慢。这两种情况在CI环境中都很常见。由于干扰其他测试而导致的失败在过去更为常见。如今,当虚拟机和容器的使用非常普遍时,这通常不是问题。此外,由各种CI即服务产品实现的测试隔离也做得很好。将CI作为服务使用的缺点是,您通常不能登录到机器并在那里调试测试。因此,您必须启用调试日志并等待下一次失败,或者猜测原因是什么,并尝试在本地机器上模拟它。

CI环境中随机故障最常见的根本原因是各种类型的慢。这是虚拟环境中过度使用资源或虚拟机/容器上的资源限制的结果。因此,在本地模拟随机测试失败的最强大的方法之一是限制本地环境中的测试资源。让我们看看常见的选项是什么以及如何做到这一点。

在一个线程中运行测试

减慢测试速度的一种可能方法是在单个线程或有限数量的线程上执行测试,特别是当您有一个多线程应用程序时。在Linux操作系统上,使用taskset命令。taskset告诉Linux调度器将给定进程附加到指定的CPU核心。运行例如Debezium开云体育官方注册网址 MySQLTransactionMetadataIT在一个CPU内核上,你只需要运行

taskset -c 0 mvn verify -DskipTests -Dit.test=开云体育官方注册网址DebeziumEngineIT

它将在CPU #0上执行测试。

限制容器资源

在Debezi开云体育官方注册网址um项目中,我们大量使用容器进行测试。我们根据容器中运行的测开云体育电动老虎机试运行数据库。我们经常需要的不是减慢测试本身,而是减慢数据库。开云体育电动老虎机Docker提供了很多选项如何限制容器资源。最有用的通常是限制CPU的使用——cpu参数。这允许我们限制Docker用于运行容器的CPU数量。这里的好处是它可以是一个浮点数,所以你可以通过设置限制容器只使用一半的CPU时间——cpu = 0.5.以类似的方式,你也可以限制其他资源,如RAM。

常见的Debezium开云体育官方注册网址工作流是从Maven运行容器,使用Docker Maven插件.插件提供属性的长列表可以对其进行配置,包括用于限制容器资源的属性。然而,这个选项有一个警告。在当前版本中,docker.cpus预计长数而不是float,它的意思是,容器在一秒周期中可以占用多少CPU纳秒。例如,相当于——cpu = 0.5是:

mvn docker:start -Ddocker.cpus=500000000

这个问题是固定应该会出现在下一个Docker Maven插件版本中,所以一旦Debezium升级到下一个版本,你应该就可以使用了开云体育官方注册网址docker.cpus与从命令行运行容器时使用的方法相同。其他Docker Maven插件属性,例如:docker.memory应该按预期工作。

施加网络延迟

随机测试失败的另一个常见来源是网络延迟。可能没有任何简单的方法在本地机器上模拟它,必须使用某种代理。幸运的是,有一个代理正是为了这个目的-Toxiproxy.它是模拟各种网络故障和延迟的专用代理。它有一个丰富的功能集,而且它很容易设置,所以使用它是一种乐趣。让我们看看如何在本地机器上使用Debezium测试来设置它。开云体育官方注册网址

您可以在本地安装Toxiproxy(在Fedora上运行Sudo DNF安装有毒代理)或在容器中下载:

Docker拉ghcr.io/shopify/toxiproxy

我们将在容器中运行Toxiproxy,但是在本地安装它也很方便,因为它包含一个CLI实用程序,可以向Toxyproxy发送命令。否则,我们将不得不从容器中运行命令。为简单起见,我们将使用本地安装的CLI工具。Toxyproxi允许我们通过HTTP发送命令,并监听端口8474。因此,当我们启动Toxyproxy时,我们需要公开这个端口。我们需要公开的另一个端口是Toxiproxy将充当其代理的数据库的端口。开云体育电动老虎机在我们的例子中,我们将使用MySQL,因此我们需要公开端口3306。当然,我们可以使用任何其他端口,但在这种情况下,我们将需要向Debezium测试传递额外的参数,即开云体育官方注册网址开云体育电动老虎机database.port指向Toxiproxy暴露的端口。同样,为了简单起见,我们还是使用默认端口3306。此外,由于我们将从本地机器(而不是容器)运行Debezium测试,开云体育官方注册网址我们需要将Toxiproxy附加到本地主机网络,该网络默认有名称宿主.把所有东西放在一起,我们可以运行Toxiproxy容器,如下所示:

Docker运行——rm -p 8474:8474 -p 3306:3306——net=host -it ghcr.io/shopify/toxiproxy

现在我们还必须启动数据库。开云体育电动老虎机由于3306端口已经被Toxiproxy占用,所以我们不得不选择另外一个端口,比如3307:

mvn docker:start -Dmysql.port=3307

最后缺少的部分是告诉Toxiproxy应该为哪些端口创建代理。在我们的例子中,它来自端口3306(监听端口)- l)至3307(上行端口- u):

创建mysql -l 0.0.0.0:3306 -u 0.0.0.0:3307

这个命令在Toxiproxy中创建一个新的代理,称为mysql.可以有多个代理。我们可以通过运行列出所有代理

toxiproxy-cli列表

输出如下:

美元toxiproxy-cli列表名字听上游使毒物  ====================================================================================== mysql[:]: 3306 0.0.0.0:3307没有启用

现在让我们尝试一下,如果一切正常,并运行一些测试:

mvn verify -DskipTests -D开云体育电动老虎机database。宿主name=localhost -Pskip-integration-tests -Dit.test=TransactionMetadataIT

一切都应该正常运行,因为我们还没有产生任何毒性(延迟或故障)。它只是检查代理是否正常工作。如果一切顺利,让我们现在创造一个有毒的:

Toxiproxy-cli toxic add mysql——type latency——attribute latency=500 -n mysql_latency

这将在mysql代理上增加500毫秒的网络延迟。“有毒的”被命名为“mysql_latency”。

您可以通过运行命令获取有关指定代理的更多详细信息检查命令:

检查mysql

输出如下:

美元toxiproxy-cli检查mysql名称:mysql听:[:]:3306上游:0.0.0.0:3307  ====================================================================== 上游毒物:代理没有上游毒物启用。下游毒性:mysql_latency: type=latency stream=下游毒性=1.00 attributes=[jitter=0 latency=500]

现在,再次运行测试。您是否注意到测试运行的时间大大延长了?如果是,一切都按预期工作,因为我们为每个对数据库的调用添加了延迟。开云体育电动老虎机

这是一个将toxic添加到Toxiproxy的简单示例。Toxiproxy提供了更多配置毒物的选项和方法。看到Toxiproxy欲知详情。

一旦我们完成了,我们就可以移除有毒物质

删除mysql -n mysql_latency

以及代理本身:

删除mysql

或者干脆停止并删除容器。

总结

在这篇博客文章中,我试图展示一些技术,这些技术可以帮助您在本地模拟不可靠的测试失败。它们都试图降低测试环境的响应性,即通过使用Toxiproxy限制CPU或施加网络延迟。在应用程序堆栈的许多部分,还有许多其他原因导致测试不稳定,而且还有许多其他工具可以注入各种类型的故障(例如磁盘故障)。所以这篇文章还不够详尽。但是我希望它将帮助您调试至少一些不可靠的测试,如果不是在Debezium项目中,那么至少是在您自己的项目中。开云体育官方注册网址

所有这些东西,尤其是Toxiproxy,也可以定期使用,甚至在CI中也可以使用,以发现项目中的各种隐藏问题,这些问题只有在它运行的环境表现不好时才会出现。

请在讨论中分享关于如何调试不可靠测试的任何其他技巧,以及您认为方便的工具类型。

Vojtěch Juranek

Vojta是红帽公司的软件工程师。他住在捷克共和国。


关于Debe开云体育官方注册网址zium

开云体育官方注册网址Debezium是一个开源的分布式平台,它将现有数据库转换为事件流,因此应用程序几乎可以立即看到并响应数据库中提交的每一个行级更改。开云体育电动老虎机开云体育官方注册网址Debezium是建立在卡夫卡并提供卡夫卡连接监控特定数据库管理系统的兼容连接器。开云体育电动老虎机开云体育官方注册网址Debezium在Kafka日志中记录了数据更改的历史,所以你的应用程序可以在任何时候停止和重新启动,并且可以很容易地使用它没有运行时错过的所有事件,确保所有事件都被正确和完整地处理。开云体育官方注册网址Debezium是开源Apache许可证,版本2.0

参与

我们希望您觉得Debezium有趣开云体育官方注册网址且有用,并愿意尝试一下。在Twitter上关注我们@开云体育官方注册网址debezium在Zulip上和我们聊天,或加入我们的邮件列表与社区对话。所有的代码都是开源的GitHub上,因此在本地构建代码并帮助我们改进现有连接器并添加更多连接器。如果您发现了问题或对我们如何改进Debezium有想法,请告诉我们开云体育官方注册网址记录问题

Baidu
map