8.pytest 強大的 fixture (下)
fixtures引數化
fixture函式可以進行引數化的呼叫,這種情況下,相關測試集會被多次呼叫,即依賴該fixture的測試的集合。測試函式通常無需關注這種重複測試 .
fixture的引數化有助於為那些可以以多種方式配置的元件編寫詳盡的功能測試 .
擴充套件之前的示例,我們標記fixture來建立兩個smtp_connection的例項,這會使得所有的測試使用這兩個不同的fixture執行兩次:
# conftest.py
import pytest
import smtplib
@pytest.fixture(scope="module", params=["smtp.qq.com", "mail.163.org"])
def smtp_connection(request):
smtp_connection = smtplib.SMTP(request.param, 587, timeout=5)
yield smtp_connection
print("finalizing %s" % smtp_connection)
smtp_connection.close()
相對於之前的程式碼,這裡主要的改動就是為@pytest.fixture定義了一個params,params是一個可以通過request.params在fixture中進行訪問的列表。無需修改其他的程式碼,讓我們來執行它:
(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 4 items
test_module.py FFFF [100%]
================================== FAILURES ==================================
__________________________________ test_ehlo[smtp.qq.com0] __________________________________
smtp_connection = <smtplib.SMTP object at 0x0000025BBB5D7EF0>
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'newxmesmtplogicsvrszb5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAILCOMPRESS\n8BITMIME'
test_module.py:4: AssertionError
__________________________________ test_noop[smtp.qq.com0] __________________________________
smtp_connection = <smtplib.SMTP object at 0x0000025BBB5D7EF0>
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
__________________________________ test_ehlo[smtp.qq.com1] __________________________________
smtp_connection = <smtplib.SMTP object at 0x0000025BBB5D7EF0>
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'newxmesmtplogicsvrszb5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAILCOMPRESS\n8BITMIME'
test_module.py:4: AssertionError
__________________________________ test_noop[smtp.qq.com1] __________________________________
smtp_connection = <smtplib.SMTP object at 0x0000025BBB5D7EF0>
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
--------------------------------- Captured stdout teardown ---------------------------------
finalizing <smtplib.SMTP object at 0x0000025BBB5D7EF0>
================================== short test summary info ==================================
FAILED test_module.py::test_ehlo[smtp.qq.com0] - AssertionError: assert b'smtp.qq.com' in b'newxmesmtplogicsvrszb5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAU...
FAILED test_module.py::test_noop[smtp.qq.com0] - assert 0
FAILED test_module.py::test_ehlo[smtp.qq.com1] - AssertionError: assert b'smtp.qq.com' in b'newxmesmtplogicsvrszb5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAU...
FAILED test_module.py::test_noop[smtp.qq.com1] - assert 0
================================== 4 failed in 0.31s ==================================
可以看到每個測試函式都是用不同的smtp_connection例項執行了兩次。
在引數化的fixture中使用marks
pytest.param()可以用來用來接收通過marks引數傳入的標誌,就像使用@pytest.mark.parametrize。 如下:
# test_fixture_marks.py
import pytest
@pytest.fixture(params=[0, 1, pytest.param(2, marks=pytest.mark.skip)])
def data_set(request):
return request.param
def test_data(data_set):
pass
執行該測試會跳過data_set中值為2的呼叫:
(pytest) D:\study\auto-pytest>pytest test_fixture_marks.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 3 items
test_fixture_marks.py ..s [100%]
==================================== 2 passed, 1 skipped in 0.14s ====================================
模組化: 通過fixture函式使用fixture
不僅測試函式可以使用fixture,fixture函式本身也可以使用其他的fixture。這可以使得fixture的設計更容易模組化,並可以在多個專案中複用fixture .
擴充套件前面的例子作為一個簡單的範例,我們在一個已經定義的smtp_connection中插入一個例項化的APP物件:
# test_appsetup.py
import pytest
class App(object):
def __init__(self, smtp_connection):
self.smtp_connection = smtp_connection
@pytest.fixture(scope="module")
def app(smtp_connection):
return App(smtp_connection)
def test_smtp_connection_exists(app):
assert app.smtp_connection
這裡我們定義了一個名為app的fixture並且接收之前定義的smtp_connection的fixture,在其中例項化了一個App物件。執行結果如下
(pytest) D:\study\auto-pytest>pytest -v test_appsetup.py
======================================== test session starts ========================================
platform win32 -- Python 3.7.1, pytest-6.0.2, py-1.9.0, pluggy-0.13.1 -- d:\envs\pytest\scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\study\auto-pytest
collected 2 items
test_appsetup.py::test_smtp_connection_exists[smtp.qq.com0] PASSED [ 50%]
test_appsetup.py::test_smtp_connection_exists[smtp.qq.com1] PASSED [100%]
======================================== 2 passed in 0.17s ========================================
因為對smtp_connection做了引數化,測試用例將會使用兩個不同的App例項分別執行來連線各自的smtp伺服器。App fixture無需關心smtp_connection的引數化,pytest會自動的分析其中的依賴關係
注意,app fixture宣告瞭作用域是module,並使用了同樣是module作用域的smtp_connection。 如果smtp_connection是session的作用域,這個示例依然是有效的:fixture可以引用作用域更廣泛的fixture,但是反過來不行,比如session作用域的fixture不能引用一個module作用域的fixture
重寫fixtures
在大型的專案中,為了保持程式碼的可讀性和可維護性,你可能需要重新在本地定義一個fixture來重寫一個global或者root的fixture。
在資料夾(conftest)這一層重寫
測試的檔案結構如下:
tests/
__init__.py
conftest.py
# tests/conftest.py
import pytest
@pytest.fixture
def username():
return 'username'
test_something.py
# test/test_something.py
def test_username(username):
assert username == "username"
subfolder/
__init__.py
conftest.py
# tests/subfolder/conftest.py
import pytest
@pytest.fixture
def username(username):
return 'overridden‐' + username
test_something.py
# tests/subfolder/test_something.py
def test_username(username):
assert username == 'overridden‐username'
如上所示,fixture可以通過使用同樣的函式名來進行重寫。
在module這一層重寫
檔案結構如下:
tests/
__init__.py
conftest.py
# tests/conftest.py
import pytest
@pytest.fixture
def username():
return 'username'
test_something.py
# test/test_something.py
import pytest
@pytest.fixture
def username(username):
return 'overridden‐' + username
def test_username(username):
assert username == "username"
test_something_else.py
# tests/test_something_else.py
import pytest
@pytest.fixture
def username(username):
return 'overridden‐else-' + username
def test_username(username):
assert username == "overridden‐else‐username"
相關文章
- 6.pytest 強大的 fixture (上)
- 7.pytest 強大的 fixture (中)
- Windows下強大的命令終端-CmderWindows
- 強大的AWR-Format工具下載ORM
- Linux系統下強大的ethtool命令Linux
- 七、fixture 的用例管理
- pytest fixture 使用
- pytest 精通 fixture
- pytes中fixture的scope: 決定可以在什麼範圍內共享fixture
- 強大的影片下載工具Downie 4 mac中文Mac
- 強大的CSS:文字下波浪線動畫效果CSS動畫
- Pytest學習(四) - fixture的使用
- 乾貨丨Linux系統下強大的ethtool命令Linux
- 強大的ognl
- pytest(6)-Fixture(韌體)
- Mac強大的視訊下載軟體Downie 4 for MacMac
- Downie 4 for Mac中文啟用版:強大的影片下載工具Mac
- 強大的Github ActionsGithub
- 強大的set容器
- android強大的SpannableStringBuilderAndroidUI
- awk的強大操作
- 強大的 VS Code
- 【pytest】fixture 與 setup, teardown 的優先順序
- pytest:通過scope控制fixture的作用範圍
- .net下功能強大的HTML解析庫HtmlAgilityPack,資料抓取必備HTML
- 加州大學:中國的科技創新強國之路(附下載)
- python @pytest.fixture示例及用法Python
- pytest進階之fixture函式函式
- vim之強大的global
- 強大的 Guava 工具類Guava
- 強大的CAS機制
- Pytest測試框架(三):pytest fixture 用法框架
- 強大的動態 LINQ 庫
- 威力強大的Linux sudo 命令Linux
- GoFrame - 強大的工具鏈集合GoFrame
- 向強大的SVG邁進SVG
- Chrome的強大搜尋功能Chrome
- 簡單又強大的SHELL