zoukankan      html  css  js  c++  java
  • Pytest之断言

    在上一篇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:Users96984DesktopcodepytestvenvScriptspython.exe "C:
    uanjianpycharm2019.3PyCharm 2019.3.1pluginspythonhelperspycharm\_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:Users96984Desktopcodelearn_pytestdemo
    ============================= test session starts =============================
    platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 -- C:Users96984Desktopcodelearn_pytestvenvScriptspython.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:Users96984Desktopcodelearn_pytestdemo
    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 += "
    Use 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的值是元组,所以要转成字符串。

     

    更多系列文章,可以关注微信公众号:ITester软件测试小栈


  • 相关阅读:
    Java基础知识整理
    HashMap源码解读(JDK1.7)
    书籍列表
    mysql4
    mysql3
    mysql2
    mysql1
    数据结构4
    数据结构3
    数据结构2
  • 原文地址:https://www.cnblogs.com/vivia/p/14470013.html
Copyright © 2011-2022 走看看