pytest
是一個可以簡化測試系統構建、方便測試規模擴展的框架,它讓測試變得更具表現力和可讀性--模版代碼再也不是必需的。python
只須要幾分鐘的時間,就能夠對你的應用開始一個簡單的單元測試或者複雜的功能測試。git
命令行執行以下命令:pipenv install pytest==5.1.3
github
查看安裝的版本信息:pipenv run pytest --version
json
它只有四行代碼:bash
# src/chapter-1/test_sample.py def func(x): return x + 1 def test_sample(): assert func(3) == 5
經過如下命令執行測試:session
λ 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
。app
執行pipenv run pytest
命令,它會執行當前及其子文件夾中,全部命名符合test_*.py
或者*_test.py
規則的文件;框架
使用raises
能夠檢查代碼是否拋出一個指定的異常:ide
# src/chapter-1/test_sysexit.py import pytest def f(): # 解釋器請求退出 raise SystemExit(1) def test_mytest(): with pytest.raises(SystemExit): f()
執行這個測試用例時,加上-q
選項能夠查看精簡版的測試報告:
λ pipenv run pytest -q src/chapter-1/test_sysexit.py . [100%] 1 passed in 0.01s
pytest
可讓你很容易的經過建立一個測試類來包含多個測試用例:
# 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')
如今咱們來執行這個測試用例:
λ 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')
;注意:
測試類要符合特定的規則,
pytest
才能發現它:
- 測試類的命令要符合
Test*
規則;- 測試類中不能有
__init__()
方法;
pytest
提供一些內置的fixtures
,能夠用來請求一些系統的資源。例如,一個惟一的臨時性目錄:
# src/chapter-1/test_tmpdir.py def test_needsfiles(tmpdir): print(tmpdir) assert 0
在測試用例中,以形參的方式使用內置的tempdir fixture
,pytest
會事先建立一個目錄,並將一個py.path.local
對象做爲實參傳入;
如今,咱們來執行這個測試用例:
λ 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 =============================