Pytest之断言

共 5711字,需浏览 12分钟

 ·

2020-08-06 23:27

VOL 147

04

2020-08

今天距2021年149天

这是ITester软件测试小栈第147次推文

点击上方蓝字“ITester软件测试小栈“关注我,每周一五早上 07:30准时推送。


微信公众号后台回复“资源测试工具包”领取测试资源,回复“微信群一起进群打怪。


本文4633字,阅读约需12分钟





在上一篇Pytest系列文章:Pytest之收集用例及命令行参数,主要介绍Pytest用例收集规则及常用的命令行参数。

在自动化测试过程中,需要判断预期结果和实际结果是否一致,这时需要使用到断言。


什么是断言呢?简单来说就是实际结果和期望结果去对比。





断言用法


在pytest中,使用assert进行断言,格式为:assert 表达式。

如果表达式返回结果为True,则断言成功,否则断言失败。




常用断言


unittest的三种断言:

assertIn(expect,result)断言包含(被包含的写前面);

assertEqual(expect,result)断言相等;

assertTure(条件)断言是否为真。返回Ture或False;


Pytest里的断言实际上就是Python中的assert断言方法,常用断言方法如下:

  • assert xx :判断 xx 为真;

  • assert not xx :判断 xx 不为真;

  • assert a in b :判断 b 包含 a;

  • assert a == b :判断 a 等于 b;

  • assert a != b :判断 a 不等于 b;


import pytest

def test_demo1():
    a = 1
    assert a

def test_demo2():
    a = 0
    assert not a

def test_demo3():
    s = 'hello'
    assert 'h' in s

def test_demo4():
    a = 3
    assert a == 3

def test_demo5():
    a = 4
    assert a != 3

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


运行结果如下:

Testing started at 18:22 ...
C:\Users\96984\Desktop\code\pytest\venv\Scripts\python.exe "C:\ruanjian\pycharm2019.3\PyCharm 2019.3.1\plugins\python\helpers\pycharm\_jb_pytest_runner.py" --path C:/Users/96984/Desktop/code/pytest/demo/demo_pytest.py
Launching pytest with arguments C:/Users/96984/Desktop/code/learn_pytest/demo/demo_pytest.py in C:\Users\96984\Desktop\code\learn_pytest\demo
============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 -- C:\Users\96984\Desktop\code\learn_pytest\venv\Scripts\python.exe
cachedir: .pytest_cache
metadata: {'Python''3.6.8''Platform''Windows-10-10.0.18362-SP0''Packages': {'pytest''5.4.3''py''1.9.0''pluggy''0.13.1'}, 'Plugins': {'html''2.1.1''metadata''1.10.0'}, 'JAVA_HOME''C:\\Program Files\\Java\\jdk1.8.0_77'}
rootdir: C:\Users\96984\Desktop\code\learn_pytest\demo
plugins: html-2.1.1, metadata-1.10.0
collecting ... collected 5 items
demo_pytest.py::test_demo1 PASSED                                        [ 20%]
demo_pytest.py::test_demo2 PASSED                                        [ 40%]
demo_pytest.py::test_demo3 PASSED                                        [ 60%]
demo_pytest.py::test_demo4 PASSED                                        [ 80%]
demo_pytest.py::test_demo5 PASSED                                        [100%]
============================== 5 passed in 0.06s ==============================
Process finished with exit code 0




异常断言


在测试过程中,有时需要对特定异常进行断言,可以使用 pytest.raises 作为上下文管理器,当抛出异常时可以获取到对应的异常实例。

import pytest
def test_zero_division():
    1 / 0
if __name__ == '__main__':
    pytest.main()


运行结果:

================================== FAILURES ===================================
_____________________________ test_zero_division ______________________________
    def test_zero_division():
>       1 / 0
E       ZeroDivisionError: division by zero


所以我们需要捕获并断言异常。

断言场景:断言抛出的异常是否符合预期。

预期结果:ZeroDivisionError: division by zero,其中ZeroDivisionError为错误类型,division by zero为具体错误值。

断言方式:  断言异常的type和value值。


断言代码如下:

import pytest
def test_zero_division_long():
    with pytest.raises(ZeroDivisionError) as excinfo:
        1 / 0
    # 断言异常类型 type
    assert excinfo.type == ZeroDivisionError
    # 断言异常 value 值
    assert "division by zero" in str(excinfo.value)
if __name__ == '__main__':
    pytest.main()

代码详细说明:

① pytest.raises 捕获异常,源码如下:

def raises(  # noqa: F811
    expected_exception: Union["Type[_E]", Tuple["Type[_E]", ...]],
    *args: Any,
    **kwargs: Any
)
 -> Union["RaisesContext[_E]", _pytest._code.ExceptionInfo[_E]]:

    __tracebackhide__ = True
    for exc in filterfalse(
        inspect.isclass, always_iterable(expected_exception, BASE_TYPE)  # type: ignore[arg-type]  # noqa: F821
    ):
        msg = "exceptions must be derived from BaseException, not %s"
        raise TypeError(msg % type(exc))
    message = "DID NOT RAISE {}".format(expected_exception)
    if not args:
        match = kwargs.pop("match"None)
        if kwargs:
            msg = "Unexpected keyword arguments passed to pytest.raises: "
            msg += ", ".join(sorted(kwargs))
            msg += "\nUse context-manager form instead?"
            raise TypeError(msg)
        return RaisesContext(expected_exception, message, match)
    else:
        func = args[0]
        if not callable(func):
            raise TypeError(
                "{!r} object (type: {}) must be callable".format(func, type(func))
            )
        try:
            func(*args[1:], **kwargs)
        except expected_exception as e:
            # We just caught the exception - there is a traceback.
            assert e.__traceback__ is not None
            return _pytest._code.ExceptionInfo.from_exc_info(
                (type(e), e, e.__traceback__)
            )
    fail(message)
raises.Exception = fail.Exception  # type: ignore



② excinfo作为异常信息实例,拥有type 、value等属性,源码如下:

@property
def type(self) -> "Type[_E]":
    """the exception class"""
    assert (
        self._excinfo is not None
    ), ".type can only be used after the context manager exits"
    return self._excinfo[0]
@property
def value(self) -> _E:
    """the exception value"""
    assert (
        self._excinfo is not None
    ), ".value can only be used after the context manager exits"
    return self._excinfo[1]


③ excinfo.value的值是元组,所以要转成字符串。




以上

That‘s all
更多系列文章
敬请期待

ITester软件测试小栈
往期内容宠幸


1.Python接口自动化-接口基础(一)

2.Python接口自动化-接口基础(二)


3.Python接口自动化-requests模块之get请求


4.Python接口自动化-requests模块之post请求

5.Python接口自动化之cookie、session应用


6.Python接口自动化之Token详解及应用


7.Python接口自动化之requests请求封装


8.Python接口自动化之pymysql数据库操作


9.Python接口自动化之logging日志


10.Python接口自动化之logging封装及实战

想获取更多最新干货内容
快来星标 置顶 关注
每周一、三、五 07:30见

<<  滑动查看下一张图片  >>


 后台 回复"资源"取干货
回复"微信群"一起打怪升级

测试交流Q群:727998947

点亮一下在看,你更好看


浏览 36
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报