代码:

# 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打印回溯,所以我将看到在任何函数异常被引发的地方?


当前回答

正确的方法是使用pytest。但我在这里的评论中找到了另一种有趣的方法,我想把它留给未来的读者:

try:
    thing_that_rasises_typeerror()
    assert False
except TypeError:
    assert True

其他回答

只是添加了另一个“愚蠢”的建议,因为我在现有的答案中没有看到它。本质上,你可以初始化一个错误变量为None,在try/except块中做这件事,然后在那之后检查错误变量的类/值

e = None

try:
    blah()
except Exception as exc:
    e = exc

assert e.__class__ == ValueError # or whatever you expect
assert str(e) == "expected message"

pytest.raise (Exception)是你所需要的。

Code

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保存了异常对象,因此您可以从中提取详细信息。例如,如果您想检查异常调用堆栈或内部的另一个嵌套异常。

更好的做法是使用继承unittest的类。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

正确的方法是使用pytest。但我在这里的评论中找到了另一种有趣的方法,我想把它留给未来的读者:

try:
    thing_that_rasises_typeerror()
    assert False
except TypeError:
    assert True

如果您希望为您的测试用例引发一个异常,这里提交的最重要的答案是有用的。如果您的测试可能会引发异常,并且您希望在任何一种情况下都能妥善地处理它,那么它就不是很有用。

如果您有一个可能(而不是将)引发异常的测试用例,我认为这可能是一个更好的选择。

@python.mark.parametrize("request_query, response_code", query_response_dataset)
def test_big_query_submission(request_query, response_code):
    try:
        stats = bigquery.Client().query(request_query)
    except Exception as e:
        assert False, f"Exception raised: {e}"
    assert stats.errors is None

通过这种方式,您可以优雅地失败测试,而不是由于任何原因引发异常导致测试崩溃。