3.pytest命令行參數(shù)
3.1 pytest控制臺(tái)信息詳解
? ? 通常在運(yùn)行pytest之后,會(huì)出現(xiàn)如下所示的控制臺(tái)信息:
C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson01>pytest test_01.py
==================test session starts =======================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson01
collected 2 items
test_01.py .F [100%]
===================FAILURES =================================
__________________ test_add_02 ______________________________
def test_add_02():
> assert Add(3,4)==6
E assert 7 == 6
E + where 7 = Add(3, 4)
test_01.py:12: AssertionError
================ short test summary info ====================
FAILED test_01.py::test_add_02 - assert 7 == 6
=============== 1 failed, 1 passed in 0.56s ==================
- ===== test session starts =====
測(cè)試會(huì)話分隔符,代表啟動(dòng)了一個(gè)新的調(diào)用
- platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
當(dāng)前運(yùn)行的平臺(tái),Python、pytest、pytest包的版本等信息
- rootdir
當(dāng)前起始目錄,pytest搜索測(cè)試代碼時(shí)使用的目錄
- collected 2 items
在搜索的目錄中找到的測(cè)試函數(shù)個(gè)數(shù)
- test_01.py .F
test_01.py代表測(cè)試文件
- FAILED
未通過(guò)的測(cè)試函數(shù)的失敗原因
- 1 failed, 1 passed in 0.14s
統(tǒng)計(jì)測(cè)試函數(shù)通過(guò)和未通過(guò)的數(shù)量及運(yùn)行時(shí)間
3.2 Pytest運(yùn)行結(jié)果類型
? ? 在Pytest中,測(cè)試函數(shù)可能會(huì)返回多種結(jié)果,不像傳統(tǒng)的單元測(cè)試框架,僅顯示通過(guò)和失敗。以下是可能返回的結(jié)果:
- PASSED(.)
測(cè)試通過(guò)。預(yù)期成功,實(shí)際成功
- F(FAILED)
表示測(cè)試未通過(guò),也可能是XPASS狀態(tài)與strict選項(xiàng)造成的沖突。預(yù)期成功,實(shí)際失敗
- SKIPPED(s)
測(cè)試函數(shù)未執(zhí)行,即該運(yùn)行測(cè)試時(shí)跳過(guò)該測(cè)試函數(shù),常用測(cè)試標(biāo)記@pytest.mark.skip()或@pytest.mark.skipif()指定跳過(guò)測(cè)試的條件
- xfail(x)
期望測(cè)試失敗,而且確實(shí)失敗。常用測(cè)試標(biāo)記@pytest.mark.xfail()來(lái)指定認(rèn)為會(huì)失敗的測(cè)試函數(shù)。預(yù)期失敗,實(shí)際失敗
- XPASS(X)
期望測(cè)試失敗,但實(shí)際結(jié)果卻是運(yùn)行通過(guò),即不符合預(yù)期。預(yù)期失敗,實(shí)際成功
- ERROR(E)
運(yùn)行測(cè)試函數(shù)時(shí),出現(xiàn)異常或錯(cuò)誤,可能由fixture引起
3.3 Pytest命令行參數(shù)
? ? 很多時(shí)候,運(yùn)行單元測(cè)試框架并不需要界面,更多的時(shí)候采用命令行的形式執(zhí)行,pytest也提供很多的命令行參數(shù),獲取命令行參數(shù)幫助如下所示:
pytest --help
usage: pytest [options] [file_or_dir] [file_or_dir] [...]
positional arguments:
file_or_dir
general:
-x, --exitfirst exit instantly on first error or failed test.
? ? 下面來(lái)學(xué)習(xí)一些常用的命令行參數(shù)
3.3.1 --collect-only
? ? 該參數(shù)僅收集測(cè)試函數(shù),但并不執(zhí)行運(yùn)行操作。如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --collect-only
============================= test session starts ================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 3 items
<Module test_01.py>
<Function test_add_01>
<Function test_add_02>
<Module test_02.py>
<Function test_requestBaidu>
3.3.2 -k Expression
? ? -k選項(xiàng)允許使用表達(dá)式來(lái)指定期望運(yùn)行的測(cè)試函數(shù)。常用于篩選要進(jìn)行運(yùn)行的測(cè)試函數(shù)。在以下示例中,僅運(yùn)行當(dāng)前及其子目錄中測(cè)試函數(shù)名含request或temp的測(cè)試函數(shù),源代碼如下所示:
- test_01.py
import pytest
# First of sample function
def Add(x:int,y:int)->int:
return x+y
# First of test function
def test_add_01():
assert Add(2,3)==5
def test_add_02():
assert Add(3,4)==6
def test_request_01():
assert Add(4,3)==7
def test_temp_01():
assert Add(8,3)==11
- test_02.py
import requests
import pytest
url = "http://www.baidu.com"
port = 80
def test_requestBaidu():
testUrl=f"{url}:{port}"
r=requests.get(url=testUrl,timeout=10)
content=r.content.decode("utf8")
print(content)
assert "bai" in content
以下先驗(yàn)證篩選的結(jié)果是否正確:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest -k "request or temp" --collect-only
============================== test session starts =======================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 5 items / 2 deselected / 3 selected
<Module test_01.py>
<Function test_request_01>
<Function test_temp_01>
<Module test_02.py>
<Function test_requestBaidu>
=========================== 2 deselected in 2.36s =================================
實(shí)際運(yùn)行結(jié)果:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest -k "request or temp" -v
======================== test session starts ======================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 5 items / 2 deselected / 3 selected
test_01.py::test_request_01 PASSED [ 33%]
test_01.py::test_temp_01 PASSED [ 66%]
test_02.py::test_requestBaidu PASSED [100%]
====================== 3 passed, 2 deselected in 0.52s ==============================
3.3.3 -m MarkExpr
? ? 該選項(xiàng)常用于標(biāo)記測(cè)試并分組,方便快速運(yùn)行選中的測(cè)試函數(shù),具體的標(biāo)記可以自定義,可以使用裝飾器@pytest.mark。示例如下:
- test_01.py
import pytest
# First of sample function
def Add(x:int,y:int)->int:
return x+y
@pytest.mark.TestMark
# First of test function
def test_add_01():
assert Add(2,3)==5
def test_add_02():
assert Add(3,4)==6
@pytest.mark.RunThisTestFunc
def test_request_01():
assert Add(4,3)==7
def test_temp_01():
assert Add(8,3)==11
- test_01.py
import requests
import pytest
url = "http://www.baidu.com"
port = 80
@pytest.mark.RunThisTestFunc
def test_requestBaidu():
testUrl=f"{url}:{port}"
r=requests.get(url=testUrl,timeout=10)
content=r.content.decode("utf8")
print(content)
assert "bai" in content
運(yùn)行結(jié)果如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest -m "RunThisTestFunc or not TestMark" --collect-only
=========================== test session starts ====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 5 items / 1 deselected / 4 selected
<Module test_01.py>
<Function test_add_02>
<Function test_request_01>
<Function test_temp_01>
<Module test_02.py>
<Function test_requestBaidu>
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest -m "RunThisTestFunc or not TestMark" -v
========================== test session starts =======================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 5 items / 1 deselected / 4 selected
test_01.py::test_add_02 FAILED [ 25%]
test_01.py::test_request_01 PASSED [ 50%]
test_01.py::test_temp_01 PASSED [ 75%]
test_02.py::test_requestBaidu PASSED [100%]
3.3.4 -x, --exitfirst
? ? 正常情況下,pytest會(huì)運(yùn)行每一個(gè)搜索到的測(cè)試函數(shù),如果某個(gè)測(cè)試函數(shù)斷言失敗或觸發(fā)了異常,則該測(cè)試函數(shù)的運(yùn)行就停止了,此時(shí)pytest會(huì)將其標(biāo)記為失敗,然后繼續(xù)運(yùn)行后續(xù)的測(cè)試函數(shù),這也是我們期望的運(yùn)行模式。那如果我們希望在某一個(gè)測(cè)試函數(shù)在運(yùn)行失敗,則中斷不再運(yùn)行后續(xù)的測(cè)試函數(shù),此時(shí)就可以使用-x選項(xiàng)。
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest -x
========================== test session starts =========================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 6 items
test_01.py .F
=============================== FAILURES ==========================================
_____________________________________________________ test_add_02 _____________________________________________________
def test_add_02():
> assert Add(3,4)==6
E assert 7 == 6
E + where 7 = Add(3, 4)
test_01.py:13: AssertionError
==================== 1 failed, 1 passed, 3 warnings in 0.32s =========================
從輸出的信息可以看出,總共有6個(gè)測(cè)試函數(shù),而在運(yùn)行第2個(gè)測(cè)試函數(shù),斷言失敗,則停止整個(gè)運(yùn)行過(guò)程,因此,僅運(yùn)行了2個(gè)測(cè)試函數(shù),一個(gè)測(cè)試通過(guò),一個(gè)測(cè)試失敗。
3.3.5 --maxfail=num
? ? -x選項(xiàng)的特點(diǎn)是一遇到失敗,就會(huì)直接全部停止。而如果想要pytest在失敗n次后再停止,則可通過(guò)選項(xiàng)-maxfail指定允許失敗的次數(shù)。
import pytest
# First of sample function
def Add(x:int,y:int)->int:
return x+y
@pytest.mark.TestMark
# First of test function
def test_add_01():
assert Add(2,3)==5
def test_add_02():
assert Add(3,4)==6
@pytest.mark.RunThisTestFunc
def test_request_01():
assert Add(4,3)==7
def test_temp_01():
assert Add(8,3)==12
運(yùn)行結(jié)果如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --maxfail=2
=============================== test session starts =====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 6 items
test_01.py .F.F
================================= FAILURES ==========================================
_________________________________ test_add_02 __________________________________________
def test_add_02():
> assert Add(3,4)==6
E assert 7 == 6
E + where 7 = Add(3, 4)
test_01.py:13: AssertionError
________________________________ test_temp_01 _________________________________________
def test_temp_01():
> assert Add(8,3)==12
E assert 11 == 12
E + where 11 = Add(8, 3)
test_01.py:20: AssertionError
====================== 2 failed, 2 passed, 3 warnings in 0.35s =========================
如果--maxfail=1,則功能與-x一樣
3.3.6 --lf --last-failed
? ? 當(dāng)一個(gè)或多個(gè)測(cè)試函數(shù)運(yùn)行失敗后,我們常常希望能夠定位到最后一個(gè)運(yùn)行失敗的測(cè)試函數(shù),并且希望能重新運(yùn)行,這時(shí)則可以使用--lf選項(xiàng)
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --lf
============================== test session starts ====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 4 items / 2 deselected / 2 selected
run-last-failure: rerun previous 2 failures (skipped 3 files)
test_01.py FF [100%]
=================================== FAILURES ==========================================
____________________________ test_add_02 ________________________________________
def test_add_02():
> assert Add(3,4)==6
E assert 7 == 6
E + where 7 = Add(3, 4)
test_01.py:13: AssertionError
_____________________________________test_temp_01 _________________________________________
def test_temp_01():
> assert Add(8,3)==12
E assert 11 == 12
E + where 11 = Add(8, 3)
test_01.py:20: AssertionError
==================== 2 failed, 2 deselected, 2 warnings in 0.13s =============================
3.3.7 --ff --failed-first
? ? --ff選項(xiàng)與--lf選項(xiàng)功能基本相同,不同之處如下所示:
--ff 先運(yùn)行上次失敗的測(cè)試函數(shù)再運(yùn)行完剩余的測(cè)試函數(shù)
--lf 僅運(yùn)行上次失敗的測(cè)試函數(shù)
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --ff
=============================== test session starts =======================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 6 items
run-last-failure: rerun previous 2 failures first
test_01.py FF.. [ 66%]
test_02.py . [ 83%]
test_03.py . [100%]
================================= FAILURES ======================================
______________________________________test_add_02 ____________________________________________
def test_add_02():
> assert Add(3,4)==6
E assert 7 == 6
E + where 7 = Add(3, 4)
test_01.py:13: AssertionError
_______________________________________ test_temp_01 _________________________________________
def test_temp_01():
> assert Add(8,3)==12
E assert 11 == 12
E + where 11 = Add(8, 3)
test_01.py:20: AssertionError
======================== 2 failed, 4 passed, 3 warnings in 1.88s ======================
3.3.8 -v --verbose
? ? 使用-v/--verbose,常用于輸出詳細(xì)的運(yùn)行信息。最主要的區(qū)別是每個(gè)文件中的每個(gè)測(cè)試函數(shù)都占用一行(之前是每一個(gè)文件占用一行),測(cè)試的結(jié)果和名字都會(huì)顯示出來(lái),而不再在是一個(gè)點(diǎn)或字符,如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --ff --tb=no -v
======================== test session starts =====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 6 items
run-last-failure: rerun previous 2 failures first
test_01.py::test_add_02 FAILED [ 16%]
test_01.py::test_temp_01 FAILED [ 33%]
test_01.py::test_add_01 PASSED [ 50%]
test_01.py::test_request_01 PASSED [ 66%]
test_02.py::test_requestBaidu PASSED [ 83%]
test_03.py::test_request PASSED [100%]
====================== 2 failed, 4 passed, 3 warnings in 0.93s =============================
如果運(yùn)行是彩色終端,則FAILED為紅色字體,PASS為綠色字體。
3.3.9 -q --quiet
? ? 該選項(xiàng)與-v功能相反,該選項(xiàng)會(huì)輸出簡(jiǎn)化信息,只保留核心信息。如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --ff --tb=line -q
FF.... [100%]
======================================== FAILURES ====================================
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01\test_01.py:13: assert 7 == 6
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01\test_01.py:20: assert 11 == 12
2 failed, 4 passed, 3 warnings in 1.34s
3.3.10 --tb=style
? ? --tb參數(shù)主要決定捕捉到失敗后的輸出信息的顯示方式。其可選值為 auto/long/short/line/native/no,其常用模式解釋如下:
- auto模式:默認(rèn)值,如果有多個(gè)測(cè)試函數(shù)失敗,僅打印第一個(gè)和最后一個(gè)用例的回溯信息
- long模式:輸出的信息最詳細(xì)
- short模式:僅輸出assert的一行及系統(tǒng)判定內(nèi)容,不顯示上下文
- line模式:只使用一行輸出顯示所有的錯(cuò)誤信息
- native模式:只輸出Python標(biāo)準(zhǔn)庫(kù)的回溯信息,不顯示額外信息
- no模式:直接屏蔽全部回溯信息
? ? 以上模式常用模式為:short/line/no
某個(gè)測(cè)試函數(shù)運(yùn)行失敗后,pytest會(huì)列舉出失敗信息,包括失敗出現(xiàn)在哪一行,什么原因?qū)е碌氖。撨^(guò)程稱之為信息回溯
示例如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest -v --tb=line
============================ test session starts ================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 6 items
test_01.py::test_add_01 PASSED [ 16%]
test_01.py::test_add_02 FAILED [ 33%]
test_01.py::test_request_01 PASSED [ 50%]
test_01.py::test_temp_01 FAILED [ 66%]
test_02.py::test_requestBaidu PASSED [ 83%]
test_03.py::test_request PASSED [100%]
==================================== FAILURES ==========================================
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01\test_01.py:13: assert 7 == 6
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01\test_01.py:20: assert 11 == 12
========================= 2 failed, 4 passed, 3 warnings in 2.10s ===========================
3.3.11 --durations=N
? ? --durations=N 該選項(xiàng)不關(guān)注測(cè)試具體的運(yùn)行過(guò)程,只統(tǒng)計(jì)測(cè)試過(guò)程中哪向個(gè)階段最慢,因此使用該選項(xiàng)可以加快測(cè)試分節(jié)奏,顯示運(yùn)行最慢的N個(gè)階段,耗時(shí)越長(zhǎng)越靠前,如果--durations=0,則將所有階段的耗時(shí)從長(zhǎng)到短排序后顯示。示例如下所示:
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01>pytest --durations=3 --tb=line -v
============================test session starts ==========================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01
collected 6 items
test_01.py::test_add_01 PASSED [ 16%]
test_01.py::test_add_02 FAILED [ 33%]
test_01.py::test_request_01 PASSED [ 50%]
test_01.py::test_temp_01 FAILED [ 66%]
test_02.py::test_requestBaidu PASSED [ 83%]
test_03.py::test_request PASSED [100%]
=============================== FAILURES =========================================
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01\test_01.py:13: assert 7 == 6
C:\Users\Surpass\PycharmProjects\PytestStudy\Lesson01\test_01.py:20: assert 11 == 12
=============================== warnings summary ======================================
================================ slowest 3 test durations =================================
0.50s call test_03.py::test_request
0.06s call test_02.py::test_requestBaidu
(0.00 durations hidden. Use -vv to show these durations.)
======================= 2 failed, 4 passed, 3 warnings in 0.93s ===========================
3.3.12 -h --help
? ? 以上僅僅是常用的一些選項(xiàng),更多選項(xiàng)可通過(guò)-h或--help來(lái)進(jìn)行查看,通過(guò)該選項(xiàng)不但能展示原生pytest的用法,還能展示新添加插件的選項(xiàng)和用法。