我目前正在使用pytest来测试现有的(unittest测试套件per the documentation)。我目前正在编写一个线程,等待分配IP地址,然后将其返回给回调函数,并且正在编写将其伴随的单元测试。
这是我编写的Test Case类。
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%失败的断言(boo!)。怎么了,我该如何编写实际上失败的测试?
答案 0 :(得分:0)
所以我要回答我自己的问题,因为虽然我能够在StackOverflow上找到答案,但是它不在任何有用的关键字下,因为大多数答案都在谈论如何使用pytest-xdist
进行多线程测试,而不是测试多线程。我最终在调试过程中使用了here(如this question所述,发现我有一个由打字错误引起的异常,该异常正在打印,但没有导致测试失败。
这导致我进入community wiki answer,因为我没有意识到断言只是在引发AssertError的错误,所以我本来就被解雇了。
结果,我如下修改了{{3}},以便使断言正确工作!
pytest -s path_to_file.py::TestGetIpAddressOnNewThread
请注意,只要另一个线程中有任何异常,这将使您的测试失败。这可能不是您想要的,所以如果您只想在断言失败或类似情况下失败,则可以将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
,因为您必须在pytest的主线程上引发异常,以使其正常通过测试。
答案 1 :(得分:0)
我遇到了同样的问题,但是无法访问创建线程的代码。我针对该用例pytest-reraise发布了一个小的测试帮助程序包:
pip install pytest-reraise
Pytest风格的测试用例:
def test_get_existing_ip(reraise):
def func(ip):
with reraise:
assert ip == "192.168.0.1" # Not the real IP
assert ip == "shouldn't be the ip"
ip_check = GetInstanceIpThread(instance, func)
ip_check.start()
ip_check.join()
Unittest风格的测试用例:
from pytest-reraise import Reraise
class TestGetIpAddressOnNewThread(unittest.TestCase):
def test_get_existing_ip(self):
reraise = Reraise()
def func(ip):
with reraise:
assert ip == "192.168.0.1" # Not the real IP
assert ip == "shouldn't be the ip"
ip_check = GetInstanceIpThread(instance, func)
ip_check.start()
ip_check.join()
# Re-raise the first exception that the `reraise` context manager captured:
reraise()
两个测试用例均按预期失败,并报告AssertionError
。