Pytest01-从官方文档开始学习

官方介绍

https://docs.pytest.org/en/latest/example/index.html

在开始之前,我们先看一段官方文档的介绍:pytest is a framework that makes building simple and scalable tests easy. Tests are expressive and readable—no boilerplate code required. Get started in minutes with a small unit test or complex functional test for your application or library.

大概的意思我Google翻译了下:pytest是一个框架,使构建简单和可扩展的测试变得容易。测试具有表现力和可读性-不需要样板代码。 数分钟内即可开始为您的应用程序或库进行小型单元测试或复杂的功能测试。

Python版本:Python 3.5, 3.6, 3.7, 3.8, 3.9, PyPy3(建议还是用Python3.5以上的吧)

平台:Linux and Windows

PyPI包名: pytest

安装

一条命令即可安装:
pip install -U pytest

安装好后可以看下版本号是不是你想要的版本:
pytest --version或者pip show pytest都可以

开始第一个测试

代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2020/6/29 14:29
# @Author  : 无罪的坏人
# @File    : test_sample.py

def func(x):
    return x + 1

def test_func():
    assert func(3) == 5

运行结果:

================================== FAILURES ===================================
__________________________________ test_func __________________________________

    def test_func():
>       assert func(3) == 5
E       assert 4 == 5

test_sample.py:13: AssertionError
------- generated html file: file://D:PythonEDR2	estcase
eport.html -------
=========================== short test summary info ===========================
FAILED test_sample.py::test_func - assert 4 == 5
============================== 1 failed in 3.78s ==============================

从结果可以看出,测试失败了,因为4不等于5。

运行多个测试

pytest会默认运行当前目录以及所有子目录下所有的test_*.py和*_test.py,这是它默认的,后面可以学习通过配置文件pytest.ini来扩大匹配的范围。

断言会引发某些异常

使用raise来断言某些代码引发异常:

# -*- coding: utf-8 -*-
# @Time    : 2020/7/7 9:13
# @Author  : 无罪的坏人
# @File    : test_sysexit.py
import pytest


def f():
    print(1111)
    raise SystemExit(1)


def test_mytest():
    with pytest.raises(SystemExit):
        f()

执行:

>> pytest -q test_sysexit.py
.                                                                                    [100%]
1 passed in 0.02s

PS: 这里-q,就是--quiet,极简结果显示,简化控制台的输出,可以看出输出信息和之前不添加-q不信息不一样,用.点代替了pass结果。

一个类中有多个测试用例

比如一个登录功能,我们可能会涉及多个测试用例,并且把这些测试用例都归类到一个登录类中,pytest支持一个类中有多个测试用例(方法)。

# -*- coding: utf-8 -*-
# @Time    : 2020/7/7 9:31
# @Author  : 无罪的坏人
# @File    : test_class.py
class TestClass:
    def test_one(self):
        x = "this"
        assert "h" in x

    def test_two(self):
        x = "hello"
        assert hasattr(x, "check")  # 判断变量x有没有check属性

Pytest遵循这么一个规则:类名Test开头,方法test_开头,都会默认被执行。可以通过以下命令执行:

>> pytest -q test_class.py
.F                                                                                                                                                                                 [100%]
======================================================================================= FAILURES ========================================================================================
__________________________________________________________________________________ TestClass.test_two ___________________________________________________________________________________

self = <testcase2.test_class.TestClass object at 0x000002170D716048>

    def test_two(self):
        x = "hello"
>       assert hasattr(x, "he")
E       AssertionError: assert False
E        +  where False = hasattr('hello', 'check')

test_class.py:13: AssertionError
================================================================================ short test summary info ================================================================================
FAILED test_class.py::TestClass::test_two - AssertionError: assert False
1 failed, 1 passed in 0.11s

可以看出,一个.成功,一个F失败了,并且指出第13行失败了,可以轻松地查看断言中的值以帮助你了解失败的原因。

申请一个唯一的临时目录进行功能测试

# -*- coding: utf-8 -*-
# @Time    : 2020/7/7 9:55
# @Author  : 无罪的坏人
# @File    : test_tmpdir.py
# @Software: PyCharm
def test_needsfiles(tmpdir):
    print(tmpdir)
    assert 0

tmpdir作为参数,每次pytest执行前,都会创建一个唯一的临时目录。

>> pytest -q test_tmpdir.py
F                                                                                                                                                                                  [100%]
======================================================================================= FAILURES ========================================================================================
____________________________________________________________________________________ test_needsfiles ____________________________________________________________________________________

tmpdir = local('C:\Users\Administrator\AppData\Local\Temp\pytest-of-Administrator\pytest-0\test_needsfiles0')

    def test_needsfiles(tmpdir):
        print(tmpdir)
>       assert 0
E       assert 0

test_tmpdir.py:8: AssertionError
--------------------------------------------------------------------------------- Captured stdout call ----------------------------------------------------------------------------------
C:UsersAdministratorAppDataLocalTemppytest-of-Administratorpytest-0	est_needsfiles0
================================================================================ short test summary info ================================================================================
FAILED test_tmpdir.py::test_needsfiles - assert 0
1 failed in 0.12s

使用以下命令还可以查看其它的内置pytest fixtures,如果想同时查看以_开头的fixtures,需要添加-v选项:
pytest --fixtures
结果:

>> pytest --fixtures
================================================= test session starts =================================================
platform win32 -- Python 3.7.3, pytest-5.4.3, py-1.8.1, pluggy-0.13.1
rootdir: C:UsersAdministrator
plugins: allure-pytest-2.8.16, html-2.1.1, metadata-1.10.0, rerunfailures-9.0
collected 0 items / 1 error
cache
    Return a cache object that can persist state between testing sessions.

    cache.get(key, default)
    cache.set(key, value)

    Keys must be a ``/`` separated value, where the first part is usually the
    name of your plugin or application to avoid clashes with other cache users.

    Values can be any object handled by the json stdlib module.

capsys
    Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.

    The captured output is made available via ``capsys.readouterr()`` method
    calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``text`` objects.

capsysbinary
    Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.

    The captured output is made available via ``capsysbinary.readouterr()``
    method calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``bytes`` objects.

capfd
    Enable text capturing of writes to file descriptors ``1`` and ``2``.

    The captured output is made available via ``capfd.readouterr()`` method
    calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``text`` objects.

capfdbinary
    Enable bytes capturing of writes to file descriptors ``1`` and ``2``.

    The captured output is made available via ``capfd.readouterr()`` method
    calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``byte`` objects.

doctest_namespace [session scope]
    Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests.

pytestconfig [session scope]
    Session-scoped fixture that returns the :class:`_pytest.config.Config` object.

    Example::

        def test_foo(pytestconfig):
            if pytestconfig.getoption("verbose") > 0:
                ...

record_property
    Add an extra properties the calling test.
    User properties become part of the test report and are available to the
    configured reporters, like JUnit XML.
    The fixture is callable with ``(name, value)``, with value being automatically
    xml-encoded.

    Example::

        def test_function(record_property):
            record_property("example_key", 1)

record_xml_attribute
    Add extra xml attributes to the tag for the calling test.
    The fixture is callable with ``(name, value)``, with value being
    automatically xml-encoded

record_testsuite_property [session scope]
    Records a new ``<property>`` tag as child of the root ``<testsuite>``. This is suitable to
    writing global information regarding the entire test suite, and is compatible with ``xunit2`` JUnit family.

    This is a ``session``-scoped fixture which is called with ``(name, value)``. Example:

    .. code-block:: python

        def test_foo(record_testsuite_property):
            record_testsuite_property("ARCH", "PPC")
            record_testsuite_property("STORAGE_TYPE", "CEPH")

    ``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped.

caplog
    Access and control log capturing.

    Captured logs are available through the following properties/methods::

    * caplog.messages        -> list of format-interpolated log messages
    * caplog.text            -> string containing formatted log output
    * caplog.records         -> list of logging.LogRecord instances
    * caplog.record_tuples   -> list of (logger_name, level, message) tuples
    * caplog.clear()         -> clear captured records and formatted log output string

monkeypatch
    The returned ``monkeypatch`` fixture provides these
    helper methods to modify objects, dictionaries or os.environ::

        monkeypatch.setattr(obj, name, value, raising=True)
        monkeypatch.delattr(obj, name, raising=True)
        monkeypatch.setitem(mapping, name, value)
        monkeypatch.delitem(obj, name, raising=True)
        monkeypatch.setenv(name, value, prepend=False)
        monkeypatch.delenv(name, raising=True)
        monkeypatch.syspath_prepend(path)
        monkeypatch.chdir(path)

    All modifications will be undone after the requesting
    test function or fixture has finished. The ``raising``
    parameter determines if a KeyError or AttributeError
    will be raised if the set/deletion operation has no target.

recwarn
    Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.

    See http://docs.python.org/library/warnings.html for information
    on warning categories.

tmpdir_factory [session scope]
    Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.


tmp_path_factory [session scope]
    Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.


tmpdir
    Return a temporary directory path object
    which is unique to each test function invocation,
    created as a sub directory of the base temporary
    directory.  The returned object is a `py.path.local`_
    path object.

    .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html

tmp_path
    Return a temporary directory path object
    which is unique to each test function invocation,
    created as a sub directory of the base temporary
    directory.  The returned object is a :class:`pathlib.Path`
    object.

    .. note::

        in python < 3.6 this is a pathlib2.Path


-------------------------------------- fixtures defined from pytest_html.plugin ---------------------------------------
extra
    Add details to the HTML reports.

    .. code-block:: python

        import pytest_html
        def test_foo(extra):
            extra.append(pytest_html.extras.url('http://www.example.com/'))


------------------------------------ fixtures defined from pytest_metadata.plugin -------------------------------------
metadata [session scope]
    Provide test session metadata
原文地址:https://www.cnblogs.com/tedliu/p/13257605.html