如何使用pytest测试无限while循环 [英] How to test an infinite while loop with pytest

查看:237
本文介绍了如何使用pytest测试无限while循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在编写一个与竹构建服务器交互的小库.测试是使用 pytest 完成的.我陷入了以下问题.我想测试一个运行直到满足某些状态的 while 循环.阅读 pytest 文档,我试图模拟"/monkeypatch 状态,但它并没有真正起作用.我可能在这里做错了一些基本的错误:这是有问题的while循环:

I am currently writing a little lib that interacts with a bamboo build server. Testing is done using pytest. I got stuck at the following problem. I want to test a while loop that runs till some status is satisfied. Reading the pytest doc, I tried to "mock" / monkeypatch the status, but it doesnt really work. I am probably doing something elementary wrong here: This is the while loop in question:

    # determine current status
    running = self._is_a_build_running()

    # turn on and off running powerplug while building
    while running:
        self.feedback.turn_off_success()
        self.feedback.turn_on_running()
        time.sleep(self.blinker_time)
        self.feedback.turn_off_running()
        self._update_builds_status()
        running = self._is_a_build_running()

所以我用 pytest 尝试的是为正负 _is_a_build_running 创建一个固定装置,如下所示:

so what I tried with pytest was creating a fixture for a positive and a negative _is_a_build_running like this:

@pytest.fixture(scope='function')
def mock_is_a_build_running():
    return False

然后使用 ThreadPool 使用此测试方法(在此处解释 如何从 python 中的线程获取返回值?) 因为我还需要包含 while 循环的方法的结果.

and then using this test method using a ThreadPool (explained here how to get the return value from a thread in python?) because I also would need a result from the method containing the while loop.

def test_update_status_running(bamboopickups, monkeypatch,
                   mock_update_overall_data_positive,
                   mock_update_builds_status_positive,
                   mock_is_a_build_running):
monkeypatch.setattr('BambooPickup._update_overall_data', lambda x: mock_update_overall_data_positive)
monkeypatch.setattr('BambooPickup._update_builds_status', lambda x: mock_update_builds_status_positive)

pool = ThreadPool(processes=1)
async_result = pool.apply_async(bamboopickups.update_status())

monkeypatch.setattr('BambooPickup._update_overall_data', lambda x: mock_update_overall_data_positive)
monkeypatch.setattr('BambooPickup._is_a_build_running', lambda x: mock_is_a_build_running)

actual = async_result.get()
expected = True
assert actual == expected

这可能很容易用 pytest-mock 完成,但到目前为止我只使用这里描述的首选方式:http://pytest.org/latest/monkeypatch.html.

This is probably easily done with pytest-mock, but so far I was only using the prefered way described here: http://pytest.org/latest/monkeypatch.html.

推荐答案

所以,在进一步深入研究之后,我找到了一个目前令我满意的解决方案.我想分享它,以防其他人遇到同样的问题.实际上它非常简单,并且带有来自 https://gist.github.com/daltonmatos/3280885 的一些帮助类 我想出了以下测试代码:

So, after some more digging into the matter, I found a solution which satisfies me for now. I want to share it, in case anyone else runs into the same problem. Actually it is quite simple, and with some helper class from https://gist.github.com/daltonmatos/3280885 I came up with the following testcode:

def test_update_status_running(bamboopickup, monkeypatch,
                               mock_update_overall_data_positive,
                               mock_update_builds_status_positive):
    monkeypatch.setattr('pickups.bamboo.bamboopickup.BambooPickup._update_overall_data', lambda x: mock_update_overall_data_positive)
    monkeypatch.setattr('pickups.bamboo.bamboopickup.BambooPickup._update_builds_status', lambda x: mock_update_builds_status_positive)

    with mock.patch.object(bamboopickup, '_is_a_build_running') as mockfoo:
        mockfoo.return_value = AlmostAlwaysTrue(2)
        bamboopickup.update_status()

和辅助类:

class AlmostAlwaysTrue(object):
    def __init__(self, total_iterations=1):
        self.total_iterations = total_iterations
        self.current_iteration = 0

    def __nonzero__(self):
        if self.current_iteration < self.total_iterations:
            self.current_iteration += 1
            return bool(1)
        return bool(0)

    # Python >= 3
    def __bool__(self):
        if self.current_iteration < self.total_iterations:
            self.current_iteration += 1
            return bool(1)
        return bool(0)

还可以修改它以在某个时候返回异常并再次检查.我把这个问题保留得更久一些,以防万一有人有更干净的解决方案(我确信).

One could also modify it to return a exception at some point and check agains that. I keep the question a bit longer open, in case anyone has a cleaner solution (which I am sure of).

这篇关于如何使用pytest测试无限while循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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