如何使用 pytest 测试无限 while 循环

2024-03-06

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

    # 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像这样:

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

然后使用 ThreadPool 使用此测试方法(此处解释如何从Python线程中获取返回值? https://stackoverflow.com/questions/6893968/how-to-get-the-return-value-from-a-thread-in-python)因为我还需要包含 while 循环的方法的结果。

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 http://pytest.org/latest/monkeypatch.html.


于是,经过一番深入研究,我找到了目前令我满意的解决方案。我想分享它,以防其他人遇到同样的问题。实际上它很简单,并且有一些辅助类https://gist.github.com/daltonmatos/3280885 https://gist.github.com/daltonmatos/3280885我想出了以下测试代码:

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)

人们还可以修改它以在某个时刻返回异常并进行检查。我将这个问题保留得更久一些,以防有人有更干净的解决方案(我确信这一点)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 pytest 测试无限 while 循环 的相关文章

随机推荐