pytest 是一個(gè)成熟的全功能 Python 測試工具,可以幫助你編寫更好的程序。
該pytest框架使編寫小型可讀測試變得容易,并且可以擴(kuò)展以支持應(yīng)用程序和庫的復(fù)雜功能測試。
pytest需要:Python 3.7+ 或 PyPy3。
1、在命令行中運(yùn)行以下命令:
pip install -U pytest
2、檢查您是否安裝了正確的版本:
$ pytest --version
pytest 7.1.0
創(chuàng)建一個(gè)名為 的新文件?test_sample.py?,其中包含一個(gè)函數(shù)和一個(gè)測試:
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
測試結(jié)果
$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 1 item
test_sample.py F [100%]
================================= FAILURES =================================
_______________________________ test_answer ________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:6: AssertionError
========================= short test summary info ==========================
FAILED test_sample.py::test_answer - assert 4 == 5
============================ 1 failed in 0.12s =============================
[100%] 是指運(yùn)行所有測試用例的整體進(jìn)度。 完成后,pytest 會顯示失敗報(bào)告,因?yàn)?nbsp;func(3) 不返回 5。
pytest將在當(dāng)前目錄及其子目錄中運(yùn)行 ?test_*.py? 或 ?*_test.py? 形式的所有文件。
使用 ?raises ?斷言某些代碼引發(fā)了異常:
# content of test_sysexit.py
import pytest
def f():
raise SystemExit(1)
def test_mytest():
with pytest.raises(SystemExit):
f()
以“安靜”報(bào)告模式執(zhí)行測試功能:
$ pytest -q test_sysexit.py
. [100%]
1 passed in 0.12s
一旦您開發(fā)了多個(gè)測試,您可能希望將它們分組到一個(gè)類中。 pytest 可以很容易地創(chuàng)建一個(gè)包含多個(gè)測試的類:
# content of 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")
pytest 按照其 Python 測試約定發(fā)現(xiàn)所有測試,因此它會找到兩個(gè)以 ?test_ ?為前綴的函數(shù)。 不需要對任何東西進(jìn)行子類化,但請確保在您的類前面加上 ?Test ?,否則該類將被跳過。 我們可以通過傳遞文件名來簡單地運(yùn)行模塊:
$ pytest -q test_class.py
.F [100%]
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass object at 0xdeadbeef0001>
def test_two(self):
x = "hello"
> assert hasattr(x, "check")
E AssertionError: assert False
E + where False = hasattr('hello', 'check')
test_class.py:8: AssertionError
========================= short test summary info ==========================
FAILED test_class.py::TestClass::test_two - AssertionError: assert False
1 failed, 1 passed in 0.12s
第一次測試通過,第二次失敗。 您可以很容易地看到斷言中的中間值,以幫助您了解失敗的原因。
將測試分組在類中可能是有益的,原因如下:
在類中對測試進(jìn)行分組時(shí)需要注意的是,每個(gè)測試都有一個(gè)唯一的類實(shí)例。 讓每個(gè)測試共享相同的類實(shí)例對測試隔離非常不利,并且會促進(jìn)不良的測試實(shí)踐。 例如:
# content of test_class_demo.py
class TestClassDemoInstance:
value = 0
def test_one(self):
self.value = 1
assert self.value == 1
def test_two(self):
assert self.value == 1
$ pytest -k TestClassDemoInstance -q
.F [100%]
================================= FAILURES =================================
______________________ TestClassDemoInstance.test_two ______________________
self = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef0002>
def test_two(self):
> assert self.value == 1
E assert 0 == 1
E + where 0 = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef0002>.value
test_class_demo.py:9: AssertionError
========================= short test summary info ==========================
FAILED test_class_demo.py::TestClassDemoInstance::test_two - assert 0 == 1
1 failed, 1 passed in 0.12s
請注意,在類級別添加的屬性是類屬性,因此它們將在測試之間共享。
pytest提供內(nèi)置?fixture /function?參數(shù)來請求任意資源,比如一個(gè)唯一的臨時(shí)目錄:
# content of test_tmp_path.py
def test_needsfiles(tmp_path):
print(tmp_path)
assert 0
在測試函數(shù)簽名中列出名稱?tmp_path?, pytest將在執(zhí)行測試函數(shù)調(diào)用之前查找并調(diào)用一個(gè)?fixture?工廠來創(chuàng)建資源。在運(yùn)行測試之前,pytest會創(chuàng)建一個(gè)每個(gè)測試調(diào)用唯一的臨時(shí)目錄:
$ pytest -q test_tmp_path.py
F [100%]
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmp_path = PosixPath('PYTEST_TMPDIR/test_needsfiles0')
def test_needsfiles(tmp_path):
print(tmp_path)
> assert 0
E assert 0
test_tmp_path.py:3: AssertionError
--------------------------- Captured stdout call ---------------------------
PYTEST_TMPDIR/test_needsfiles0
========================= short test summary info ==========================
FAILED test_tmp_path.py::test_needsfiles - assert 0
1 failed in 0.12s
通過下面的命令來了解內(nèi)置pytest fixture的類型:
pytest --fixtures # shows builtin and custom fixtures
注意,除非添加了?-v?選項(xiàng),否則該命令會省略帶有?_?前導(dǎo)的fixture。
掃描下方二維碼或打開微信搜一搜“w3cschool編程獅”關(guān)注公眾號回復(fù)關(guān)鍵詞【Python123】或者【Python資料包】免費(fèi)領(lǐng)取 Python 學(xué)習(xí)資料,包含軟件安裝包,電子書、思維導(dǎo)圖等