手冊簡介

pytest 是一個(gè)成熟的全功能 Python 測試工具,可以幫助你編寫更好的程序。

手冊說明

該pytest框架使編寫小型可讀測試變得容易,并且可以擴(kuò)展以支持應(yīng)用程序和庫的復(fù)雜功能測試。

pytest 開始使用

pytest需要你已掌握Python,如果還沒有點(diǎn)擊這里學(xué)習(xí)Python

安裝pytest

pytest需要:Python 3.7+ 或 PyPy3。

1、在命令行中運(yùn)行以下命令:

pip install -U pytest

2、檢查您是否安裝了正確的版本:

$ pytest --version
pytest 7.1.0

創(chuàng)建你的第一個(gè)測試

創(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。

運(yùn)行多個(gè)測試

pytest將在當(dāng)前目錄及其子目錄中運(yùn)行 ?test_*.py? 或 ?*_test.py? 形式的所有文件。

斷言引發(fā)了某個(gè)異常

使用 ?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

將多個(gè)測試分組到一個(gè)類中

一旦您開發(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

第一次測試通過,第二次失敗。 您可以很容易地看到斷言中的中間值,以幫助您了解失敗的原因。

將測試分組在類中可能是有益的,原因如下:

  • 測試配置
  • 僅在該特定類中共享用于測試的固定裝置
  • 在類級別應(yīng)用標(biāo)記,并將它們隱式應(yīng)用于所有測試

在類中對測試進(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

請注意,在類級別添加的屬性是類屬性,因此它們將在測試之間共享。

為功能測試請求一個(gè)唯一的臨時(shí)目錄

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。

領(lǐng)取免費(fèi)資料

掃描下方二維碼或打開微信搜一搜“w3cschool編程獅”關(guān)注公眾號回復(fù)關(guān)鍵詞【Python123】或者【Python資料包】免費(fèi)領(lǐng)取 Python 學(xué)習(xí)資料,包含軟件安裝包,電子書、思維導(dǎo)圖等

w3cschool編程獅微信公眾號


在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號