我正在使用面向软件的架构,该架构有多个芹菜工人(我们称之为worker1
,worker2
和worker3
)。所有三个工作者都是独立的实体(即,单独的代码库,单独的存储库,单独的芹菜实例,单独的机器),并且它们都没有连接到Django应用程序。
与这三个工作者中的每一个进行通信是基于Django的MySQL支持的RESTful API。
在开发过程中,这些服务都在一个流浪盒上,每个服务器都作为一个独立的机器运行。我们有一个RabbitMQ代理可以完成所有Celery任务。
通过这些服务的典型路径可能如下所示:worker1
从设备获取消息,进行一些处理,在worker2
上排队任务,进行进一步处理并进行POST到API
,它写入MySQL数据库并触发worker3
上的任务,该任务执行一些其他处理并对API
进行另一次POST,从而导致MySQL写入。
服务正在很好地沟通,但每次我们对任何服务进行更改时测试此流程都非常烦人。我真的希望得到一些完整的集成测试(即,从发送到worker1
并通过整个链的消息开始),但我不知道从哪里开始。我面临的主要问题是:
如果我在worker1
上排队,我怎么能分辨出整个流程何时结束?当我不知道结果是否已经到达时,我怎样才能对结果做出合理的断言?
如何处理数据库设置/拆除?我希望在每次测试结束时删除测试期间所有条目,但如果我从Django应用程序外部开始测试,我不确定如何有效地清除它。手动删除它并在每次测试后重新创建它似乎可能是太多的开销。
答案 0 :(得分:3)
Celery允许同步运行任务,因此第一步是:将整个流程划分为单独的任务,伪造请求和断言结果:
原始流程:
device --- worker1 --- worker2 --- django --- worker3 --- django
第一级集成测试:
1. |- worker1 -|
2. |- worker2 -|
3. |- django -|
4. |- worker3 -|
5. |- django -|
对于每个测试,创建虚假请求或同步调用并断言结果。将这些测试放在相应的存储库中例如,在worker1的测试中,您可以模拟worker2并测试它是否已使用适当的参数调用。然后,在另一个测试中,您将调用worker2和模拟请求来检查它是否正确调用API。等等。
测试整个流程将很困难,因为所有任务都是独立的实体。我现在唯一想到的方法就是对worker1进行一次虚假调用,设置合理的超时并等待数据库中的最终结果。此类测试仅告诉您它是否有效。它不会告诉你,问题出在哪里。
答案 1 :(得分:0)
要使用完整设置,您可以设置Celery结果后端。 有关基础知识,请参阅Celery 'next steps'文档。
然后, worker1
可以报告传递给worker2
的任务句柄。
worker2
返回的结果将是传递给worker3
的任务ID。
worker3
返回的结果意味着整个序列已完成,您可以检查结果。
结果还可以立即报告这些结果的有趣部分,以便更容易进行检查。
这可能在Celery中看起来像一样:
worker1_result = mytask.delay(someargs) # executed by worker1
worker2_result = worker1_result.get() # waits for worker1 to finish
worker3_result = worker2_result.get() # waits for worker2 to finish
outcome = worker3_result.get() # waits for worker3 to finish
(细节可能需要不同;我自己还没有使用过。我不确定任务结果是否可序列化,因此它们本身适合作为任务函数返回值。)