Pytest進階使用
fixture
特點:
-
命令靈活:對於setup,teardown可以省略
-
數據共享:在conftest.py配置里寫方法可以實現數據共享,不需要import導入,可以跨文件共享
-
scope的層次及神奇的yield組合相當於各種setup和teardown
-
實現參數化
應用
- 場景:
測試用例執行時,有的用例需要登錄才能執行,有些用例不需要登錄。
setup和teardown無法滿足這種情況,但是fixture可以。默認scope(範圍):function
-
步驟:
-
導入pytest
-
在登錄的函數上添加@pytest.fixture()
-
在要使用的測試方法中傳入(登錄函數名稱)
-
不傳入的就不登錄,直接執行測試方法。
-
fixture作用域
取值 | 範圍 | 說明 |
---|---|---|
function | 函數級 | 每一個函數或方法都會調用 |
class | 類級別 | 每個測試類只執行一次 |
module | 模塊級 | 每個.py文件調用一次 |
package | 包級 | 每個python包只調用一次(暫不支持) |
session | 會話 | 每次會話只需要運行一次,會話內所有方法及類,模塊都共享這個方法 |
- session是在整個項目中只執行一次的代碼
yield關鍵字
- 場景:
你已經可以將測試方法【前要執行的或依賴的】解決了,那測試方法後銷毀清除數據要如何進行?
- 解決:
通過在fixture函數中加入yield關鍵字,yield是調用第一次返回結果,第二次執行它下面的語句返回。
- 步驟:
@pytest.fixture(scope=module)
在登錄的方法中加yield,之後加銷毀清除的步驟
import pytest
@pytest.fixture()
def login():
# setup
token = '1235236fdg'
print("登錄功能")
yield token# 相當於return 返回none
# teardown
print("退出登錄操作")
def test_search():
print("搜索功能")
def test_cart(login):
print(f"token:{login}")
print("購物車")
數據共享
- 場景:
你與其他工程師合作一起開發時,公共的模塊要在不同文件中,要在大家都訪問的到的地方
- 解決:
使用conftest.py這個文件進行數據共享,並且它可以放在不同位置起着不同的範圍共享作用
-
前提:
-
conftest文件名不能換
-
放在項目下是全局的數據共享
-
-
執行:
-
系統執行到參數login時先從本模塊中查找是否有這個名字的變量之類的
-
之後在conftest.py中找是否含有
-
-
步驟:
將登錄模塊帶@pytest.fixture寫在conftest.py
自動應用
- 場景:
不想原測試方法有任何改動,或全部都自動實現自動應用,沒特例,也都不需要返回值時可以選擇自動應用的方法
- 解決:
使用fixture中的參數autouse=True實現
- 步驟:
在方法上面加@pytest.fixture(autouse=Ture)
參數化
- 場景:
測試離不開數據,為了數據靈活,一般數據都是通過參數傳的
- 解決:
使用fixture中的固定參數request傳遞
- 步驟:
在fixture中添加@pytest.fixture(params=[1,2,3,’linda’])
在方法參數寫request,方法體裏面使用request.param接受參數
@pytest.fixture(params=['hogwarts','joker'])
def demo_params(request):
print(f'用戶名為:{request.param}')
return request.param
def test_demo(demo_params):
print(f"數據為:{demo_params}")
- 注意:fixture的參數是params,而調用的時候是request.param,沒有s
總結:
-
模擬setup,teardown(一個用例可以引用多個fixture)
-
yield的用法
-
作用域(session,module,類級別,方法級別)
-
自動執行(autouse參數)
-
conftest.py用法,一般會把fixture寫在conftest.py文件中
-
實現參數化
pytest.ini文件
-
pytest.ini是pytest的配置文件
-
可以修改pytest的默認行為
-
不能使用中文符號,包括漢字,空格 ,引號,冒號等
作用:
-
修改用例的命名規則
-
配置日誌格式,比代碼配置方便很多
-
添加標籤,防止運行過程報警告錯誤
-
指定執行目錄
-
排除搜索目錄
改變pytest運行規則
[pytest]
;執行check_開頭的所有文件
python_files = check_* test_*
;執行所有的以Test和Check開頭的類
python_classes = Test* Check*
;執行所有以test_和check_開頭的方法
python_functions = check_* test_*
- 注意:win系統的pytest.ini文件不能寫中文,注釋也不行
pytest配置-添加默認參數
addopts = -v -s –alluredir=./results
指定/忽略執行目錄
;設置執行得路徑
;testpaths = bilibili baidu
;忽略某些文件夾/目錄
norecursedirs = result logs datas test_demo*
插件開發
-
pytest插件分類
-
外部插件:pip install 安裝的插件
-
本地插件:pytest自動模塊發現機制(conftest.py存放的)
-
內置插件:代碼內部的_pytest目錄加載(hook函數)
-
官網://pypi.org/
常用插件
每一種測試框架收集測試用例的順序是不一樣的
pytest執行順序控制
- 場景:
對於集成測試,經常會有上下文依賴關係的測試用例。如十個步驟,拆分成十個case,這時候能知道到底執行到哪步報錯。
用例默認執行順序:自上而下執行
- 解決:
可以通過setup,teardown和fixture來解決,也可以使用pytest-ordering插件來解決
-
安裝:pip install pytest-ordering
-
用法:@pytest.mark.run(order=2)
-
注意:多個插件裝飾器(>2)的時候,有可能會發生衝突
並行與分佈式並發執行(xdist)
場景1:
- 測試用例1000條,一個用例執行1分鐘,一個測試人員需要1000分鐘,通常我們會用人力成本換取時間成本,加幾個人一起執行,時間就會縮短。這就是一種分佈式場景。
場景2:
- 假設有個報名系統,對報名總數進行統計,數據同時進行修改操作的時候有可能出現問題,需要模擬這個場景,需要多用戶並發請求數據
解決:
-
使用分佈式並發執行測試用例,分佈式插件:pytest-xdist
-
安裝:pip install pytest-xdist
-
注意:用例多的時候效果明顯,多進程並發執行,同時支持allure
hook函數
1. 介紹
-
是個函數,在系統消息觸發時被系統調用
-
自動觸發機制
-
Hook函數的名稱是確定的
-
pytest有非常多的hook函數
-
使用時直接編寫函數體
-
執行是有先後順序的
-
可以在不同階段實現不同的功能
pytest執行過程
執行順序:
-
簡潔版:
pytest編寫插件1-修改默認編碼
pytest_collection_modifyitems收集上來的測試用例實現定製化功能
解決問題:
-
自定義用例的執行順序
-
解決編碼問題(中文的測試用例名稱)
-
自動添加標籤
from typing import List
# 修改編碼的hook函數
def pytest_collection_modifyitems(
session: "Session", config: "Config", items: List["Item"]
) -> None:
# items里的name是測試用例的名字,nodeid是測試用例的路徑
print(items)
for item in items:
# 如果想改變unicode編碼格式的話,需要先encode成utf-8格式的,再decode成unicode-escape就可以了
item.name = item.name.encode('utf-8').decode('unicode-escape')
item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')
編寫插件2-添加命令行參數
# 定義命令行參數的hook函數
def pytest_addoption(parser):
# group 將下面所有的option都展示在這個group組下
mygroup = parser.getgroup('hogwarts')
mygroup.addoption('--env', # 註冊一個命令行選項
default='test', # 參數的默認值
dest='env', # 存儲的變量,為屬性命令,可以使用option對象訪問到這個值
help='set your run env') # 幫助提示,參數的描述信息
@pytest.fixture(scope='session')
def cmd_option(request):
# request獲取命令行的參數,config拿到pytest相關配置,getoption拿到命令行參數
return request.config.getoption('--env')
打包發佈
打包項目構成:
-
源碼包
-
setup.py
-
測試包
from setuptools import setup, find_packages
setup(
name='pytest_encode',
url='',
version='1.0', # 版本
author='joker', # 作者
author_email='', # 郵箱
description='set your encoding and logger', # 描述用法
long_description='Show Chinese for you mark.parametrize().', # 完整描述
classifiers=[ # 分類索引,pip所屬包的分類,方便在pip官網中搜索
'Framework :: Pytest',
'Programming Language :: Python',
'Topic :: Software Development :: Testing',
'Programming Language :: Python :: 3.8',
],
license='proprietary', # 程序授權信息
packages=find_packages(), # 通過導入的方式發現當前項目下所有的包
keywords=[ # 便於pip進行分類
'pytest', 'py.test', 'pytest_encode'
],
# 需要安裝的依賴
install_requires=[
'pytest'
],
# 入口模塊,或者入口函數(最重要的)
entry_points={
'pytest11': [
'pytest_encode = pytest_encode.main'
]
},
zip_safe=False
# 針對win系統,不設置成false會出錯
)
打包命令
依賴包安裝:
-
pip install setuptools python的包管理工具,負責安裝和發佈,尤其是安裝擁有依賴關係的包
-
pip install wheel 生成 *.whl格式的安裝包,本質上也是一個壓縮包
打包命令:(切到setup.py所在的目錄下執行)
python setup.py sdist bdist_wheel
dist目錄下.whl的文件,可以通過pip install 下載
發佈命令
-
python3 -m pip install –user –upgrade twine ## 安裝twine工具
-
python3 -m twine upload –repository testpypi dist/* ## 上傳代碼