如何正确地断言在pytest中引发exception?
码:
# coding=utf-8 import pytest def whatever(): return 9/0 def test_whatever(): try: whatever() except ZeroDivisionError as exc: pytest.fail(exc, pytrace=True)
输出:
================================ test session starts ================================= platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 plugins: django, cov collected 1 items pytest_test.py F ====================================== FAILURES ====================================== ___________________________________ test_whatever ____________________________________ def test_whatever(): try: whatever() except ZeroDivisionError as exc: > pytest.fail(exc, pytrace=True) E Failed: integer division or modulo by zero pytest_test.py:12: Failed ============================== 1 failed in 1.16 seconds ==============================
如何使pytest打印回溯,所以我会看到在whatever
functionexception提出的地方?
pytest.raises(Exception)
是你需要的。
码
import pytest def test_passes(): with pytest.raises(Exception) as e_info: x = 1 / 0 def test_passes_without_info(): with pytest.raises(Exception): x = 1 / 0 def test_fails(): with pytest.raises(Exception) as e_info: x = 1 / 1 def test_fails_without_info(): with pytest.raises(Exception): x = 1 / 1 # Don't do this. Assertions are caught as exceptions. def test_passes_but_should_not(): try: x = 1 / 1 assert False except Exception: assert True # Even if the appropriate exception is caught, it is bad style, # because the test result is less informative # than it would be with pytest.raises(e) # (it just says pass or fail.) def test_passes_but_bad_style(): try: x = 1 / 0 assert False except ZeroDivisionError: assert True def test_fails_but_bad_style(): try: x = 1 / 1 assert False except ZeroDivisionError: assert True
产量
============================================================================================= test session starts ============================================================================================== platform linux2 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4 collected 7 items test.py ..FF..F =================================================================================================== FAILURES =================================================================================================== __________________________________________________________________________________________________ test_fails __________________________________________________________________________________________________ def test_fails(): with pytest.raises(Exception) as e_info: > x = 1 / 1 E Failed: DID NOT RAISE test.py:13: Failed ___________________________________________________________________________________________ test_fails_without_info ____________________________________________________________________________________________ def test_fails_without_info(): with pytest.raises(Exception): > x = 1 / 1 E Failed: DID NOT RAISE test.py:17: Failed ___________________________________________________________________________________________ test_fails_but_bad_style ___________________________________________________________________________________________ def test_fails_but_bad_style(): try: x = 1 / 1 > assert False E assert False test.py:43: AssertionError ====================================================================================== 3 failed, 4 passed in 0.02 seconds ======================================================================================
请注意, e_info
保存exception对象,以便可以从中提取详细信息。 例如,如果你想检查exception调用堆栈或其他嵌套的exception里面。
你的意思是这样的:
def test_raises(): with pytest.raises(Exception) as excinfo: raise Exception('some info') assert excinfo.value.message == 'some info'
你可以试试
def test_exception(): with pytest.raises(Exception) as excinfo: function_that_raises_exception() assert str(excinfo.value) == 'some info'
在pytest中有两种方法来处理这种情况:
-
使用
pytest.raises
函数 -
使用
pytest.mark.xfail
修饰符
pytest.raises
用法:
def whatever(): return 9/0 def test_whatever(): with pytest.raises(ZeroDivisionError): whatever()
pytest.mark.xfail
用法:
@pytest.mark.xfail(raises=ZeroDivisionError) def test_whatever(): whatever()
pytest.raises
输出:
============================= test session starts ============================ platform linux2 -- Python 2.7.10, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- /usr/local/python_2.7_10/bin/python cachedir: .cache rootdir: /home/ukpdl, inifile: collected 1 item test_fun.py::test_whatever PASSED ======================== 1 passed in 0.01 seconds =============================
pytest.xfail
标记的输出:
============================= test session starts ============================ platform linux2 -- Python 2.7.10, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- /usr/local/python_2.7_10/bin/python cachedir: .cache rootdir: /home/ukpdl, inifile: collected 1 item test_fun.py::test_whatever xfail ======================== 1 xfailed in 0.03 seconds=============================
正如文件所说:
使用pytest.raises
可能会更好,因为你正在testing你自己的代码故意提高的exception,而使用@pytest.mark.xfail
和check函数可能更适合于像logging未@pytest.mark.xfail
错误(testing描述了什么“应该”发生)或错误的依赖。
你有没有尝试删除“pytrace = True”?
pytest.fail(exc, pytrace=True) # before pytest.fail(exc) # after
你有没有试图用' – fulltrace'来运行?
更好的做法是使用inheritanceunittest.TestCase并运行self.assertRaises的类。
例如:
import unittest def whatever(): return 9/0 class TestWhatEver(unittest.TestCase): def test_whatever(): with self.assertRaises(ZeroDivisionError): whatever()
然后你可以通过运行来执行它:
pytest -vs test_path