python - 当在 Python 中测试另一个线程的结果时,PyTest 测试套件在断言应该失败时通过?

标签 python multithreading testing pytest python-multithreading

我目前正在使用 pytest 来测试现有的 (unittest test-suite per the documentation)。我目前正在编写一个等待分配 IP 地址的线程,然后将其返回给回调函数,我正在编写单元测试来配合它。

这是我编写的测试用例类。

class TestGetIpAddressOnNewThread(unittest.TestCase):

    def test_get_existing_ip(self):
        def func(ip):
            assert ip == "192.168.0.1" # Not the real IP
            # Even when I introduce an assert statement that should fail, test still passes
            assert ip == "shouldn't be the ip" 

        ip_check = GetInstanceIpThread(instance, func)
        ip_check.start()
        ip_check.join()

if __name__ == '__main__':
    pytest.main()

下面是 GetInstanceIpThread 伪定义:

class GetInstanceIpThread(threading.Thread):
    def __init__(self, instance, callback):
        threading.Thread.__init__(self)
        self.event = threading.Event()
        self.instance = instance
        self.callback = callback

    def run(self):
        self.instance.wait_until_running()

        ip = self.instance.ip_address
        self.callback(ip)

当我使用 pytest path_to_file.py::TestGetIpAddressOnNewThread 运行此测试用例时,它通过了(耶!)但即使我引入了应该 100% 失败的断言语句(嘘!)。出了什么问题,我该如何编写实际失败的测试?

最佳答案

所以我正在回答我自己的问题,因为虽然我能够在 StackOverflow 上找到答案,但它没有任何有用的关键字,因为大多数答案都在谈论如何使用 pytest-xdist< 进行多线程测试,不测试多线程。如前所述,我最终使用了 pytest -s path_to_file.py::TestGetIpAddressOnNewThread here在调试期间显示我有一个打印错误导致的异常,但不会导致测试失败。

这让我找到了 this question ,我最初不予理会,因为我没有意识到断言只是引发 AssertError。

因此,我改编了 community wiki answer为了让断言正常工作,如下所示!

class GetInstanceIpThread(threading.Thread):
    def __init__(self, instance, callback=None):
        threading.Thread.__init__(self)
        self.event = threading.Event()
        self.instance = instance
        self.callback = callback

    def _run(self):
        # The original run code goes here
        self.instance.wait_until_running()

        ip = self.instance.ip_address
        self.callback(ip)

    def run(self):
        self.exc = None
        try:
            self._run()
        except BaseException as e:
            self.exc = e

    def join(self):
        super(GetInstanceIpThread, self).join()
        if self.exc:
            raise self.exc

请注意,只要其他线程中存在任何异常,这就会使您的测试失败。这可能不是你想要的,所以如果你只想在断言失败或类似的情况下失败,你可以将 BaseException 更改为 AssertError (或任何你想失败的东西) 而不是。

重写 join() 是必要的,因为您必须在 pytest 的主线程上引发异常,以便它正确地使测试失败。

关于python - 当在 Python 中测试另一个线程的结果时,PyTest 测试套件在断言应该失败时通过?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50935019/

相关文章:

ruby - rspec:第一次失败后如何继续测试

python - 在matplotlib中,如何在不调整其他子图大小的情况下将表添加到子图

python - 在 Google App Engine 上导入 django-widget-tweaks 时出错

c# - Task.Run(()=> DoWorkAsync()) 和 new Thread(async()=> DoWorkAsync()); 之间的区别

等待线程的Java列表

ruby-on-rails - 应允许空白 validate_uniqueness_of

Spring - 如何测试具有 ApplicationEventPublisher 依赖关系的 Controller ?

python - 找不到 "six",但已安装

python - 使用 BeautifulSoup 从 `p` 中提取 `div` 中的文本

java - 我们如何停止后端进程?