Pytest----自定义Pytest断言报错信息

简介: Pytest----自定义Pytest断言报错信息

一、默认的报错信息

比如编写如下测试用例

def test_01():
    assert 1==1

def test_02():
    assert 1==2

def test_03():
    assert "1"==1

执行结果如下:

$ pytest
============================== test session starts ===============================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\summer_ospp\summer_ospp_autotest\function_tests, configfile: pytest.ini
, testpaths: tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailure
s-10.1, xdist-2.3.0
collected 3 items                                                                 

tests/test_demo.py::test_01 PASSED                                          [ 33%]
tests/test_demo.py::test_02 FAILED                                          [ 66%]
tests/test_demo.py::test_03 FAILED                                          [100%]

==================================== FAILURES ====================================
____________________________________ test_02 _____________________________________

    def test_02():
>       assert 1==2
E       assert 1 == 2
E         +1
E         -2

tests\test_demo.py:7: AssertionError
____________________________________ test_03 _____________________________________

    def test_03():
>       assert "1"==1
E       AssertionError: assert '1' == 1
E         +'1'
E         -1

tests\test_demo.py:10: AssertionError
============================ short test summary info =============================
FAILED tests/test_demo.py::test_02 - assert 1 == 2
FAILED tests/test_demo.py::test_03 - AssertionError: assert '1' == 1
========================== 2 failed, 1 passed in 0.18s ===========================

对于许多测试人员,可能习惯于看中文描述或者更加准确的中文描述,而当看到上述报错时,虽说从报错描述来说已经很清晰了,但是从多年的自动化测试经历中发现,其实很多测试人员或者编写自动化测试脚本的测试人员,调试或者执行自动化用例的时候看到上述报错的时候仍然是一脸茫然,他们更加的希望看到中文描述,甚至是更加人性化的中文描述,当然pytest的断言也提供了在脚本中自定义报错信息的方式,比如如下的方式,但是在实际测试开发中发现,虽然这种方式给自动化脚本开发人员自己定义的权利,但是在进行脚本开发的过程中如果每个断言都按照如下的方式增加断言报错信息,又很占用时间,感觉不方便,甚至有很多断言报错信息其实都是类似的,比如判断两个变量是否相等,其实断言信息都是类似的,而在脚本中每次断言都加断言报错信息又会显得很冗余,因此,另外一种在conftest.py中重写断言报错信息的处理方式就显得非常好用了

def test_03():
    assert "1"==1,f"期望 ’1‘与1 相等,实际不相等"

二、重写pytest断言报错信息

在测试用例的根目录中的conftest.py中编写如下代码:即这里对==运算符的报错信息进行了重写,比如如下首先判断是否是一个类型,如果不是一个类型,则直接提示两个数据不是一个类型,如果是一个类型的,在进行数值的比较,并且报错信息都是中文描述

def pytest_assertrepr_compare(op, left, right):
    if op == "==":
        if not isinstance(right,type(left)):
            return [
                f"断言错误,期望值与实际值的数据类型不一致,期望值数据类型为:{type(right)}, 实际值为:{type(left)}",
                f"期望值为:{right}, 实际值为:{left}",
            ]
        else:
            return [
                f"断言错误,期望值与实际值不一致,期望值为:{right}, 实际值为:{left}",
            ]

此时编写如下测试用例,如下,断言同样还是采用如下的简单的方式,即不去自己增加报错信息

def test_01():
    assert 1==1

def test_02():
    assert 1==2

def test_03():
    assert "1"==1

执行结果如下:可以看出,虽然在用例中没有自定义报错信息,而在执行结果中仍然打印出了中文描述的报错信息,对于这样中文报错信息,相信任何测试人员看到都能知道为啥报错了,也不会因为满屏的英文报错而头大了

$ pytest
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\summer_ospp\summer_ospp_autotest\function_tests, configfile: pytest.ini, testpaths: tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 3 items                                                                                                                                                       

tests/test_demo.py::test_01 PASSED                                                                                                                                [ 33%]
tests/test_demo.py::test_02 FAILED                                                                                                                                [ 66%]
tests/test_demo.py::test_03 FAILED                                                                                                                                [100%]

=============================================================================== FAILURES ===============================================================================
_______________________________________________________________________________ test_02 ________________________________________________________________________________

    def test_02():
>       assert 1==2
E       assert 断言错误,期望值与实际值不一致,期望值为:2, 实际值为:1

tests\test_demo.py:7: AssertionError
_______________________________________________________________________________ test_03 ________________________________________________________________________________

    def test_03():
>       assert "1"==1
E       AssertionError: assert 断言错误,期望值与实际值的数据类型不一致,期望值数据类型为:<class 'int'>, 实际值为:<class 'str'>
E         期望值为:1, 实际值为:1

tests\test_demo.py:10: AssertionError
======================================================================= short test summary info ========================================================================
FAILED tests/test_demo.py::test_02 - assert 断言错误,期望值与实际值不一致,期望值为:2, 实际值为:1
FAILED tests/test_demo.py::test_03 - AssertionError: assert 断言错误,期望值与实际值的数据类型不一致,期望值数据类型为:<class 'int'>, 实际值为:<class 'str'>
===================================================================== 2 failed, 1 passed in 0.18s ======================================================================

三、重写常见的断言报错信息

如下,重写了 ==,in,not in 的断言报错信息,其他的比如 >, <,>=,<=,!=等运算符重写方法类似,这里不在一一列举,conftest.py中编写如下代码:

def pytest_assertrepr_compare(op, left, right):
    if op == "==":
        if not isinstance(right,type(left)):
            return [
                f"断言错误,期望值与实际值的数据类型不一致,期望值数据类型为:{type(right)}, 实际值为:{type(left)}",
                f"期望值为:{right}, 实际值为:{left}",
            ]
        else:
            return [
                f"断言错误,期望值与实际值不一致,期望值为:{right}, 实际值为:{left}",
            ]
    if op == "in":
        if isinstance(left,str) and isinstance(right,str):
            return [
                f"期望 {left} 是 {right} 的子串,实际 {left} 不是 {right} 的子串,"
            ]

        elif isinstance(right,list) or isinstance(right,set) or isinstance(right,tuple):
            return [
                f"期望 {left} 是集合 {right} 中的一个元素,实际集合 {right} 中没有 {left} 元素"
            ]
        elif isinstance(right,dict):
            return [
                f"期望 {left} 是字典 {right} 中的一个key,实际字典 {right} 中没有值为 {left} 的key"
            ]
        else:
            return [
                f"期望 {left} 是 {right} 中的一部分,实际上 {left} 并不是 {right} 的一部分"
            ]
    if op == "not in":
        if isinstance(left, str) and isinstance(right, str):
            return [
                f"期望 {left} 不是 {right} 的子串,实际 {left} 是 {right} 的子串,"
            ]

        elif isinstance(right, list) or isinstance(right, set) or isinstance(right, tuple):
            return [
                f"期望 {left} 不是集合 {right} 中的一个元素,实际集合 {right} 中有 {left} 元素"
            ]
        elif isinstance(right, dict):
            return [
                f"期望 {left} 不是字典 {right} 中的一个key,实际字典{right}中有值为 {left} 的key"
            ]
        else:
            return [
                f"期望 {left} 不是 {right} 中的一部分,实际上 {left} 是 {right} 的一部分"
            ]

如下为实例脚本

def test_01():
    assert 1==1

def test_02():
    assert 1==2

def test_03():
    assert "1"==1

def test_04():
    assert "aa" in "bbaa"

def test_05():
    assert "aa" in "bba"

def test_06():
    assert "aa" in ["aa","bb"]

def test_07():
    assert "aa" in ("aa","bb")

def test_08():
    assert "aa" in {"aa","bb"}


def test_09():
    assert "ab" in ["aa", "bb"]


def test_10():
    assert "ab" in ("aa", "bb")


def test_11():
    assert "ab" in {"aa", "bb"}

def test_12():
    assert "name" in {"name":"张三丰","age":100}

def test_13():
    assert "gender" in {"name":"张三丰","age":100}

def test_14():
    assert "aa" not in "bbaa"

def test_15():
    assert "aa" not in "bba"

def test_16():
    assert "aa" not in ["aa","bb"]

def test_17():
    assert "aa" not in ("aa","bb")

def test_18():
    assert "aa" not in {"aa","bb"}


def test_19():
    assert "ab" not in ["aa", "bb"]


def test_20():
    assert "ab" not in ("aa", "bb")


def test_21():
    assert "ab" not in {"aa", "bb"}

def test_22():
    assert "name" not in {"name":"张三丰","age":100}

def test_23():
    assert "gender" not in {"name":"张三丰","age":100}

执行结果如下:

$ pytest
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\summer_ospp\summer_ospp_autotest\function_tests, configfile: pytest.ini, testpaths: tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 23 items                                                                                                                                                      

tests/test_demo.py::test_01 PASSED                                                                                                                                [  4%]
tests/test_demo.py::test_02 FAILED                                                                                                                                [  8%]
tests/test_demo.py::test_03 FAILED                                                                                                                                [ 13%]
tests/test_demo.py::test_04 PASSED                                                                                                                                [ 17%]
tests/test_demo.py::test_05 FAILED                                                                                                                                [ 21%]
tests/test_demo.py::test_06 PASSED                                                                                                                                [ 26%]
tests/test_demo.py::test_07 PASSED                                                                                                                                [ 30%]
tests/test_demo.py::test_08 PASSED                                                                                                                                [ 34%]
tests/test_demo.py::test_09 FAILED                                                                                                                                [ 39%]
tests/test_demo.py::test_10 FAILED                                                                                                                                [ 43%]
tests/test_demo.py::test_11 FAILED                                                                                                                                [ 47%]
tests/test_demo.py::test_12 PASSED                                                                                                                                [ 52%]
tests/test_demo.py::test_13 FAILED                                                                                                                                [ 56%]
tests/test_demo.py::test_14 FAILED                                                                                                                                [ 60%]
tests/test_demo.py::test_15 PASSED                                                                                                                                [ 65%]
tests/test_demo.py::test_16 FAILED                                                                                                                                [ 69%]
tests/test_demo.py::test_17 FAILED                                                                                                                                [ 73%]
tests/test_demo.py::test_18 FAILED                                                                                                                                [ 78%]
tests/test_demo.py::test_19 PASSED                                                                                                                                [ 82%]
tests/test_demo.py::test_20 PASSED                                                                                                                                [ 86%]
tests/test_demo.py::test_21 PASSED                                                                                                                                [ 91%]
tests/test_demo.py::test_22 FAILED                                                                                                                                [ 95%]
tests/test_demo.py::test_23 PASSED                                                                                                                                [100%]

=============================================================================== FAILURES ===============================================================================
_______________________________________________________________________________ test_02 ________________________________________________________________________________

    def test_02():
>       assert 1==2
E       assert 断言错误,期望值与实际值不一致,期望值为:2, 实际值为:1

tests\test_demo.py:7: AssertionError
_______________________________________________________________________________ test_03 ________________________________________________________________________________

    def test_03():
>       assert "1"==1
E       AssertionError: assert 断言错误,期望值与实际值的数据类型不一致,期望值数据类型为:<class 'int'>, 实际值为:<class 'str'>
E         期望值为:1, 实际值为:1

tests\test_demo.py:10: AssertionError
_______________________________________________________________________________ test_05 ________________________________________________________________________________

    def test_05():
>       assert "aa" in "bba"
E       assert 期望 aa 是 bba 的子串,实际 aa 不是 bba 的子串,

tests\test_demo.py:16: AssertionError
_______________________________________________________________________________ test_09 ________________________________________________________________________________

    def test_09():
>       assert "ab" in ["aa", "bb"]
E       AssertionError: assert 期望 ab 是集合 ['aa', 'bb'] 中的一个元素,实际集合 ['aa', 'bb'] 中没有 ab 元素

tests\test_demo.py:29: AssertionError
_______________________________________________________________________________ test_10 ________________________________________________________________________________

    def test_10():
>       assert "ab" in ("aa", "bb")
E       AssertionError: assert 期望 ab 是集合 ('aa', 'bb') 中的一个元素,实际集合 ('aa', 'bb') 中没有 ab 元素

tests\test_demo.py:33: AssertionError
_______________________________________________________________________________ test_11 ________________________________________________________________________________

    def test_11():
>       assert "ab" in {"aa", "bb"}
E       AssertionError: assert 期望 ab 是集合 {'aa', 'bb'} 中的一个元素,实际集合 {'aa', 'bb'} 中没有 ab 元素

tests\test_demo.py:37: AssertionError
_______________________________________________________________________________ test_13 ________________________________________________________________________________

    def test_13():
>       assert "gender" in {"name":"张三丰","age":100}
E       AssertionError: assert 期望 gender 是字典 {'name': '张三丰', 'age': 100} 中的一个key,实际字典 {'name': '张三丰', 'age': 100} 中没有值为 gender 的key

tests\test_demo.py:43: AssertionError
_______________________________________________________________________________ test_14 ________________________________________________________________________________

    def test_14():
>       assert "aa" not in "bbaa"
E       assert 期望 aa 不是 bbaa 的子串,实际 aa 是 bbaa 的子串,

tests\test_demo.py:46: AssertionError
_______________________________________________________________________________ test_16 ________________________________________________________________________________

    def test_16():
>       assert "aa" not in ["aa","bb"]
E       AssertionError: assert 期望 aa 不是集合 ['aa', 'bb'] 中的一个元素,实际集合 ['aa', 'bb'] 中有 aa 元素

tests\test_demo.py:52: AssertionError
_______________________________________________________________________________ test_17 ________________________________________________________________________________

    def test_17():
>       assert "aa" not in ("aa","bb")
E       AssertionError: assert 期望 aa 不是集合 ('aa', 'bb') 中的一个元素,实际集合 ('aa', 'bb') 中有 aa 元素

tests\test_demo.py:55: AssertionError
_______________________________________________________________________________ test_18 ________________________________________________________________________________

    def test_18():
>       assert "aa" not in {"aa","bb"}
E       AssertionError: assert 期望 aa 不是集合 {'aa', 'bb'} 中的一个元素,实际集合 {'aa', 'bb'} 中有 aa 元素

tests\test_demo.py:58: AssertionError
_______________________________________________________________________________ test_22 ________________________________________________________________________________

    def test_22():
>       assert "name" not in {"name":"张三丰","age":100}
E       AssertionError: assert 期望 name 不是字典 {'name': '张三丰', 'age': 100} 中的一个key,实际字典{'name': '张三丰', 'age': 100}中有值为 name 的key

tests\test_demo.py:73: AssertionError
======================================================================= short test summary info ========================================================================
FAILED tests/test_demo.py::test_02 - assert 断言错误,期望值与实际值不一致,期望值为:2, 实际值为:1
FAILED tests/test_demo.py::test_03 - AssertionError: assert 断言错误,期望值与实际值的数据类型不一致,期望值数据类型为:<class 'int'>, 实际值为:<class 'str'>
FAILED tests/test_demo.py::test_05 - assert 期望 aa 是 bba 的子串,实际 aa 不是 bba 的子串,
FAILED tests/test_demo.py::test_09 - AssertionError: assert 期望 ab 是集合 ['aa', 'bb'] 中的一个元素,实际集合 ['aa', 'bb'] 中没有 ab 元素
FAILED tests/test_demo.py::test_10 - AssertionError: assert 期望 ab 是集合 ('aa', 'bb') 中的一个元素,实际集合 ('aa', 'bb') 中没有 ab 元素
FAILED tests/test_demo.py::test_11 - AssertionError: assert 期望 ab 是集合 {'aa', 'bb'} 中的一个元素,实际集合 {'aa', 'bb'} 中没有 ab 元素
FAILED tests/test_demo.py::test_13 - AssertionError: assert 期望 gender 是字典 {'name': '张三丰', 'age': 100} 中的一个key,实际字典 {'name': '张三丰', 'age': 100} 中...
FAILED tests/test_demo.py::test_14 - assert 期望 aa 不是 bbaa 的子串,实际 aa 是 bbaa 的子串,
FAILED tests/test_demo.py::test_16 - AssertionError: assert 期望 aa 不是集合 ['aa', 'bb'] 中的一个元素,实际集合 ['aa', 'bb'] 中有 aa 元素
FAILED tests/test_demo.py::test_17 - AssertionError: assert 期望 aa 不是集合 ('aa', 'bb') 中的一个元素,实际集合 ('aa', 'bb') 中有 aa 元素
FAILED tests/test_demo.py::test_18 - AssertionError: assert 期望 aa 不是集合 {'aa', 'bb'} 中的一个元素,实际集合 {'aa', 'bb'} 中有 aa 元素
FAILED tests/test_demo.py::test_22 - AssertionError: assert 期望 name 不是字典 {'name': '张三丰', 'age': 100} 中的一个key,实际字典{'name': '张三丰', 'age': 100}中有...
==================================================================== 12 failed, 11 passed in 0.25s =====================================================================

目录
相关文章
|
测试技术 Python
Pytest断言
Pytest断言
56 0
|
6月前
|
测试技术 Python
pycharm使用pytest运行测试用例,无法在控制台输出print语句、log语句的解决办法
pycharm使用pytest运行测试用例,无法在控制台输出print语句、log语句的解决办法
419 1
|
6月前
pytest添加自定义参数
pytest添加自定义参数
185 0
|
测试技术
unittest--断言
unittest--断言
|
测试技术 C++ Python
pytest 执行规则_基本用法_常用插件_常用断言_常用参数
pytest 执行规则_基本用法_常用插件_常用断言_常用参数
|
测试技术
pytest学习和使用13-Pytest的fixture如何使用request传入参数?
pytest学习和使用13-Pytest的fixture如何使用request传入参数?
101 0
|
测试技术
pytest学习和使用5-Pytest和Unittest中的断言如何使用?
pytest学习和使用5-Pytest和Unittest中的断言如何使用?
92 0
pytest学习和使用5-Pytest和Unittest中的断言如何使用?
pytest学习和使用19-pytest断言失败后,怎样保持后续的断言继续执行?(pytest-assume)
pytest学习和使用19-pytest断言失败后,怎样保持后续的断言继续执行?(pytest-assume)
128 0
|
测试技术 Python
pytest学习和使用15-Pytest用例失败如何重跑?(pytest-rerunfailures的简单使用)
pytest学习和使用15-Pytest用例失败如何重跑?(pytest-rerunfailures的简单使用)
111 0