使用模拟时间对周期性协程进行单元测试 [英] Unit-testing a periodic coroutine with mock time

查看:42
本文介绍了使用模拟时间对周期性协程进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Tornado 作为周期性进程的协程引擎,其中重复的协程在每次执行结束时自行调用 ioloop.call_later().我现在正在尝试通过单元测试(使用 Tornado 的 gen.test)来驱动它,我用局部变量 t 来模拟 ioloop 的时间:DUT.ioloop.time = mock.Mock(side_effect= lambda: t)(DUT <==> 被测设备)然后在测试中,我手动增加 t,并yield gen.moment 来启动 ioloop.这个想法是在不同的时间间隔后触发重复的协程,这样我就可以验证它的行为.但是协程并不总是触发 - 或者它可能在完成执行之前屈服于测试代码,从而导致失败.我认为应该使用 stop()wait() 来同步测试代码,但我看不出在这种情况下具体如何使用它们.如果 DUT 在自己的 ioloop 中运行,那么整个测试策略如何工作?

I'm using Tornado as a coroutine engine for a periodic process, where the repeating coroutine calls ioloop.call_later() on itself at the end of each execution. I'm now trying to drive this with unit tests (using Tornado's gen.test) where I'm mocking the ioloop's time with a local variable t: DUT.ioloop.time = mock.Mock(side_effect= lambda: t) (DUT <==> Device Under Test) Then in the test, I manually increment t, and yield gen.moment to kick the ioloop. The idea is to trigger the repeating coroutine after various intervals so I can verify its behaviour. But the coroutine doesn't always trigger - or perhaps it yields back to the testing code before completing execution, causing failures. I think should be using stop() and wait() to synchronise the test code, but I can't see concretely how to use them in this situation. And how does this whole testing strategy work if the DUT runs in its own ioloop?

推荐答案

一般来说,使用 yield gen.moment 来触发特定事件是很冒险的;不能保证您必须等待多少时刻",或者触发事件发生的顺序.最好确保被测试的函数有一些可以异步等待的效果(如果它自然没有这种效果,可以使用一个tornado.locks.Condition).

In general, using yield gen.moment to trigger specific events is dicey; there are no guarantees about how many "moments" you must wait, or in what order the triggered events occur. It's better to make sure that the function being tested has some effect that can be asynchronously waited for (if it doesn't have such an effect naturally, you can use a tornado.locks.Condition).

修补IOLoop.time 也有一些微妙之处.我认为它可以与默认的 Tornado IOLoops 一起使用(在不使用 mock 的情况下是可能的:在构造循环时传递一个 time_func 参数),但它不会具有所需的效果,例如AsyncIOLoop.

There are also subtleties to patching IOLoop.time. I think it will work with the default Tornado IOLoops (where it is possible without the use of mock: pass a time_func argument when constructing the loop), but it won't have the desired effect with e.g. AsyncIOLoop.

我认为您不想使用 AsyncTestCase.stop.wait,但不清楚您的测试是如何设置的.

I don't think you want to use AsyncTestCase.stop and .wait, but it's not clear how your test is set up.

这篇关于使用模拟时间对周期性协程进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆