日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python开源考试_可能是 Python 中最火的第三方开源测试框架 pytest

發(fā)布時(shí)間:2023/12/20 python 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python开源考试_可能是 Python 中最火的第三方开源测试框架 pytest 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作者:HelloGitHub-Prodesire

一、介紹

本篇文章是《聊聊 Python 的單元測(cè)試框架》的第三篇,前兩篇分別介紹了標(biāo)準(zhǔn)庫(kù) unittest 和第三方單元測(cè)試框架 nose。作為本系列的最后一篇,壓軸出場(chǎng)的是Python 世界中最火的第三方單元測(cè)試框架:pytest。

它有如下主要特性:

assert 斷言失敗時(shí)輸出詳細(xì)信息(再也不用去記憶 self.assert* 名稱了)

自動(dòng)發(fā)現(xiàn) 測(cè)試模塊和函數(shù)

模塊化夾具 用以管理各類測(cè)試資源

對(duì) unittest 完全兼容,對(duì) nose 基本兼容

非常豐富的插件體系,有超過 315 款第三方插件,社區(qū)繁榮

和前面介紹 unittest 和 nose 一樣,我們將從如下幾個(gè)方面介紹 pytest 的特性。

二、用例編寫

同 nose 一樣,pytest 支持函數(shù)、測(cè)試類形式的測(cè)試用例。最大的不同點(diǎn)是,你可以盡情地使用 assert 語句進(jìn)行斷言,絲毫不用擔(dān)心它會(huì)在 nose 或 unittest 中產(chǎn)生的缺失詳細(xì)上下文信息的問題。

比如下面的測(cè)試示例中,故意使得 test_upper 中斷言不通過:

import pytest

def test_upper():

assert 'foo'.upper() == 'FOO1'

class TestClass:

def test_one(self):

x = "this"

assert "h" in x

def test_two(self):

x = "hello"

with pytest.raises(TypeError):

x + []

而當(dāng)使用 pytest 去執(zhí)行用例時(shí),它會(huì)輸出詳細(xì)的(且是多種顏色)上下文信息:

=================================== test session starts ===================================

platform darwin -- Python 3.7.1, pytest-4.0.1, py-1.7.0, pluggy-0.8.0

rootdir: /Users/prodesire/projects/tests, inifile:

plugins: cov-2.6.0

collected 3 items

test.py F.. [100%]

======================================== FAILURES =========================================

_______________________________________ test_upper ________________________________________

def test_upper():

> assert 'foo'.upper() == 'FOO1'

E AssertionError: assert 'FOO' == 'FOO1'

E - FOO

E + FOO1

E ? +

test.py:4: AssertionError

=========================== 1 failed, 2 passed in 0.08 seconds ============================

不難看到,pytest 既輸出了測(cè)試代碼上下文,也輸出了被測(cè)變量值的信息。相比于 nose 和 unittest,pytest 允許用戶使用更簡(jiǎn)單的方式編寫測(cè)試用例,又能得到一個(gè)更豐富和友好的測(cè)試結(jié)果。

三、用例發(fā)現(xiàn)和執(zhí)行

unittest 和 nose 所支持的用例發(fā)現(xiàn)和執(zhí)行能力,pytest 均支持。

pytest 支持用例自動(dòng)(遞歸)發(fā)現(xiàn):

默認(rèn)發(fā)現(xiàn)當(dāng)前目錄下所有符合 test_*.py 或 *_test.py 的測(cè)試用例文件中,以 test 開頭的測(cè)試函數(shù)或以 Test 開頭的測(cè)試類中的以 test 開頭的測(cè)試方法

使用 pytest 命令

同 nose2 的理念一樣,通過在配置文件中指定特定參數(shù),可配置用例文件、類和函數(shù)的名稱模式(模糊匹配)

pytest 也支持執(zhí)行指定用例:

指定測(cè)試文件路徑

pytest /path/to/test/file.py

指定測(cè)試類

pytest /path/to/test/file.py:TestCase

指定測(cè)試方法

pytest another.test::TestClass::test_method

指定測(cè)試函數(shù)

pytest /path/to/test/file.py:test_function

四、測(cè)試夾具(Fixtures)

pytest 的測(cè)試夾具和 unittest、nose、nose2的風(fēng)格迥異,它不但能實(shí)現(xiàn) setUp 和 tearDown這種測(cè)試前置和清理邏輯,還其他非常多強(qiáng)大的功能。

4.1 聲明和使用

pytest 中的測(cè)試夾具更像是測(cè)試資源,你只需定義一個(gè)夾具,然后就可以在用例中直接使用它。得益于 pytest 的依賴注入機(jī)制,你無需通過from xx import xx的形式顯示導(dǎo)入,只需要在測(cè)試函數(shù)的參數(shù)中指定同名參數(shù)即可,比如:

import pytest

@pytest.fixture

def smtp_connection():

import smtplib

return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

def test_ehlo(smtp_connection):

response, msg = smtp_connection.ehlo()

assert response == 250

上述示例中定義了一個(gè)測(cè)試夾具 smtp_connection,在測(cè)試函數(shù) test_ehlo 簽名中定義了同名參數(shù),則 pytest 框架會(huì)自動(dòng)注入該變量。

4.2 共享

在 pytest 中,同一個(gè)測(cè)試夾具可被多個(gè)測(cè)試文件中的多個(gè)測(cè)試用例共享。只需在包(Package)中定義 conftest.py 文件,并把測(cè)試夾具的定義寫在該文件中,則該包內(nèi)所有模塊(Module)的所有測(cè)試用例均可使用 conftest.py 中所定義的測(cè)試夾具。

比如,如果在如下文件結(jié)構(gòu)的 test_1/conftest.py 定義了測(cè)試夾具,那么 test_a.py 和 test_b.py 可以使用該測(cè)試夾具;而 test_c.py 則無法使用。

`-- test_1

| |-- conftest.py

| `-- test_a.py

| `-- test_b.py

`-- test_2

`-- test_c.py

4.3 生效級(jí)別

unittest 和 nose 均支持測(cè)試前置和清理的生效級(jí)別:測(cè)試方法、測(cè)試類和測(cè)試模塊。

pytest 的測(cè)試夾具同樣支持各類生效級(jí)別,且更加豐富。通過在 pytest.fixture 中指定 scope 參數(shù)來設(shè)置:

function —— 函數(shù)級(jí),即調(diào)用每個(gè)測(cè)試函數(shù)前,均會(huì)重新生成 fixture

class —— 類級(jí),調(diào)用每個(gè)測(cè)試類前,均會(huì)重新生成 fixture

module —— 模塊級(jí),載入每個(gè)測(cè)試模塊前,均會(huì)重新生成 fixture

package —— 包級(jí),載入每個(gè)包前,均會(huì)重新生成 fixture

session —— 會(huì)話級(jí),運(yùn)行所有用例前,只生成一次 fixture

當(dāng)我們指定生效級(jí)別為模塊級(jí)時(shí),示例如下:

import pytest

import smtplib

@pytest.fixture(scope="module")

def smtp_connection():

return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

4.4 測(cè)試前置和清理

pytest 的測(cè)試夾具也能夠?qū)崿F(xiàn)測(cè)試前置和清理,通過 yield 語句來拆分這兩個(gè)邏輯,寫法變得很簡(jiǎn)單,如:

import smtplib

import pytest

@pytest.fixture(scope="module")

def smtp_connection():

smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

yield smtp_connection # provide the fixture value

print("teardown smtp")

smtp_connection.close()

在上述示例中,yield smtp_connection 及前面的語句相當(dāng)于測(cè)試前置,通過 yield 返回準(zhǔn)備好的測(cè)試資源 smtp_connection;

而后面的語句則會(huì)在用例執(zhí)行結(jié)束(確切的說是測(cè)試夾具的生效級(jí)別的聲明周期結(jié)束時(shí))后執(zhí)行,相當(dāng)于測(cè)試清理。

如果生成測(cè)試資源(如示例中的 smtp_connection)的過程支持 with 語句,那么還可以寫成更加簡(jiǎn)單的形式:

@pytest.fixture(scope="module")

def smtp_connection():

with smtplib.SMTP("smtp.gmail.com", 587, timeout=5) as smtp_connection:

yield smtp_connection # provide the fixture value

五、跳過測(cè)試和預(yù)計(jì)失敗

pytest 除了支持 unittest 和 nosetest 的跳過測(cè)試和預(yù)計(jì)失敗的方式外,還在 pytest.mark 中提供對(duì)應(yīng)方法:

通過 skipif按條件跳過測(cè)試

通過 xfail 預(yù)計(jì)測(cè)試失敗

示例如下:

@pytest.mark.skip(reason="no way of currently testing this")

def test_mark_skip():

...

def test_skip():

if not valid_config():

pytest.skip("unsupported configuration")

@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")

def test_mark_skip_if():

...

@pytest.mark.xfail

def test_mark_xfail():

...

六、子測(cè)試/參數(shù)化測(cè)試

pytest 除了支持 unittest 中的 TestCase.subTest,還支持一種更為靈活的子測(cè)試編寫方式,也就是 參數(shù)化測(cè)試,通過 pytest.mark.parametrize 裝飾器實(shí)現(xiàn)。

在下面的示例中,定義一個(gè) test_eval 測(cè)試函數(shù),通過 pytest.mark.parametrize 裝飾器指定 3 組參數(shù),則將生成 3 個(gè)子測(cè)試:

@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])

def test_eval(test_input, expected):

assert eval(test_input) == expected

示例中故意讓最后一組參數(shù)導(dǎo)致失敗,運(yùn)行用例可以看到豐富的測(cè)試結(jié)果輸出:

========================================= test session starts =========================================

platform darwin -- Python 3.7.1, pytest-4.0.1, py-1.7.0, pluggy-0.8.0

rootdir: /Users/prodesire/projects/tests, inifile:

plugins: cov-2.6.0

collected 3 items

test.py ..F [100%]

============================================== FAILURES ===============================================

__________________________________________ test_eval[6*9-42] __________________________________________

test_input = '6*9', expected = 42

@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])

def test_eval(test_input, expected):

> assert eval(test_input) == expected

E AssertionError: assert 54 == 42

E + where 54 = eval('6*9')

test.py:6: AssertionError

================================= 1 failed, 2 passed in 0.09 seconds ==================================

若將參數(shù)換成 pytest.param,我們還可以有更高階的玩法,比如知道最后一組參數(shù)是失敗的,所以將它標(biāo)記為 xfail:

@pytest.mark.parametrize(

"test_input,expected",

[("3+5", 8), ("2+4", 6), pytest.param("6*9", 42, marks=pytest.mark.xfail)],

)

def test_eval(test_input, expected):

assert eval(test_input) == expected

如果測(cè)試函數(shù)的多個(gè)參數(shù)的值希望互相排列組合,我們可以這么寫:

@pytest.mark.parametrize("x", [0, 1])

@pytest.mark.parametrize("y", [2, 3])

def test_foo(x, y):

pass

上述示例中會(huì)分別把 x=0/y=2、x=1/y=2、x=0/y=3和x=1/y=3帶入測(cè)試函數(shù),視作四個(gè)測(cè)試用例來執(zhí)行。

七、測(cè)試結(jié)果輸出

pytest 的測(cè)試結(jié)果輸出相比于 unittest 和 nose 來說更為豐富,其優(yōu)勢(shì)在于:

高亮輸出,通過或不通過會(huì)用不同的顏色進(jìn)行區(qū)分

更豐富的上下文信息,自動(dòng)輸出代碼上下文和變量信息

測(cè)試進(jìn)度展示

測(cè)試結(jié)果輸出布局更加友好易讀

八、插件體系

pytest 的插件十分豐富,而且即插即用,作為使用者不需要編寫額外代碼。關(guān)于插件的使用,參見"Installing and Using plugins"。

此外,得益于 pytest 良好的架構(gòu)設(shè)計(jì)和鉤子機(jī)制,其插件編寫也變得容易上手。關(guān)于插件的編寫,參見"Writing plugins"。

九、總結(jié)

三篇關(guān)于 Python 測(cè)試框架的介紹到這里就要收尾了。寫了這么多,各位看官怕也是看得累了。我們不妨羅列一個(gè)橫向?qū)Ρ缺?#xff0c;來總結(jié)下這些單元測(cè)試框架的異同:

unittest

nose

nose2

pytest

自動(dòng)發(fā)現(xiàn)用例

?

?

?

?

指定(各級(jí)別)用例執(zhí)行

?

?

?

?

支持 assert 斷言

強(qiáng)

測(cè)試夾具

?

?

?

?

測(cè)試夾具種類

前置和清理

前置和清理

前置和清理

前置、清理、內(nèi)置各類 fixtures,自定義各類 fixtures

測(cè)試夾具生效級(jí)別

方法、類、模塊

方法、類、模塊

方法、類、模塊

方法、類、模塊、包、會(huì)話

支持跳過測(cè)試和預(yù)計(jì)失敗

?

?

?

?

子測(cè)試

?

?

?

?

測(cè)試結(jié)果輸出

一般

較好

較好

插件

-

較豐富

一般

豐富

鉤子

-

-

?

?

社區(qū)生態(tài)

作為標(biāo)準(zhǔn)庫(kù),由官方維護(hù)

停止維護(hù)

維護(hù)中,活躍度低

維護(hù)中,活躍度高

Python 的單元測(cè)試框架看似種類繁多,實(shí)則是一代代的進(jìn)化,有跡可循。抓住其特點(diǎn),結(jié)合使用場(chǎng)景,就能容易的做出選擇。

若你不想安裝或不允許第三方庫(kù),那么 unittest 是最好也是唯一的選擇。反之,pytest 無疑是最佳選擇,眾多 Python 開源項(xiàng)目(如大名鼎鼎的 requests)都是使用 pytest 作為單元測(cè)試框架。甚至,連 nose2 在官方文檔上都建議大家使用 pytest,這得是多大的敬佩呀!

『講解開源項(xiàng)目系列』——讓對(duì)開源項(xiàng)目感興趣的人不再畏懼、讓開源項(xiàng)目的發(fā)起者不再孤單。跟著我們的文章,你會(huì)發(fā)現(xiàn)編程的樂趣、使用和發(fā)現(xiàn)參與開源項(xiàng)目如此簡(jiǎn)單。歡迎留言聯(lián)系我們、加入我們,讓更多人愛上開源、貢獻(xiàn)開源~

總結(jié)

以上是生活随笔為你收集整理的python开源考试_可能是 Python 中最火的第三方开源测试框架 pytest的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。