Pytest單元測試系列[v1.0.0][Pytest基礎]

Pytest安裝與配置

和Unittest一樣,Pytest是另一個Python語言的單元測試框架,與Unittest相比它的測試用例更加容易編寫、運行方式更加靈活、報錯信息更加清晰、斷言寫法更簡潔并且它可以運行有unittest和nose編寫的測試用例。

Pytest 安裝

啟動命令行,在命令行中使用pip工具安裝pytest,如圖所示。

C:\Users\Administrator>pip install -U pytest
Collecting pytestUsing cached pytest-5.4.1-py3-none-any.whl (246 kB)
Requirement already satisfied, skipping upgrade: pluggy<1.0,>=0.12 in c:\program files\python38\lib\site-packages (from pytest) (0.13.1)
Requirement already satisfied, skipping upgrade: atomicwrites>=1.0; sys_platform == "win32" in c:\program files\python38\lib\site-packages (from pytest) (1.3.0)
Requirement already satisfied, skipping upgrade: colorama; sys_platform == "win32" in c:\program files\python38\lib\site-packages (from pytest) (0.4.3)
Requirement already satisfied, skipping upgrade: wcwidth in c:\program files\python38\lib\site-packages (from pytest) (0.1.8)
Requirement already satisfied, skipping upgrade: packaging in c:\program files\python38\lib\site-packages (from pytest) (20.3)
Requirement already satisfied, skipping upgrade: attrs>=17.4.0 in c:\program files\python38\lib\site-packages (from pytest) (19.3.0)
Requirement already satisfied, skipping upgrade: more-itertools>=4.0.0 in c:\program files\python38\lib\site-packages (from pytest) (8.2.0)
Requirement already satisfied, skipping upgrade: py>=1.5.0 in c:\program files\python38\lib\site-packages (from pytest) (1.8.1)
Requirement already satisfied, skipping upgrade: six in c:\program files\python38\lib\site-packages (from packaging->pytest) (1.14.0)
Requirement already satisfied, skipping upgrade: pyparsing>=2.0.2 in c:\program files\python38\lib\site-packages (from packaging->pytest) (2.4.6)
Installing collected packages: pytest
Successfully installed pytest-5.4.1

代碼示例

新建一個python文件,并寫入如下代碼:

def test_equal():assert(1,2,3)==(1,2,3)

然后在命令行運行該文件,執行命令為 pytest xxx.py,執行結果如圖

C:\Users\Administrator>pytest C:\Users\Administrator\Desktop\123.py
===================================== test session starts ==================================================
platform win32 -- Python 3.8.1, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Administrator
collected 1 itemDesktop\123.py .                                                                                                 [100%]====================================== 1 passed in 0.09s ==================================================

如果想看到詳細的執行結果,可以給執行命令加上參數 -v或者–verbose,即pytest -v xxx.py,執行結果如圖

C:\Users\Administrator>pytest -v C:\Users\Administrator\Desktop\123.py
======================================= test session starts =================================================
platform win32 -- Python 3.8.1, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- c:\program files\python38\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Administrator
collected 1 itemDesktop/123.py::test_equal PASSED                                                                                [100%]============================================ 1 passed in 0.04s ===============================================

我們在看一個執行失敗的例子,再新建一個py文件,寫入如下代碼:

def test_equal():assert(1,2,3)==(3,2,1)

然后執行該文件,pytest -v xxx.py,執行結果如圖

C:\Users\Administrator>pytest -v C:\Users\Administrator\Desktop\123.py
=========================================== test session starts ==============================================
platform win32 -- Python 3.8.1, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- c:\program files\python38\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Administrator
collected 1 itemDesktop/123.py::test_equal FAILED                                                                                [100%]============================================= FAILURES =======================================================
____________________________________________ test_equal ______________________________________________________def test_equal():
>       assert(1,2,3)==(3,2,1)
E    assert (1, 2, 3) == (3, 2, 1)
E      At index 0 diff: 1 != 3
E      Full diff:
E      - (3, 2, 1)
E      ?  ^     ^
E      + (1, 2, 3)
E      ?  ^     ^Desktop\123.py:2: AssertionError
====================================== short test summary info ===============================================
FAILED Desktop/123.py::test_equal - assert (1, 2, 3) == (3, 2, 1)
============================================= 1 failed in 0.20s ==============================================

雖然斷言結果是失敗,但我們從執行結果中能夠很清晰的看到為什么,pytest使用脫字符(^)表明結果中不同的地方

配置Pycharm

在這里插入圖片描述

卸載Pytest

C:\Users\Administrator>pip uninstall pytest
Found existing installation: pytest 5.4.1
Uninstalling pytest-5.4.1:Would remove:c:\program files\python38\lib\site-packages\_pytest\*c:\program files\python38\lib\site-packages\pytest-5.4.1.dist-info\*c:\program files\python38\lib\site-packages\pytest\*c:\program files\python38\scripts\py.test.exec:\program files\python38\scripts\pytest.exe
Proceed (y/n)? ySuccessfully uninstalled pytest-5.4.1C:\Users\Administrator>

常用命令行參數

Pytest執行規則

  • 在命令行使用pytest執行測試,完整的pytest命令需要在pytest后加選項和文件名或者路徑
  • 如果不提供這些選項或參數,pytest會在當前目錄及其子目錄下尋找測試文件,然后運行搜索到的測試代碼
  • 如果提供了一個或者多個文件名、目錄,pytest會逐一查找并運行所有測試,為了搜索到所有的測試代碼,pytest會遞歸遍歷每個目錄及其子目錄,但也只是執行以test_開頭或者_test開頭的測試函數

pytest搜索測試文件和測試用例的過程稱為測試搜索,只要遵循如下幾條原則便能夠被它搜索到

  • 測試文件應命名為test_(something).py或者(something)_test.py
  • 測試函數、測試類方法應命名為test_(something)
  • 測試類應命名為Test(something)
測試代碼

假如有如下待測代碼,將其保存在py文件中,文件名為tobetest.py

import pytest# 功能
def add(a, b):return a + b# 測試相等
@allure.step
def test_add():assert add(3, 4) == 7# 測試不相等
@allure.step
def test_add2():assert add(17, 22) != 50# 測試大于
@allure.step
def test_add3():assert add(17, 22) <= 50# 測試小于
@pytest.mark.aaaa
def test_add4():assert add(17, 22) >= 50# 測試相等
def test_in():a = "hello"b = "he"assert b in a# 測試不相等
def test_not_in():a = "hello"b = "hi"assert b not in a# 用于判斷素數
def is_prime(n):if n <= 1:return Falsefor i in range(2, n):if n % i == 0:return Falsereturn True# 判斷是否為素數
def test_true():assert is_prime(13)# 判斷是否不為素數
def test_not_true():assert not is_prime(7)
執行單一文件
E:\Programs\Python\Python_Pytest\TestScripts>pytest tobetest.py
============================================= test session starts ====================================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.13.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts, inifile: pytest.ini
plugins: allure-pytest-2.6.3, cov-2.7.1, emoji-0.2.0, forked-1.0.2, instafail-0.4.1, nice-0.1.0, repeat-0.8.0, timeout-1.3.3, xdist-1.29.0
collected 8 items                                                                                                                                                          tobetest.py ...F...F                                                                                                                                             [100%]================================================ FAILURES ===========================================================
_________________________________________________ test_add4 __________________________________________________________@pytest.mark.aaaadef test_add4():
>       assert add(17, 22) >= 50
E       assert 39 >= 50
E        +  where 39 = add(17, 22)test_asserts.py:36: AssertionError
_________________________________________________ test_not_true ______________________________________________________def test_not_true():
>       assert not is_prime(7)
E       assert not True
E        +  where True = is_prime(7)test_asserts.py:70: AssertionError
========================================= warnings summary ============================================================
c:\python37\lib\site-packages\_pytest\mark\structures.py:324c:\python37\lib\site-packages\_pytest\mark\structures.py:324: PytestUnknownMarkWarning: Unknown pytest.mark.aaaa - is this a typo?  You can register custom marks to avoidthis warning - for details, see https://docs.pytest.org/en/latest/mark.htmlPytestUnknownMarkWarning,test_asserts.py::test_add4
test_asserts.py::test_not_truec:\python37\lib\site-packages\pytest_nice.py:22: PytestDeprecationWarning: the `pytest.config` global is deprecated.  Please use `request.config` or `pytest_configure` (i
f you're a pytest plugin) instead.if report.failed and pytest.config.getoption('nice'):-- Docs: https://docs.pytest.org/en/latest/warnings.html
================================ 2 failed, 6 passed, 3 warnings in 0.46 seconds =========================================
  • 第一行顯示執行代碼的操作系統、python版本以及pytest的版本:platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.13.0
  • 第二行顯示搜索代碼的啟示目錄以及配置文件,在本例中沒有配置文件,因此inifile為空:rootdir: E:\Programs\Python\Python_Pytest\TestScripts, inifile: pytest.ini
  • 第三行顯示當前已經安裝的pytest插件plugins: allure-pytest-2.6.3, cov-2.7.1, emoji-0.2.0, forked-1.0.2, instafail-0.4.1, nice-0.1.0, repeat-0.8.0, timeout-1.3.3, xdist-1.29.0
  • 第四行 collected 8 items 表示找到8個測試函數。
  • 第五行tobetest.py ...F...F顯示的是測試文件名,后邊的點表示測試通過,除了點以外,還可能遇到Failure、error(測試異常)、skip、xfail(預期失敗并確實失敗)、xpass(預期失敗但實際通過,不符合預期)分別會顯示F、E、s、x、X
  • 2 failed, 6 passed, 3 warnings in 0.46 seconds表示測試結果和執行時間
執行單一測試函數

使用命令 pytest -v 路徑/文件名::測試用例函數名執行結果如下:

E:\Programs\Python\Python_Pytest\TestScripts>pytest test_asserts.py::test_true
==================================================== test session starts ===============================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.13.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts, inifile: pytest.ini
plugins: allure-pytest-2.6.3, cov-2.7.1, emoji-0.2.0, forked-1.0.2, instafail-0.4.1, nice-0.1.0, repeat-0.8.0, timeout-1.3.3, xdist-1.29.0
collected 1 item                                                                                                                                                           test_asserts.py .                                                                                                                                                    [100%]================================================== warnings summary ====================================================
c:\python37\lib\site-packages\_pytest\mark\structures.py:324c:\python37\lib\site-packages\_pytest\mark\structures.py:324: PytestUnknownMarkWarning: Unknown pytest.mark.aaaa - is this a typo?  You can register custom marks to avoidthis warning - for details, see https://docs.pytest.org/en/latest/mark.htmlPytestUnknownMarkWarning,-- Docs: https://docs.pytest.org/en/latest/warnings.html
========================================== 1 passed, 1 warnings in 0.07 seconds =========================================
其他命令行規則
  • 運行某個模塊內的某個測試函數pytest test_mod.py::test_func
  • 運行某個模塊內某個類的某個測試方法pytest test_mod.py::TestClass::test_method
  • 執行單一測試模塊的語法是pytest test_module.py
  • 執行某個目錄下的所有測試函數語法是pytest test/

常用pytest命令選項

--collect-only

在批量執行測試用例之前,我們往往會想知道哪些用例將被執行是否符合我們的預期等等,這種場景下可以使用–collect-only選項,如下執行結果所示:

D:\PythonPrograms\Python_Pytest\TestScripts>pytest --collect-only
================================================= test session starts ===================================================
platform win32 -- Python 3.7.2, pytest-4.0.2, py-1.8.0, pluggy-0.12.0
rootdir: D:\PythonPrograms\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 17 items
<Package 'D:\\PythonPrograms\\Python_Pytest\\TestScripts'><Module 'test_asserts.py'><Function 'test_add'><Function 'test_add2'><Function 'test_add3'><Function 'test_add4'><Function 'test_in'><Function 'test_not_in'><Function 'test_true'><Module 'test_fixture1.py'><Function 'test_numbers_3_4'><Function 'test_strings_a_3'><Module 'test_fixture2.py'><Class 'TestUM'><Function 'test_numbers_5_6'><Function 'test_strings_b_2'><Module 'test_one.py'><Function 'test_equal'><Function 'test_not_equal'><Module 'test_two.py'><Function 'test_default'><Function 'test_member_access'><Function 'test_asdict'><Function 'test_replace'>============================================= no tests ran in 0.09 seconds ==============================================
-k

該選項允許我們使用表達式指定希望運行的測試用例,如果某測試名是唯一的或者多個測試名的前綴或后綴相同,則可以使用這個選項來執行,如下執行結果所示:

D:\PythonPrograms\Python_Pytest\TestScripts>pytest -k "asdict or default" --collect-only
================================================= test session starts ===================================================
platform win32 -- Python 3.7.2, pytest-4.0.2, py-1.8.0, pluggy-0.12.0
rootdir: D:\PythonPrograms\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 17 items / 15 deselected
<Package 'D:\\PythonPrograms\\Python_Pytest\\TestScripts'><Module 'test_two.py'><Function 'test_default'><Function 'test_asdict'>============================================ 15 deselected in 0.06 seconds ===========================================

從執行結果中我們能看到使用-k和–collect-only組合能夠查詢到我們設置的參數所能執行的測試方法。
然后我們將–collect-only從命令行移出,只使用-k便可執行test_default和test_asdict了

D:\PythonPrograms\Python_Pytest\TestScripts>pytest -k "asdict or default"
================================================ test session starts =================================================
platform win32 -- Python 3.7.2, pytest-4.0.2, py-1.8.0, pluggy-0.12.0
rootdir: D:\PythonPrograms\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 17 items / 15 deselectedtest_two.py ..                                                           [100%]============================================= 2 passed, 15 deselected in 0.07 seconds ================================

如果我們在定義用例名的時候特別注意一下便可以使用-k的方式執行一系列測試用例了,同時表達式中科包含 and、or、not

-m

用于標記并分組,然后僅執行帶有標記的用例,如此便實現了執行某個測試集合的場景,如下代碼所示,給我們之前的兩個測試方法添加標記

@pytest.mark.run_these_cases
def test_member_access():"""利用屬性名來訪問對象成員:return:"""t = Task('buy milk', 'brian')assert t.summary == 'buy milk'assert t.owner == 'brian'assert(t.done,  t.id) == (False, None)@pytest.mark.run_these_cases
def test_asdict():"""_asdict()返回一個字典"""t_task = Task('do something','okken',True, 21)t_dict = t_task._asdict()expected_dict = {'summary': 'do something','owner': 'okken','done': True,'id': 21}assert t_dict == expected_dict

執行命令pytest -v -m run_these_cases,結果如下:

D:\PythonPrograms\Python_Pytest\TestScripts>pytest -v -m run_these_cases
============================================== test session starts ======================================================
platform win32 -- Python 3.7.2, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 -- c:\python37\python.exe
cachedir: .pytest_cache
rootdir: D:\PythonPrograms\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 17 items / 15 deselectedtest_two.py::test_member_access PASSED                                   [ 50%]
test_two.py::test_asdict PASSED                                          [100%]======================================= 2 passed, 15 deselected in 0.07 seconds =========================================

-m選項也可以用表達式指定多個標記名,例如-m “mark1 and mark2” 或者-m “mark1 and not mark2” 或者-m “mark1 or mark2”

-x

Pytest會運行每一個搜索到的測試用例,如果某個測試函數被斷言失敗,或者觸發了外部異常,則該測試用例的運行就會停止,pytest將其標記為失敗后繼續運行一下測試用例,然而在debug的時候,我們往往希望遇到失敗時立刻停止整個會話,-x選項為我們提供了該場景的支持,如下執行結果所示:

E:\Programs\Python\Python_Pytest\TestScripts>pytest -x
=============================================== test session starts =================================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts
plugins: allure-pytest-2.6.3
collected 17 items                                                                                                                                                                                                                     test_asserts.py ...F=====================================================FAILURES ===========================================================
____________________________________________________test_add4 ___________________________________________________________def test_add4():
>       assert add(17,22) >= 50
E       assert 39 >= 50
E        +  where 39 = add(17, 22)test_asserts.py:34: AssertionError
============================================ warnings summary ===========================================================
c:\python37\lib\site-packages\_pytest\mark\structures.py:324c:\python37\lib\site-packages\_pytest\mark\structures.py:324: PytestUnknownMarkWarning: Unknown pytest.mark.run_these_cases - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pyt
est.org/en/latest/mark.htmlPytestUnknownMarkWarning,-- Docs: https://docs.pytest.org/en/latest/warnings.html
=============================== 1 failed, 3 passed, 1 warnings in 0.41 seconds ==========================================

在執行結果中我們可以看到實際收集的測試用例是17條,但執行了4條,通過3條失敗一條,執行便停止了。
如果不適用-x選項再執行一次結果如下:

E:\Programs\Python\Python_Pytest\TestScripts>pytest --tb=no
============================================ test session starts =====================================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts
plugins: allure-pytest-2.6.3
collected 17 items                                                                                                                                                                                                                     test_asserts.py ...F..F                                                                                                                                                                                                          [ 41%]
test_fixture1.py ..                                                                                                                                                                                                              [ 52%]
test_fixture2.py ..                                                                                                                                                                                                              [ 64%]
test_one.py .F                                                                                                                                                                                                                   [ 76%]
test_two.py ....                                                                                                                                                                                                                 [100%]============================================= warnings summary =======================================================
c:\python37\lib\site-packages\_pytest\mark\structures.py:324c:\python37\lib\site-packages\_pytest\mark\structures.py:324: PytestUnknownMarkWarning: Unknown pytest.mark.run_these_cases - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pyt
est.org/en/latest/mark.htmlPytestUnknownMarkWarning,-- Docs: https://docs.pytest.org/en/latest/warnings.html
==================================== 3 failed, 14 passed, 1 warnings in 0.31 seconds =================================

從執行結果中我們看到一共收集的測試用例為17條,14條通過,3條失敗,使用了選項–tb=no關閉錯誤信息回溯,當我們只想看執行結果而不想看那么多報錯信息的時候可以使用它。

--maxfail=num

-x是遇到失敗便全局停止,如果我們想遇到失敗幾次再停止呢?–maxfail選項為我們提供了這個場景的支持,如下執行結果所示:

E:\Programs\Python\Python_Pytest\TestScripts>pytest --maxfail=2 --tb=no
============================================= test session starts =======================================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts
plugins: allure-pytest-2.6.3
collected 17 items                                                                                                                                                                                                                     test_asserts.py ...F..F================================================= warnings summary ======================================================
c:\python37\lib\site-packages\_pytest\mark\structures.py:324c:\python37\lib\site-packages\_pytest\mark\structures.py:324: PytestUnknownMarkWarning: Unknown pytest.mark.run_these_cases - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pyt
est.org/en/latest/mark.htmlPytestUnknownMarkWarning,-- Docs: https://docs.pytest.org/en/latest/warnings.html
========================================= 2 failed, 5 passed, 1 warnings in 0.22 seconds ================================

從執行結果中我們看到收集了17條用例,執行了7條,當錯誤數量達到2的時候便停止了執行。

--tb=
命令及參數描述
pytest --showlocals# show local variables in tracebacks
pytest -l# show local variables (shortcut)
pytest --tb=auto# (default) ‘long’ tracebacks for the first and last entry, but ‘short’ style for the other entries
pytest --tb=long# exhaustive, informative traceback formatting
pytest --tb=short# shorter traceback format
pytest --tb=line# only one line per failure
pytest --tb=native# Python standard library formatting
pytest --tb=no# no traceback at all
pytest --full-trace#causes very long traces to be printed on error (longer than --tb=long).
-v (--verbose)

-v, --verbose:increase verbosity.

-q (--quiet)

-q, --quiet:decrease verbosity.

--lf (--last-failed)

–lf, --last-failed:rerun only the tests that failed at the last run (or all if none failed)

E:\Programs\Python\Python_Pytest\TestScripts>pytest --lf --tb=no
================================== test session starts ==========================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts
plugins: allure-pytest-2.6.3
collected 9 items / 6 deselected / 3 selected                                                                                                                                                                                          
run-last-failure: rerun previous 3 failures (skipped 7 files)
test_asserts.py FF                                                                                                                                                                                                               [ 66%]
test_one.py F                                                                                                                                                                                                                    [100%]
============================= 3 failed, 6 deselected in 0.15 seconds ============================
--ff (--failed-first)

–ff, --failed-first :run all tests but run the last failures first. This may re-order tests and thus lead to repeated fixture setup/teardown

E:\Programs\Python\Python_Pytest\TestScripts>pytest --ff --tb=no
================================= test session starts ==================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: E:\Programs\Python\Python_Pytest\TestScripts
plugins: allure-pytest-2.6.3
collected 17 items                                                                                                                                                                                                                     
run-last-failure: rerun previous 3 failures first
test_asserts.py FF                                                                                                                                                                                                               [ 11%]
test_one.py F                                                                                                                                                                                                                    [ 17%]
test_asserts.py .....                                                                                                                                                                                                            [ 47%]
test_fixture1.py ..                                                                                                                                                                                                              [ 58%]
test_fixture2.py ..                                                                                                                                                                                                              [ 70%]
test_one.py .                                                                                                                                                                                                                    [ 76%]
test_two.py ....                                                                                                                                                                                                                 [100%]
======================== warnings summary ==========================================
c:\python37\lib\site-packages\_pytest\mark\structures.py:324c:\python37\lib\site-packages\_pytest\mark\structures.py:324: PytestUnknownMarkWarning: Unknown pytest.mark.run_these_cases - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pyt
est.org/en/latest/mark.htmlPytestUnknownMarkWarning,-- Docs: https://docs.pytest.org/en/latest/warnings.html
================= 3 failed, 14 passed, 1 warnings in 0.25 seconds ==========================
-s與--capture=method

-s等同于--capture=no

 (venv) D:\Python_Pytest\TestScripts>pytest -s
============================= test session starts ============================================
platform win32 -- Python 3.7.3, pytest-4.0.2, py-1.8.0, pluggy-0.12.0
rootdir: D:\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 18 items                                                                                                                                                                                                                        test_asserts.py ...F...F
test_fixture1.pysetup_module================>
setup_function------>
test_numbers_3_4
.teardown_function--->
setup_function------>
test_strings_a_3
.teardown_function--->
teardown_module=============>test_fixture2.pysetup_class=========>
setup_method----->>
setup----->
test_numbers_5_6
.teardown-->
teardown_method-->>
setup_method----->>
setup----->
test_strings_b_2
.teardown-->
teardown_method-->>
teardown_class=========>test_one.py .F
test_two.py ....========================================== FAILURES ============================================
____________________________________________ test_add4 ______________________________________________@pytest.mark.aaaadef test_add4():
>       assert add(17, 22) >= 50
E       assert 39 >= 50
E        +  where 39 = add(17, 22)test_asserts.py:36: AssertionError
_____________________________________________________________________________________________________________ test_not_true ______________________________________________________________________________________________________________def test_not_true():
>       assert not is_prime(7)
E       assert not True
E        +  where True = is_prime(7)test_asserts.py:70: AssertionError
_______________________________________ test_not_equal ________________________________________________def test_not_equal():
>       assert (1, 2, 3) == (3, 2, 1)
E       assert (1, 2, 3) == (3, 2, 1)
E         At index 0 diff: 1 != 3
E         Use -v to get the full difftest_one.py:9: AssertionError
================================== 3 failed, 15 passed in 0.15 seconds =================================

--capture=method per-test capturing method: one of fd|sys|no.

-l (--showlocals)

-l, --showlocals show locals in tracebacks (disabled by default).

--duration=N

--durations=N show N slowest setup/test durations (N=0 for all).
該選項絕大多數用于調優測試代碼,該選項展示最慢的N個用例,等于0則表示全部倒序

(venv) D:\Python_Pytest\TestScripts>pytest --duration=5
===================================================== test session starts ==============================================
platform win32 -- Python 3.7.3, pytest-4.0.2, py-1.8.0, pluggy-0.12.0
rootdir: D:\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 18 items                                                             test_asserts.py ...F...F                                                 [ 44%]
test_fixture1.py ..                                                      [ 55%]
test_fixture2.py ..                                                      [ 66%]
test_one.py .F                                                           [ 77%]
test_two.py ....                                                         [100%]======================================================= FAILURES ======================================================
_______________________________________________________ test_add4 _____________________________________________________@pytest.mark.aaaadef test_add4():
>       assert add(17, 22) >= 50
E       assert 39 >= 50
E        +  where 39 = add(17, 22)test_asserts.py:36: AssertionError
_____________________________________________________ test_not_true _____________________________________________________def test_not_true():
>       assert not is_prime(7)
E       assert not True
E        +  where True = is_prime(7)test_asserts.py:70: AssertionError
___________________________________________________ test_not_equal ______________________________________________________def test_not_equal():
>       assert (1, 2, 3) == (3, 2, 1)
E       assert (1, 2, 3) == (3, 2, 1)
E         At index 0 diff: 1 != 3
E         Use -v to get the full difftest_one.py:9: AssertionError
================================================ slowest 5 test durations ===============================================
0.01s call     test_asserts.py::test_add4(0.00 durations hidden.  Use -vv to show these durations.)
========================================== 3 failed, 15 passed in 0.27 seconds ==========================================

在執行結果中我們看到提示(0.00 durations hidden. Use -vv to show these durations.),如果加上-vv,執行結果如下:

(venv) D:\Python_Pytest\TestScripts>pytest --duration=5 -vv
============================= test session starts =============================
platform win32 -- Python 3.7.3, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 -- c:\python37\python.exe
cachedir: .pytest_cache
rootdir: D:\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 18 items                                                             test_asserts.py::test_add PASSED                                         [  5%]
test_asserts.py::test_add2 PASSED                                        [ 11%]
test_asserts.py::test_add3 PASSED                                        [ 16%]
test_asserts.py::test_add4 FAILED                                        [ 22%]
test_asserts.py::test_in PASSED                                          [ 27%]
test_asserts.py::test_not_in PASSED                                      [ 33%]
test_asserts.py::test_true PASSED                                        [ 38%]
test_asserts.py::test_not_true FAILED                                    [ 44%]
test_fixture1.py::test_numbers_3_4 PASSED                                [ 50%]
test_fixture1.py::test_strings_a_3 PASSED                                [ 55%]
test_fixture2.py::TestUM::test_numbers_5_6 PASSED                        [ 61%]
test_fixture2.py::TestUM::test_strings_b_2 PASSED                        [ 66%]
test_one.py::test_equal PASSED                                           [ 72%]
test_one.py::test_not_equal FAILED                                       [ 77%]
test_two.py::test_default PASSED                                         [ 83%]
test_two.py::test_member_access PASSED                                   [ 88%]
test_two.py::test_asdict PASSED                                          [ 94%]
test_two.py::test_replace PASSED                                         [100%]====================================================== FAILURES =========================================================
______________________________________________________ test_add4 ________________________________________________________@pytest.mark.aaaadef test_add4():
>       assert add(17, 22) >= 50
E       assert 39 >= 50
E        +  where 39 = add(17, 22)test_asserts.py:36: AssertionError
____________________________________________________ test_not_true ____________________________________________________def test_not_true():
>       assert not is_prime(7)
E       assert not True
E        +  where True = is_prime(7)test_asserts.py:70: AssertionError
___________________________________________________ test_not_equal ____________________________________________________def test_not_equal():
>       assert (1, 2, 3) == (3, 2, 1)
E       assert (1, 2, 3) == (3, 2, 1)
E         At index 0 diff: 1 != 3
E         Full diff:
E         - (1, 2, 3)
E         ?  ^     ^
E         + (3, 2, 1)
E         ?  ^     ^test_one.py:9: AssertionError
============================================== slowest 5 test durations ===============================================
0.00s setup    test_one.py::test_not_equal
0.00s setup    test_fixture1.py::test_strings_a_3
0.00s setup    test_asserts.py::test_add3
0.00s call     test_fixture2.py::TestUM::test_strings_b_2
0.00s call     test_asserts.py::test_in
========================================= 3 failed, 15 passed in 0.16 seconds =========================================
-r

生成一個簡短的概述報告,同時配合-r還可以使用

OptionDescription
ffailed
Eerror
sskipped
xxfailed
Xxpassed
ppassed
Ppassed with output
aall except pP
Aall
例如只想看失敗的和跳過的測試,可以這樣執行

(venv) E:\Python_Pytest\TestScripts>pytest -rfs
=================================================== test session starts =================================================
platform win32 -- Python 3.7.3, pytest-4.0.2, py-1.8.0, pluggy-0.12.0
rootdir: E:\Python_Pytest\TestScripts, inifile:
plugins: allure-adaptor-1.7.10
collected 18 items                                                             test_asserts.py ...F...F                                                 [ 44%]
test_fixture1.py ..                                                      [ 55%]
test_fixture2.py ..                                                      [ 66%]
test_one.py .F                                                           [ 77%]
test_two.py ....                                                         [100%]==================================================== FAILURES ===========================================================
____________________________________________________ test_add4 __________________________________________________________@pytest.mark.aaaadef test_add4():
>       assert add(17, 22) >= 50
E       assert 39 >= 50
E        +  where 39 = add(17, 22)test_asserts.py:36: AssertionError
__________________________________________________ test_not_true _______________________________________________________def test_not_true():
>       assert not is_prime(7)
E       assert not True
E        +  where True = is_prime(7)test_asserts.py:70: AssertionError
____________________________________________________ test_not_equal _____________________________________________________def test_not_equal():
>       assert (1, 2, 3) == (3, 2, 1)
E       assert (1, 2, 3) == (3, 2, 1)
E         At index 0 diff: 1 != 3
E         Use -v to get the full difftest_one.py:9: AssertionError
================================================ short test summary info ================================================
FAIL test_asserts.py::test_add4
FAIL test_asserts.py::test_not_true
FAIL test_one.py::test_not_equal
======================================== 3 failed, 15 passed in 0.10 seconds ============================================
pytest --help獲取更多參數

在命令行輸入pytest --help 然后執行結果如下,在打印出來的結果中我們能夠看到pytest命令的使用方式usage: pytest [options] [file_or_dir] [file_or_dir] […]以及一系列的執行方式(options)及其描述。

C:\Users\Administrator>pytest --help
usage: pytest [options] [file_or_dir] [file_or_dir] [...]
positional arguments:file_or_dir
general:-k EXPRESSION         only run tests which match the given substringexpression. An expression is a python evaluatableexpression where all names are substring-matchedagainst test names and their parent classes. Example:-k 'test_method or test_other' matches all testfunctions and classes whose name contains'test_method' or 'test_other', while -k 'nottest_method' matches those that don't contain'test_method' in their names. Additionally keywordsare matched to classes and functions containing extranames in their 'extra_keyword_matches' set, as well asfunctions which have names assigned directly to them.-m MARKEXPR           only run tests matching given mark expression.example: -m 'mark1 and not mark2'.--markers             show markers (builtin, plugin and per-project ones).-x, --exitfirst       exit instantly on first error or failed test.--maxfail=num         exit after first num failures or errors.--strict              marks not registered in configuration file raiseerrors.-c file               load configuration from `file` instead of trying tolocate one of the implicit configuration files.--continue-on-collection-errorsForce test execution even if collection errors occur.--rootdir=ROOTDIR     Define root directory for tests. Can be relative path:'root_dir', './root_dir', 'root_dir/another_dir/';absolute path: '/home/user/root_dir'; path withvariables: '$HOME/root_dir'.--fixtures, --funcargsshow available fixtures, sorted by plugin appearance(fixtures with leading '_' are only shown with '-v')--fixtures-per-test   show fixtures per test--import-mode={prepend,append}prepend/append to sys.path when importing testmodules, default is to prepend.--pdb                 start the interactive Python debugger on errors orKeyboardInterrupt.--pdbcls=modulename:classnamestart a custom interactive Python debugger on errors.For example:--pdbcls=IPython.terminal.debugger:TerminalPdb--trace               Immediately break when running each test.--capture=method      per-test capturing method: one of fd|sys|no.-s                    shortcut for --capture=no.--runxfail            run tests even if they are marked xfail--lf, --last-failed   rerun only the tests that failed at the last run (orall if none failed)--ff, --failed-first  run all tests but run the last failures first. Thismay re-order tests and thus lead to repeated fixturesetup/teardown--nf, --new-first     run tests from new files first, then the rest of thetests sorted by file mtime--cache-show          show cache contents, don't perform collection or tests--cache-clear         remove all cache contents at start of test run.--lfnf={all,none}, --last-failed-no-failures={all,none}change the behavior when no test failed in the lastrun or no information about the last failures wasfound in the cache--sw, --stepwise      exit on test fail and continue from last failing testnext time--stepwise-skip       ignore the first failing test but stop on the nextfailing test--allure_severities=SEVERITIES_SETComma-separated list of severity names. Tests onlywith these severities will be run. Possible valuesare:blocker, critical, minor, normal, trivial.--allure_features=FEATURES_SETComma-separated list of feature names. Run tests thathave at least one of the specified feature labels.--allure_stories=STORIES_SETComma-separated list of story names. Run tests thathave at least one of the specified story labels.reporting:-v, --verbose         increase verbosity.-q, --quiet           decrease verbosity.--verbosity=VERBOSE   set verbosity-r chars              show extra test summary info as specified by chars(f)ailed, (E)error, (s)skipped, (x)failed, (X)passed,(p)passed, (P)passed with output, (a)all except pP.Warnings are displayed at all times except when--disable-warnings is set--disable-warnings, --disable-pytest-warningsdisable warnings summary-l, --showlocals      show locals in tracebacks (disabled by default).--tb=style            traceback print mode (auto/long/short/line/native/no).--show-capture={no,stdout,stderr,log,all}Controls how captured stdout/stderr/log is shown onfailed tests. Default is 'all'.--full-trace          don't cut any tracebacks (default is to cut).--color=color         color terminal output (yes/no/auto).--durations=N         show N slowest setup/test durations (N=0 for all).--pastebin=mode       send failed|all info to bpaste.net pastebin service.--junit-xml=path      create junit-xml style report file at given path.--junit-prefix=str    prepend prefix to classnames in junit-xml output--result-log=path     DEPRECATED path for machine-readable result log.collection:--collect-only        only collect tests, don't execute them.--pyargs              try to interpret all arguments as python packages.--ignore=path         ignore path during collection (multi-allowed).--deselect=nodeid_prefixdeselect item during collection (multi-allowed).--confcutdir=dir      only load conftest.py's relative to specified dir.--noconftest          Don't load any conftest.py files.--keep-duplicates     Keep duplicate tests.--collect-in-virtualenvDon't ignore tests in a local virtualenv directory--doctest-modules     run doctests in all .py modules--doctest-report={none,cdiff,ndiff,udiff,only_first_failure}choose another output format for diffs on doctestfailure--doctest-glob=pat    doctests file matching pattern, default: test*.txt--doctest-ignore-import-errorsignore doctest ImportErrors--doctest-continue-on-failurefor a given doctest, continue to run after the firstfailuretest session debugging and configuration:--basetemp=dir        base temporary directory for this test run.(warning:this directory is removed if it exists)--version             display pytest lib version and import information.-h, --help            show help message and configuration info-p name               early-load given plugin (multi-allowed). To avoidloading of plugins, use the `no:` prefix, e.g.`no:doctest`.--trace-config        trace considerations of conftest.py files.--debug               store internal tracing debug information in'pytestdebug.log'.-o OVERRIDE_INI, --override-ini=OVERRIDE_INIoverride ini option with "option=value" style, e.g.`-o xfail_strict=True -o cache_dir=cache`.--assert=MODE         Control assertion debugging tools. 'plain' performs noassertion debugging. 'rewrite' (the default) rewritesassert statements in test modules on import to provideassert expression information.--setup-only          only setup fixtures, do not execute tests.--setup-show          show setup of fixtures while executing tests.--setup-plan          show what fixtures and tests would be executed butdon't execute anything.pytest-warnings:-W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGSset which warnings to report, see -W option of pythonitself.logging:--no-print-logs       disable printing caught logs on failed tests.--log-level=LOG_LEVELlogging level used by the logging module--log-format=LOG_FORMATlog format as used by the logging module.--log-date-format=LOG_DATE_FORMATlog date format as used by the logging module.--log-cli-level=LOG_CLI_LEVELcli logging level.--log-cli-format=LOG_CLI_FORMATlog format as used by the logging module.--log-cli-date-format=LOG_CLI_DATE_FORMATlog date format as used by the logging module.--log-file=LOG_FILE   path to a file when logging will be written to.--log-file-level=LOG_FILE_LEVELlog file logging level.--log-file-format=LOG_FILE_FORMATlog format as used by the logging module.--log-file-date-format=LOG_FILE_DATE_FORMATlog date format as used by the logging module.reporting:--alluredir=DIR       Generate Allure report in the specified directory (maynot exist)[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:markers (linelist)       markers for test functionsempty_parameter_set_mark (string) default marker for empty parametersetsnorecursedirs (args)     directory patterns to avoid for recursiontestpaths (args)         directories to search for tests when no files or direconsole_output_style (string) console output: classic or with additional progrusefixtures (args)       list of default fixtures to be used with this projectpython_files (args)      glob-style file patterns for Python test module discopython_classes (args)    prefixes or glob names for Python test class discoverpython_functions (args)  prefixes or glob names for Python test function and mxfail_strict (bool)      default for the strict parameter of xfail markers whejunit_suite_name (string) Test suite name for JUnit reportjunit_logging (string)   Write captured log messages to JUnit report: one of ndoctest_optionflags (args) option flags for doctestsdoctest_encoding (string) encoding used for doctest filescache_dir (string)       cache directory path.filterwarnings (linelist) Each line specifies a pattern for warnings.filterwarlog_print (bool)         default value for --no-print-logslog_level (string)       default value for --log-levellog_format (string)      default value for --log-formatlog_date_format (string) default value for --log-date-formatlog_cli (bool)           enable log display during test run (also known as "lilog_cli_level (string)   default value for --log-cli-levellog_cli_format (string)  default value for --log-cli-formatlog_cli_date_format (string) default value for --log-cli-date-formatlog_file (string)        default value for --log-filelog_file_level (string)  default value for --log-file-levellog_file_format (string) default value for --log-file-formatlog_file_date_format (string) default value for --log-file-date-formataddopts (args)           extra command line optionsminversion (string)      minimally required pytest versionenvironment variables:PYTEST_ADDOPTS           extra command line optionsPYTEST_PLUGINS           comma-separated plugins to load during startupPYTEST_DISABLE_PLUGIN_AUTOLOAD set to disable plugin auto-loadingPYTEST_DEBUG             set to enable debug tracing of pytest's internalsto see available markers type: pytest --markers
to see available fixtures type: pytest --fixtures
(shown according to specified file_or_dir or current dir if not specified; fixtures with leading '_' are only shown with the '-v' option

理解Pytest的配置文件

Pytest里有哪些配置文件:

配置文件描述:無論選擇使用哪種配置文件,它們的格式幾乎是一樣的
pytest.inipytest主配置文件,可以改變pytest默認行為
conftest.py本地插件庫,其中的hook函數和fixture將作用于該文件所在目錄及其子目錄
__init__.py每個測試子目錄都包含該文件時,在多個測試目錄中可以出現同名的測試文件
tox.ini如果你使用tox工具,會用到tox.ini,它與pytest.ini類似,只不過是tox的配置文件,可以把pytest的配置寫在tox.ini里,就無需同時使用pytest.ini和tox.ini了
setup.cfg它也采用ini文件格式,而且可以影響setup.py的行為,如果要發布一個python包,它的作用也很大,可以在setup.py文件里添加幾行代碼,使用python setup.py test 運行所有的pytest測試用例;如果打算發布python包,也可以使用setup.cfg文件存儲pytest的配置信息
pytest.ini
;---
; Excerpted from "Python Testing with pytest",
; published by The Pragmatic Bookshelf.
; Copyrights apply to this code. It may not be used to create training material,
; courses, books, articles, and the like. Contact us if you are in doubt.
; We make no guarantees that this code is fit for any purpose.
; Visit http://www.pragmaticprogrammer.com/titles/bopytest for more book information.
;---
[pytest]
addopts = -rsxX -l --tb=short --strict
xfail_strict = true
;... more options ...

tox.ini

;---
; Excerpted from "Python Testing with pytest",
; published by The Pragmatic Bookshelf.
; Copyrights apply to this code. It may not be used to create training material,
; courses, books, articles, and the like. Contact us if you are in doubt.
; We make no guarantees that this code is fit for any purpose.
; Visit http://www.pragmaticprogrammer.com/titles/bopytest for more book information.
;---
;... tox specific stuff ...[pytest]
addopts = -rsxX -l --tb=short --strict
xfail_strict = true
;... more options ...

setup.cfg

;... packaging specific stuff ...[tool:pytest]
addopts = -rsxX -l --tb=short --strict
xfail_strict = true
;... more options ...

執行命令pytest --help能夠看到所有設置選項


[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:markers (linelist)       markers for test functionsempty_parameter_set_mark (string) default marker for empty parametersetsnorecursedirs (args)     directory patterns to avoid for recursiontestpaths (args)         directories to search for tests when no files or directories are given in the command line.usefixtures (args)       list of default fixtures to be used with this projectpython_files (args)      glob-style file patterns for Python test module discoverypython_classes (args)    prefixes or glob names for Python test class discoverypython_functions (args)  prefixes or glob names for Python test function and method discoverydisable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool) disable string escape non-ascii characters, might cause unwanted side effects(use at your ownconsole_output_style (string) console output: "classic", or with additional progress information ("progress" (percentage) | "count").xfail_strict (bool)      default for the strict parameter of xfail markers when not given explicitly (default: False)junit_suite_name (string) Test suite name for JUnit reportjunit_logging (string)   Write captured log messages to JUnit report: one of no|system-out|system-errjunit_duration_report (string) Duration time to report: one of total|calljunit_family (string)    Emit XML for schema: one of legacy|xunit1|xunit2doctest_optionflags (args) option flags for doctestsdoctest_encoding (string) encoding used for doctest filescache_dir (string)       cache directory path.filterwarnings (linelist) Each line specifies a pattern for warnings.filterwarnings. Processed after -W and --pythonwarnings.log_print (bool)         default value for --no-print-logslog_level (string)       default value for --log-levellog_format (string)      default value for --log-formatlog_date_format (string) default value for --log-date-formatlog_cli (bool)           enable log display during test run (also known as "live logging").log_cli_level (string)   default value for --log-cli-levellog_cli_format (string)  default value for --log-cli-formatlog_cli_date_format (string) default value for --log-cli-date-formatlog_file (string)        default value for --log-filelog_file_level (string)  default value for --log-file-levellog_file_format (string) default value for --log-file-formatlog_file_date_format (string) default value for --log-file-date-formataddopts (args)           extra command line optionsminversion (string)      minimally required pytest versionrsyncdirs (pathlist)     list of (relative) paths to be rsynced for remote distributed testing.rsyncignore (pathlist)   list of (relative) glob-style paths to be ignored for rsyncing.looponfailroots (pathlist) directories to check for changestimeout (string)         Timeout in seconds before dumping the stacks.  Default is 0 which
means no timeout.timeout_method (string)  Timeout mechanism to use.  'signal' uses SIGALRM if available,
'thread' uses a timer thread.  The default is to use 'signal' and fall
back to 'thtimeout_func_only (bool) When set to True, defers the timeout evaluation to only the test
function body, ignoring the time it takes when evaluating any fixtures
used in tpytester_example_dir (string) directory to take the pytester example files fromenvironment variables:PYTEST_ADDOPTS           extra command line optionsPYTEST_PLUGINS           comma-separated plugins to load during startupPYTEST_DISABLE_PLUGIN_AUTOLOAD set to disable plugin auto-loadingPYTEST_DEBUG             set to enable debug tracing of pytest's internals

插件可以添加ini文件選項

除了前邊列出來的這些選項,利用插件和conftest.py文件還可以添加新的選項,而且新增的選項也可以使用pytest --help查看。

更改默認命令行選項

經過前邊的文章,已經涉獵到很多pytest選項了,例如-v/–verbose可以輸出詳細信息,-l/–showlocals可以查看失敗測試用例里堆棧中的局部變量,你可能經常用到這些選項,但又不想重復輸入,此時就可以借助pytest.ini文件里的addopts設置

[pytest]
addopts = -rsxX -l --tb=short --strict
選項介紹
-rsxX表示pytest報告所有測試用例被跳過、預計失敗、預計失敗但實際通過的原因
-l表示pytest報告所有失敗測試用例的對戰中的局部變量
–tb=short表示簡化堆棧回溯信息,只保留文件和行數
–strict選項表示禁止使用未在配置文件中注冊的標記

注冊標記來防范拼寫錯誤

在pytest.ini中注冊標記:

[pytest]
markers=smoke: Run the smoke test functions for tasks projectget:Run the test functions that test tasks.get()

標記注冊好后,可以通過pytest --markers來查看

(venv) E:\Programs\Python\Python_Pytest\pytest-nice>pytest --markers
@pytest.mark.smoke: Run the smoke test functions for tasks project@pytest.mark.get:Run the test functions that test tasks.get()

這樣當我們給addopts加上–strict時,沒有注冊的標記就不能再使用,因此也就盡可能減少拼寫錯誤

指定pytest的最低版本號

minversion選項可以指定運行測試用例的pytest的最低版本,例如測試兩個浮點數的值是否接近,我們會使用approx()函數,但這個功能直到pytest3.0才出現,為此我們可以在pytest.ini文件中添加

[pytest]
minversion = 3.0

指定pytest忽略某些目錄

pytest執行搜索時,會遞歸遍歷所有子目錄,可以使用norecurse選項簡化pytest的搜索工作。
norecurse的默認值是.* build dist CVS _darcs {arch} *.egg
如果讓pytest忽略Tasks項目的src目錄,則需要加入norecursedirs里

[pytest]
norecursedirs = .* venv src *.egg dist build

指定測試目錄

testpaths只是pytest去哪里訪問,它是一系列相對于根目錄的路徑,用于限定測試用例的搜索范圍,只有在pytest未指定文件目錄參數或者測試用例標識符時,該選項才會啟動。

task_proj/
|------pytest.ini
|------src
|		|------tasks
|		|------api.py
|		|------......
|------test|------conftest.py|------func|		|------__init__py|		|------test_add.py|		|------......|------unit|------__init__.py|------test_task.py|------......

例如這樣的機構目錄,我們要指定test目錄為pytest的執行路徑

[pytest]
testpaths = test

然后只需要從tasks_proj開始運行pytest,pytest就會直接去找test路徑。

更改測試搜索的規則

pytest的執行,是根據一定的規則搜索并運行測試的:

  • 從一個或多個目錄開始查找
  • 在該目錄和所有子目錄下遞歸查找測試模塊
  • 測試模塊是指定文件名為test_.py和_test.py的文件
  • 在測試模塊中查找以test_開頭的函數名
  • 查找名字以Test開頭的類,首先篩選掉包含__init__函數的類,再查找類中以Test_開頭的類方法

接下來修改規則:
默認規則pytest尋找Test*開頭的類,而這個類不能含有__init__()函數,可以使用python_classes來修改

 [pytest]python_classes = *Test Test* *Suite

像python_classes一樣,python_files可以更改默認的測試搜索規則,而不是僅查找以test_開頭的文件和_test結尾的文件

[pytest]
python_files = test_* *_test check_*

同樣的可以修改搜索測試函數和方法的命名規則

[pytest]
python_functions = test_* check_*

禁用XPASS

設置xfail_strict = true將會使那些被標記為@pytest.mark.xfail但是實際通過的測試用例也會報告為失敗。

避免文件名沖突

duplicate
|------dup_a
|		|------test_func.py
|		dup_b
|		|------test_func.py		

兩個py文件中分別寫入函數test_a()和test_b()

def test_a():pass
def test_b():pass

如此目錄結構,兩個同名文件,雖然文件內容不同,但他們還是會沖突,可以單獨運行py文件,但在duplicate路徑下執行就不行了,會報如下錯誤:


(venv) E:\Programs\Python\Python_Pytest\SourceCode\ch6\duplicate>pytest
================== test session starts ===================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: E:\Programs\Python\Python_Pytest, inifile: pytest.ini
plugins: xdist-1.29.0, timeout-1.3.3, repeat-0.8.0, nice-0.1.0, instafail-0.4.1, forked-1.0.2, emoji-0.2.0, allure-pytest-2.6.3
collected 1 item / 1 errors                                                                                                                                                =========================================== ERRORS ============================
____________________ ERROR collecting SourceCode/ch6/duplicate/b/test_func.py __________________________
import file mismatch:
imported module 'test_func' has this __file__ attribute:E:\Programs\Python\Python_Pytest\SourceCode\ch6\duplicate\a\test_func.py
which is not the same as the test file we want to collect:E:\Programs\Python\Python_Pytest\SourceCode\ch6\duplicate\b\test_func.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modules
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 error in 0.32 seconds ==========================================

報錯信息中也并沒明顯指出問題在哪,要解決這個問題,只需要在各個子目錄里添加一個空的__init__.py文件即可,測試子目錄添加__init__.py是個好習慣

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/44180.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44180.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44180.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Pytorch】Conda環境下載慢換源/刪源/恢復默認源

文章目錄 背景臨時換源永久換源打開conda配置condarc換源執行配置 命令行修改源添加源查看源 刪源恢復默認源使用示范 背景 隨著實驗增多&#xff0c;需要分割創建環境的情況時有出現&#xff0c;在此情況下使用conda create --name xx python3.10 pytorch torchvision pytorc…

uni-app三部曲之二: 封裝http請求

1.引言 前面一篇文章寫了使用Pinia進行全局狀態管理。 這篇文章主要介紹一下封裝http請求&#xff0c;發送數據請求到服務端進行數據的獲取。 感謝&#xff1a; 1.yudao-mall-uniapp: 芋道商城&#xff0c;基于 Vue Uniapp 實現&#xff0c;支持分銷、拼團、砍價、秒殺、優…

電腦自動重啟是什么原因呢?99%人都不知道的解決辦法,直接打破循環

當你的電腦突然毫無預警地自動重啟&#xff0c;不僅打斷了工作流程&#xff0c;還可能導致未保存的數據丟失&#xff0c;這無疑是一件令人沮喪的事情。那么&#xff0c;電腦自動重啟是什么原因呢&#xff1f;有什么方法可以解決呢&#xff1f;別擔心&#xff0c;在大多數情況下…

Android Retrofit post請求,@Body傳遞的參數轉義問題

文章目錄 問題解決原因解決方案一&#xff1a;自己拼接json字符串&#xff0c;Body使用RequestBody類型&#xff0c;比如解決方案二&#xff1a;修改Retrofit的Gson 問題 因為傳遞的參數字符串中有等號 &#xff0c;結果傳遞的時候&#xff0c;打印出來 原始字符串&#xff…

【AIGC】GPT-4深度解析:自然語言處理的新紀元

目錄 第一部分&#xff1a;GPT-4技術概覽 1.1 GPT-4模型架構 多模態輸入處理 專家混合&#xff08;MoE&#xff09;技術詳解 參數規模和模型復雜性 1.2 GPT-4的關鍵技術創新 上下文窗口的擴展 模型性能預測技術 1.3 GPT-4與其他模型的比較 性能對比 架構差異 第二部…

docker-2

27.構建python應用鏡像-dockerfile實踐項目 1.基于官方的鏡像&#xff0c;構建python代碼運行環境 dockerfile 2.運行鏡像&#xff0c;開啟一個讀寫的容器空間&#xff08;定制操作&#xff0c;將代碼丟進去&#xff0c;運行調試&#xff09; 3.提交這個變化的容器層數據&#…

cal命令

1、命令詳解&#xff1a; cal&#xff08;全稱&#xff1a;Calendar&#xff09;該命令用來顯示當前日歷或者指定日期的公歷。 2、官方參數&#xff1a; -1, --one 僅顯示當前月份&#xff08;默認&#xff09;-3, --three 顯示上個月、當前月和下個月-s, --sunday…

谷粒商城P85發布商品時規格參數不顯示問題

P85講&#xff0c;發布商品&#xff0c;點擊下一步之后&#xff0c;發現規格參數不顯示 打開控制臺發現報錯forEach...錯誤 查了問題原因&#xff0c;發現返回的分組中個別組的關聯屬性(attrs)可能為null 所以這個時候&#xff0c;需要確保后端返回的attrs不能為null 方式1…

數據結構之順序存儲線性表實現詳解與示例(C,C#,C++)

文章目錄 一、順序存儲線性表的基本概念二、順序存儲線性表的實現1、數據結構定義2、初始化3、添加元素4、訪問元素5、修改元素6、刪除元素7、銷毀 三、示例C語言示例C#語言示例C語言示例 順序存儲線性表是一種基本的數據結構&#xff0c;它將線性表的元素按照一定的順序存放在…

Mysql中存儲過程、存儲函數、自定義函數、變量、流程控制語句、光標/游標、定義條件和處理程序的使用示例

場景 存儲過程 存儲過程是一組為了完成特定功能的SQL語句集合。使用存儲過程的目的是將常用或復雜的工作預先用SQL語句寫好并用一個指定名稱存儲起來&#xff0c; 這個過程經編譯和優化后存儲在數據庫服務器中&#xff0c;因此稱為存儲過程。 當以后需要數據庫提供與己定義…

分享WPF的UI開源庫

文章目錄 前言一、HandyControl二、AduSkin三、Adonis UI四、Panuon.WPF.UI五、LayUI-WPF六、MahApps.Metro七、MaterialDesignInXamlToolkit八、FluentWPF九、DMSkin總結 前言 分享WPF的UI開源庫。 一、HandyControl HandyControl是一套WPF控件庫&#xff0c;它幾乎重寫了所…

uni-app 掃描二維碼獲取信息功能

首先是掃描二維碼的功能&#xff0c;可以參考這篇博文 uni-app-H5頁面調用設備攝像頭掃描二維碼_uni-app app端調用攝像頭顯示至指定元素上顯示-CSDN博客 然后現在是可以掃描二維碼的狀態&#xff0c;掃描之后&#xff0c;可以看到首先是出發上一個頁面的事件&#xff0c;然后…

每天一個數據分析題(四百二十五)- 單因素方差分析

關于下表&#xff0c;錯誤說法是&#xff08; &#xff09; A. 這是單因素方差分析的輸出結果 B. 表中 F< F crit, 與 P-value 大于顯著性水平是等價的 C. 表內組間均方差沒有顯著大于組內均方差 D. 由于組內SS數值顯著大于組間SS&#xff0c;因此可以推斷不同分類對于…

使用Python繪制面積圖

使用Python繪制面積圖 面積圖效果代碼 面積圖 面積圖展示數據隨時間的累積變化&#xff0c;適合表現趨勢和總量。通過填充圖形下方的區域&#xff0c;可以直觀地顯示各時間點的數值及其變化。 效果 [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-…

機器學習——決策樹(筆記)

目錄 一、認識決策樹 1. 介紹 2. 決策樹生成過程 二、sklearn中的決策樹 1. tree.DecisionTreeClassifier&#xff08;分類樹&#xff09; &#xff08;1&#xff09;模型基本參數 &#xff08;2&#xff09;模型屬性 &#xff08;3&#xff09;接口 2. tree.Decision…

最新開源免費數字人工具

使用步驟更是簡單到不行&#xff1a; 1. 輸入圖片&#xff1a;選擇你想要生成動態視頻的肖像圖片。 2. 輸入音頻&#xff1a;提供與圖片匹配的音頻文件&#xff0c;EchoMimic會根據音頻內容驅動肖像的動態效果。 3. 設置參數&#xff1a;一般保持默認設置即可&#xff0c;當然&…

排序題目:最小時間差

文章目錄 題目標題和出處難度題目描述要求示例數據范圍 解法思路和算法代碼復雜度分析 題目 標題和出處 標題&#xff1a;最小時間差 出處&#xff1a;539. 最小時間差 難度 3 級 題目描述 要求 給定一個 24 \texttt{24} 24 小時制的時間列表&#xff0c;時間以 &quo…

暗黑魅力:Xcode全面擁抱應用暗黑模式開發指南

暗黑魅力&#xff1a;Xcode全面擁抱應用暗黑模式開發指南 隨著蘋果在iOS 13和iPadOS 13中引入暗黑模式&#xff0c;用戶可以根據自己的喜好或環境光線選擇不同的界面主題。作為開發者&#xff0c;支持暗黑模式不僅能提升用戶體驗&#xff0c;還能彰顯應用的專業性。Xcode提供了…

《夢醒蝶飛:釋放Excel函數與公式的力量》11.4 ISERROR函數

第11章&#xff1a;信息函數 第四節 11.4 ISERROR函數 11.4.1 簡介 ISERROR函數是Excel中的一個信息函數&#xff0c;用于檢查指定單元格或表達式是否產生錯誤。如果單元格或表達式產生任何類型的錯誤&#xff08;如N/A、VALUE!、REF!等&#xff09;&#xff0c;則返回TRUE&…

全開源TikTok跨境商城源碼/TikTok內嵌商城+搭建教程/前端uniapp+后端

多語言跨境電商外貿商城 TikTok內嵌商城&#xff0c;商家入駐一鍵鋪貨一鍵提貨 全開源完美運營 海外版抖音TikTok商城系統源碼&#xff0c;TikToK內嵌商城&#xff0c;跨境商城系統源碼 接在tiktok里面的商城。tiktok內嵌&#xff0c;也可單獨分開出來當獨立站運營 二十一種…