pytest
是一個能夠簡化測試系統(tǒng)構(gòu)建季率、方便測試規(guī)模擴展的框架,它讓測試變得更具表現(xiàn)力和可讀性--模版代碼不再是必需的描沟。
只需要幾分鐘的時間飒泻,就可以對你的應(yīng)用開始一個簡單的單元測試或者復(fù)雜的功能測試。
安裝
命令行執(zhí)行如下命令:
pipenv install pytest==5.1.3
查看安裝的版本信息:
pipenv run pytest --version
創(chuàng)建你的第一個測試用例
它只有四行代碼:
# src/chapter-1/test_sample.py
def func(x):
return x + 1
def test_sample():
assert func(3) == 5
通過以下命令執(zhí)行測試:
λ pipenv run pytest src/chapter-1/test_sample.py
============================= test session starts ==============================
platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
rootdir: D:\Personal Files\Projects\pytest-chinese-doc
collected 1 item
src\chapter-1\test_sample.py F [100%]
=================================== FAILURES ===================================
_________________________________ test_sample __________________________________
def test_sample():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
src\chapter-1\test_sample.py:28: AssertionError
============================== 1 failed in 0.05s ===============================
pytest
返回一個失敗的測試報告吏廉,因為func(3)
不等于5
泞遗。
執(zhí)行多個測試用例
執(zhí)行pipenv run pytest
命令,它會執(zhí)行當(dāng)前及其子文件夾中席覆,所有命名符合test_*.py
或者*_test.py
規(guī)則的文件史辙;
觸發(fā)一個指定異常的斷言
使用raises
可以檢查代碼是否拋出一個指定的異常:
# src/chapter-1/test_sysexit.py
import pytest
def f():
# 解釋器請求退出
raise SystemExit(1)
def test_mytest():
with pytest.raises(SystemExit):
f()
執(zhí)行這個測試用例時,加上-q
選項可以查看精簡版的測試報告:
λ pipenv run pytest -q src/chapter-1/test_sysexit.py
. [100%]
1 passed in 0.01s
在一個類中組織多個測試用例
pytest
可以讓你很容易的通過創(chuàng)建一個測試類來包含多個測試用例:
# src/chapter-1/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')
現(xiàn)在我們來執(zhí)行這個測試用例:
λ pipenv run pytest -q src/chapter-1/test_class.py
.F [100%]
=================================== FAILURES ===================================
______________________________ TestClass.test_two ______________________________
self = <test_class.TestClass object at 0x000001D364778E48>
def test_two(self):
x = 'hello'
> assert hasattr(x, 'check')
E AssertionError: assert False
E + where False = hasattr('hello', 'check')
src\chapter-1\test_class.py:30: AssertionError
1 failed, 1 passed in 0.05s
從輸出的報告中我們可以看到:
-
test_one
測試通過佩伤,用.
表示聊倔;test_two
測試失敗,用F
表示生巡; - 清除的看到耙蔑,
test_two
失敗的原因是:False = hasattr('hello', 'check')
;
注意:
測試類要符合特定的規(guī)則孤荣,
pytest
才能發(fā)現(xiàn)它:
- 測試類的命令要符合
Test*
規(guī)則甸陌;- 測試類中不能有
__init__()
方法;
申請一個唯一的臨時目錄
pytest
提供一些內(nèi)置的fixtures
盐股,可以用來請求一些系統(tǒng)的資源钱豁。例如,一個唯一的臨時性目錄:
# src/chapter-1/test_tmpdir.py
def test_needsfiles(tmpdir):
print(tmpdir)
assert 0
在測試用例中遂庄,以形參的方式使用內(nèi)置的tempdir fixture
寥院,pytest
會事先創(chuàng)建一個目錄,并將一個py.path.local
對象作為實參傳入涛目;
現(xiàn)在秸谢,我們來執(zhí)行這個測試用例:
λ pipenv run pytest -q src/chapter-1/test_tmpdir.py
F [100%]
=================================== FAILURES ===================================
_______________________________ test_needsfiles ________________________________
tmpdir = local('C:\\Users\\luyao\\AppData\\Local\\Temp\\pytest-of-luyao\\pytest-1\\test_needsfiles0')
def test_needsfiles(tmpdir):
print(tmpdir)
> assert 0
E assert 0
src\chapter-1\test_tmpdir.py:25: AssertionError
----------------------------- Captured stdout call ----------------------------- C:\Users\luyao\AppData\Local\Temp\pytest-of-luyao\pytest-1\test_needsfiles0
1 failed in 0.05s
可以使用如下命令查看所有可用的fixtures
,如果想同時查看以_
開頭的fixtures
霹肝,需要添加-v
選項:
λ pipenv run pytest -q -v --fixtures
============================= test session starts ==============================
platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
rootdir: D:\Personal Files\Projects\pytest-chinese-doc
collected 5 items
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.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
============================ no tests ran in 0.10s =============================