Pytest - 使用介紹

1. 概述

pytest是一個非常成熟的全功能的Python測試框架,主要特點有以下幾點:

  • 1、簡單靈活,容易上手,文檔豐富;
  • 2、支持參數化,可以細粒度地控制要測試的測試用例;
  • 3、能夠支持簡單的單元測試和復雜的功能測試,還可以用來做selenium/appnium等自動化測試、接口自動化測試(pytest+requests);
  • 4、pytest具有很多第三方插件,并且可以自定義擴展,比較好用的如pytest-selenium(集成selenium)、pytest-html(完美html測試報告生成)、pytest-rerunfailures(失敗case重復執行)、pytest-xdist(多CPU分發)等;
  • 5、測試用例的skip和xfail處理;
  • 6、可以很好的和CI工具結合,例如jenkins

2. 使用介紹

2.1. 安裝

pip install pytest

2.2. 示例代碼

編寫規則

編寫pytest測試樣例非常簡單,只需要按照下面的規則:

  • 測試文件以test_開頭(以_test結尾也可以)
  • 測試類以Test開頭,并且不能帶有 init 方法
  • 測試函數以test_開頭
  • 斷言使用基本的assert即可

pytest1.py

# -*- coding:utf-8 -*-
import pytest

@pytest.fixture(scope='function')
def setup_function(request):
    def teardown_function():
        print("teardown_function called.")
    request.addfinalizer(teardown_function)  # 此內嵌函數做teardown工作
    print('setup_function called.')

@pytest.fixture(scope='module')
def setup_module(request):
    def teardown_module():
        print("teardown_module called.")
    request.addfinalizer(teardown_module)
    print('setup_module called.')

@pytest.mark.website
def test_1(setup_function):
    print('Test_1 called.')

def test_2(setup_module):
    print('Test_2 called.')

def test_3(setup_module):
    print('Test_3 called.')
    assert 2==1+1              # 通過assert斷言確認測試結果是否符合預期

fixture的scope參數

scope參數有四種,分別是'function','module','class','session',默認為function。

  • function:每個test都運行,默認是function的scope
  • class:每個class的所有test只運行一次
  • module:每個module的所有test只運行一次
  • session:每個session只運行一次

setup和teardown操作

  • setup,在測試函數或類之前執行,完成準備工作,例如數據庫鏈接、測試數據、打開文件等
  • teardown,在測試函數或類之后執行,完成收尾工作,例如斷開數據庫鏈接、回收內存資源等
  • 備注:也可以通過在fixture函數中通過yield實現setup和teardown功能

2.3. 測試結果

如何執行

  • pytest # run all tests below current dir
  • pytest test_mod.py # run tests in module file test_mod.py
  • pytest somepath # run all tests below somepath like ./tests/
  • pytest -k stringexpr # only run tests with names that match the
    # the "string expression", e.g. "MyClass and not method"
    # will select TestMyClass.test_something
    # but not TestMyClass.test_method_simple
  • pytest test_mod.py::test_func # only run tests that match the "node ID",
    # e.g "test_mod.py::test_func" will be selected
    # only run test_func in test_mod.py

通過pytest.mark對test方法分類執行

通過@pytest.mark控制需要執行哪些feature的test,例如在執行test前增加修飾@pytest.mark.website

  • 通過 -m "website" 執行有website標記的test方法
$ pytest  -v -m "website" pytest1.py
============================================================================== test session starts ===============================================================================
platform linux2 -- Python 2.7.14, pytest-3.0.0, py-1.5.2, pluggy-0.3.1 -- /home/kevin/soft/anaconda2/bin/python
cachedir: .cache
Using --randomly-seed=1522925202
rootdir: /home/kevin/learn/python-web/tox/case2, inifile:
plugins: randomly-1.0.0, mock-1.2, cov-2.0.0
collected 3 items

pytest1.py::test_1 PASSED

============================================================================= pytest-warning summary =============================================================================
WC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.
=============================================================================== 2 tests deselected ===============================================================================
=========================================================== 1 passed, 2 deselected, 1 pytest-warnings in 0.00 seconds ============================================================
  • 通過 -m "not website" 執行沒有website標記的test方法
$ pytest  -v -m "not website" pytest1.py
============================================================================== test session starts ===============================================================================
platform linux2 -- Python 2.7.14, pytest-3.0.0, py-1.5.2, pluggy-0.3.1 -- /home/kevin/soft/anaconda2/bin/python
cachedir: .cache
Using --randomly-seed=1522925192
rootdir: /home/kevin/learn/python-web/tox/case2, inifile:
plugins: randomly-1.0.0, mock-1.2, cov-2.0.0
collected 3 items

pytest1.py::test_3 PASSED
pytest1.py::test_2 PASSED

============================================================================= pytest-warning summary =============================================================================
WC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.
=============================================================================== 1 tests deselected ===============================================================================
=========================================================== 2 passed, 1 deselected, 1 pytest-warnings in 0.00 seconds ============================================================

Console參數介紹

  • -v 用于顯示每個測試函數的執行結果
  • -q 只顯示整體測試結果
  • -s 用于顯示測試函數中print()函數輸出
  • -x, --exitfirst, exit instantly on first error or failed test
  • -h 幫助

Case 1

$ pytest -v pytest1.py
============================================================================== test session starts ===============================================================================
platform linux2 -- Python 2.7.14, pytest-3.0.0, py-1.5.2, pluggy-0.3.1 -- /home/kevin/soft/anaconda2/bin/python
cachedir: .cache
Using --randomly-seed=1522920341
rootdir: /home/kevin/learn/python-web/tox/case2, inifile:
plugins: randomly-1.0.0, mock-1.2, cov-2.0.0
collected 3 items

pytest1.py::test_1 PASSED
pytest1.py::test_3 PASSED
pytest1.py::test_2 PASSED

============================================================================= pytest-warning summary =============================================================================
WC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.
================================================================== 3 passed, 1 pytest-warnings in 0.01 seconds ===================================================================

Case 2

$ pytest -s pytest1.py
============================================================================== test session starts ===============================================================================
platform linux2 -- Python 2.7.14, pytest-3.0.0, py-1.5.2, pluggy-0.3.1
Using --randomly-seed=1522920508
rootdir: /home/kevin/learn/python-web/tox/case2, inifile:
plugins: randomly-1.0.0, mock-1.2, cov-2.0.0
collected 3 items

pytest1.py setup_function called.
Test_1 called.
.teardown_function called.
setup_module called.
Test_2 called.
.Test_3 called.
.teardown_module called.


============================================================================= pytest-warning summary =============================================================================
WC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.
================================================================== 3 passed, 1 pytest-warnings in 0.01 seconds ===================================================================

3. 擴展插件

3.1. 測試報告

安裝與樣例

pip install pytest-cov # 計算pytest覆蓋率,支持輸出多種格式的測試報告
pytest --cov-report=html --cov=./ test_code_target_dir

Console參數介紹

  • --cov=[path], measure coverage for filesystem path (multi-allowed), 指定被測試對象,用于計算測試覆蓋率
  • --cov-report=type, type of report to generate: term, term-missing, annotate, html, xml (multi-allowed), 測試報告的類型
  • --cov-config=path, config file for coverage, default: .coveragerc, coverage配置文件
  • --no-cov-on-fail, do not report coverage if test run fails, default: False,如果測試失敗,不生成測試報告
  • --cov-fail-under=MIN, Fail if the total coverage is less than MIN. 如果測試覆蓋率低于MIN,則認為失敗

Console Result

---------------------------------------------------------------- coverage: platform linux2, python 2.7.14-final-0 ----------------------------------------------------------------
Name         Stmts   Miss  Cover
--------------------------------
pytest1.py      18      0   100%

Html Result

image.png

3.2. 測試順序隨機

pip install pytest-randomly

3.3. 分布式測試

pip install pytest-xdist

3.4. 出錯立即返回

pip install pytest-instafail

4. 參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容