7.pytest 強大的 fixture (中)
scope:在類/模組/整個測試中共享fixture例項
當fixture需要訪問網路時,因為依賴於網路狀況,通常是一個非常耗時的動作 。
擴充套件下上面的示例,我們可以將scope="module"引數新增到@pytest.fixture中,這樣每個測試模組就只會呼叫一次smtp_connection的fixture函式(預設情況下時每個測試函式都呼叫一次)。因此,一個測試模組中的多個測試函式將使用同樣的smtp_connection例項,從而節省了反覆建立的時間。
scope可能的值為:function, class, module, package 和 session
下面的示例將fixture函式放在獨立的conftest.py中,這樣可以在多個測試模組中訪問使用該測試fixture:
# conftest.py
import pytest
import smtplib
@pytest.fixture(scope="module")
def smtp_connection():
return smtplib.SMTP("smtp.qq.com", 587, timeout=5)
fixture的名稱依然為smtp_connection,你可以在任意的測試用例中通過該名稱來呼叫該fixture(在conftest.py所在的目錄及子目錄下)
# test_module.py
def test_ehlo(smtp_connection):
response, msg = smtp_connection.ehlo()
assert response == 250 assert b"smtp.qq.com" in msg
assert 0 # for debug
def test_noop(smtp_connection):
response, msg = smtp_connection.noop()
assert response == 250 assert 0 # for debug
我們故意新增了assert 0的斷言來檢視測試用例的執行情況:
(pytest) D:\study\auto-pytest>pytest test_module.py
======================= test session starts =======================
platform win32 -- Python 3.7.1, pytest-6.0.2, py-1.9.0, pluggy-0.13.1
rootdir: D:\study\auto-pytest
collected 2 items
test_module.py FF [100%]
======================= FAILURES =======================
_______________________ test_ehlo _______________________
smtp_connection = <smtplib.SMTP object at 0x000001BDA449BB70>
def test_ehlo(smtp_connection):
response, msg = smtp_connection.ehlo()
assert response == 250
> assert b"smtp.qq.com" in msg
E AssertionError: assert b'smtp.qq.com' in b'newxmesmtplogicsvrsza5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAILCOMPRESS\n8BITMIME'
test_module.py:4: AssertionError
_______________________ test_noop _______________________
smtp_connection = <smtplib.SMTP object at 0x000001BDA449BB70>
def test_noop(smtp_connection):
response, msg = smtp_connection.noop()
assert response == 250
> assert 0 # for debug
E assert 0
test_module.py:11: AssertionError
======================= short test summary info =======================
FAILED test_module.py::test_ehlo - AssertionError: assert b'smtp.qq.com' in b'newxmesmtplogicsvrsza5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAIL...
FAILED test_module.py::test_noop - assert 0
======================= 2 failed in 0.32s =======================
可以看到這兩個用例都失敗了,並且你可以在traceback中看到smtp_connection被傳進了這兩個測試函式中。這兩個函式複用了同一個smtp_connection例項如果你需要一個session作用域的smtp_connection例項,你可以按照如下來定義:
@pytest.fixture(scope="session")
def smtp_connection():
#該韌體會在所有的用例中共享
scope定義為class的話會建立一個在每個class中呼叫一次的fixture
注意: Pytest對於每個fixture只會快取一個例項,這意味著如果使用引數化的fixture,pytest可能會比定義的作用域更多次的呼叫fixture函式(因為需要建立不同引數的fixture)
scope越大,例項化越早
當函式呼叫多個fixtures的時候,scope較大的(比如session)例項化早於scope較小的(比如function或者class)。同樣scope的順序則按照其在測試函式中定義的順序及依賴關係來例項化。
@pytest.fixture(scope="session")
def s1():
pass
@pytest.fixture(scope="module")
def m1():
pass
@pytest.fixture
def f1(tmpdir):
pass
@pytest.fixture
def f2():
pass
def test_foo(f1, m1, f2, s1):
...
該函式所請求的fixtures的例項化順序如下:
s1: 具有最大的scope(session)
m1: 第二高的scope(module)
tmpdir: f1需要使用該fixture,需要在f1之前例項化
f1:在function級的scope的fixtures中,在test_foo中處於第一個
f2:在function級的scope的fixtures中,在test_foo中處於最後一個
fixture的呼叫結束/執行清理程式碼
pytest支援在fixture退出作用域的時候執行相關的清理/結束程式碼。使用yield而不是return關鍵字的時候,yield後面的語句將會在fixture退出作用域的時候被呼叫來清理測試用例
# conftest.py
import smtplib
import pytest
@pytest.fixture(scope="module")
def smtp_connection():
smtp_connection = smtplib.SMTP("smtp.qq.com", 587, timeout=5)
yield smtp_connection
print("teardown smtp")
smtp_connection.close()
無論測試是否發生了異常,print及smtp.close()語句將在module的最後一個測試函式完成之後被執行
$ pytest ‐s ‐q ‐‐tb=no
FFteardown smtp
2 failed in 0.12 seconds
可以看到在兩個測試函式完成後smtp_connection例項呼叫了相關的程式碼。注意如果我們定義scope為function級別(scope=‘function’),該部分程式碼會在每個測試函式結束後都會呼叫。測試函式本身並不需要關心fixture的實現的細節。
我們也可以在with語句中使用yield:
@pytest.fixture(scope="module")
def smtp_connection():
with smtplib.SMTP("smtp.qq.com", 587, timeout=5) as smtp_connection:
yield smtp_connection
相關文章
- 6.pytest 強大的 fixture (上)
- 8.pytest 強大的 fixture (下)
- pytes中fixture的scope: 決定可以在什麼範圍內共享fixture
- [譯] Swift 中強大的模式匹配Swift模式
- 七、fixture 的用例管理
- pytest fixture 使用
- pytest 精通 fixture
- Pytest學習(四) - fixture的使用
- Golang中的強大Web框架Fiber詳解GolangWeb框架
- Laravel 中強大的tap你用過麼Laravel
- 強大的ognl
- pytest(6)-Fixture(韌體)
- [譯]發現 JavaScript 中閉包的強大威力JavaScript
- 『德不孤』Pytest框架 — 12、Pytest中Fixture裝飾器(二)框架
- 『德不孤』Pytest框架 — 13、Pytest中Fixture裝飾器(三)框架
- 『德不孤』Pytest框架 — 11、Pytest中Fixture裝飾器(一)框架
- 強大的Github ActionsGithub
- 強大的set容器
- android強大的SpannableStringBuilderAndroidUI
- awk的強大操作
- 強大的 VS Code
- 【pytest】fixture 與 setup, teardown 的優先順序
- pytest:通過scope控制fixture的作用範圍
- python @pytest.fixture示例及用法Python
- pytest進階之fixture函式函式
- vim之強大的global
- 強大的 Guava 工具類Guava
- 強大的CAS機制
- 2022中國大資料企業50強大資料
- 請教一個 pytest 中 fixture 相關問題:將 fixture 中寫入 allure 附件的程式碼提出來定義成自定義方法後,就無法按預期寫入 allure 附件了
- 這次,我掌握了 pytest 中 fixture 的使用及 pytest 執行測試的載入順序
- Pytest測試框架(三):pytest fixture 用法框架
- 強大的動態 LINQ 庫
- 威力強大的Linux sudo 命令Linux
- GoFrame - 強大的工具鏈集合GoFrame
- 向強大的SVG邁進SVG
- Chrome的強大搜尋功能Chrome
- 簡單又強大的SHELL