Tep0.6.0更新聊聊Pytest變量接口用例3個(gè)級(jí)別復(fù)用
本文轉(zhuǎn)載自微信公眾號(hào)「PythonMind」,作者dongfanger。轉(zhuǎn)載本文請(qǐng)聯(lián)系PythonMind公眾號(hào)。
tep是一款測試工具,在pytest測試框架基礎(chǔ)上集成了第三方包,提供項(xiàng)目腳手架,幫助以寫Python代碼方式,快速實(shí)現(xiàn)自動(dòng)化項(xiàng)目落地。fixture是pytest核心技術(shù),本文聊聊如何使用fixture完成變量、接口、用例3個(gè)級(jí)別復(fù)用。
技術(shù)原理
fixture是一種特殊函數(shù),實(shí)現(xiàn)了依賴注入,pytest規(guī)定,只要在conftest.py模塊中定義了fixture,作為參數(shù)傳給測試函數(shù)test(fixture_name)就可以使用,無需import。tep在conftest.py上封裝了一層fixtures,類似于Django初始化數(shù)據(jù)加載的fixtures,定義了env_vars環(huán)境變量,預(yù)置了登錄接口等。整體思路如下圖所示:
- 實(shí)線:表示fixture流轉(zhuǎn),從tep.fixture預(yù)置fixture,到fixtures,到conftest.py,到tests。
- 虛線:表示動(dòng)態(tài)變量流轉(zhuǎn),參考JMeter vars.put()和vars.get(),實(shí)現(xiàn)用例級(jí)別復(fù)用。
- 藍(lán)色線:表示靜態(tài)變量流轉(zhuǎn),參考JMeter自定義用戶變量,實(shí)現(xiàn)變量級(jí)別復(fù)用。
tep.fixture
tep.fixture第一塊內(nèi)容是預(yù)置fixture的實(shí)現(xiàn)代碼,如url、faker_ch等,對(duì)使用者隱藏。第二塊內(nèi)容是類TepVar,預(yù)置了1個(gè)Python字典vars_和2個(gè)存取方法put()、get(),劃分了一塊key-value形式存儲(chǔ)區(qū)域。
fixtures
fixtures是一個(gè)包,里面包括多個(gè)fixture_*.py格式的Python模塊,定義的全部都是fixture,只對(duì)外提供fixture,不提供function。
自動(dòng)注冊(cè)
conftest.py是pytest的特殊文件,文件名固定,tep在其中實(shí)現(xiàn)了自動(dòng)注冊(cè)功能,它會(huì)自動(dòng)查找fixtures目錄下,所有以fixture_開頭,以.py結(jié)尾的Python模塊進(jìn)行導(dǎo)入,無需手動(dòng)添加。注冊(cè)后,tests才能夠找到fixtures中定義的fixture,否則報(bào)錯(cuò)fixture not found。
tests
tests存放所有測試用例,tep建議每個(gè)Python模塊中只定義1個(gè)test()函數(shù),用例分離,獨(dú)立運(yùn)行。
參考了HttpRunner每個(gè)yaml文件1條用例的做法。復(fù)雜場景可以定義多個(gè)測試test()函數(shù)或Test類,pytest都支持。
使用示例
變量級(jí)別復(fù)用
函數(shù)局部變量
- import jmespath
- from loguru import logger
- from tep.client import request
- def test_post(faker_ch, url, login):
- # description
- logger.info("test post")
- # data
- fake = faker_ch
- # request
- response = request(
- "post",
- url=url("/api/users"),
- headers=login.jwt_headers,
- json={
- "name": fake.name()
- }
- )
- # assert
- assert response.status_code < 400
- # extract
- user_id = jmespath.search("id", response.json())
函數(shù)內(nèi)部變量,作用域是整條測試用例,可以在多個(gè)接口之間進(jìn)行復(fù)用,比如參數(shù)化和關(guān)聯(lián):
全局環(huán)境變量
- """ Can only be modified by the administrator. Only fixtures are provided.
- """
- from tep.dao import mysql_engine
- from tep.fixture import *
- @pytest.fixture(scope="session")
- def env_vars(config):
- class Clazz(TepVars):
- env = config["env"]
- """Variables define start"""
- # Environment and variables
- mapping = {
- "qa": {
- "domain": "https://qa.com",
- "mysql_engine": mysql_engine("127.0.0.1", # host
- "2306", # port
- "root", # username
- "123456", # password
- "qa"), # db_name
- },
- "release": {
- "domain": "https://release.com",
- "mysql_engine": mysql_engine("127.0.0.1",
- "2306",
- "root",
- "123456",
- "release"),
- }
- # Add your environment and variables
- }
- # Define properties for auto display
- domain = mapping[env]["domain"]
- mysql_engine = mapping[env]["mysql_engine"]
- """Variables define end"""
- return Clazz()
- @pytest.fixture
- def project_level():
- pass
使用:
- def test(env_vars, env_vars_your_name):
- print(env_vars.common_var)
- print(env_vars_your_name.my_var)
全局環(huán)境變量由fixtures提供:
核心數(shù)據(jù)是env_vars.Clazz類里面的mapping、domain、mysql_engine等屬性:
這么做的目的是為了在PyCharm中敲代碼,輸入.后能自動(dòng)帶出來,提高編碼效率。fixture_admin.py建議由管理員維護(hù)項(xiàng)目級(jí)別的公共變量,fixture_your_name.py由團(tuán)隊(duì)成員定義自己的環(huán)境變量,避免沖突。它們還有一個(gè)區(qū)別是fixture_admin.py的env_vars繼承了tep.fixture.TepVar,支持env_vars.put()和env_vars.get()。
變量都由fixture提供。
接口級(jí)別復(fù)用
tep預(yù)置登錄接口fixture_login.py已經(jīng)實(shí)現(xiàn)了接口級(jí)別復(fù)用,其他接口可以參照實(shí)現(xiàn):
- from tep.client import request
- from tep.fixture import *
- def _jwt_headers(token):
- return {"Content-Type": "application/json", "authorization": f"Bearer {token}"}
- @pytest.fixture(scope="session")
- def login(url):
- # Code your login
- logger.info("Administrator login")
- response = request(
- "post",
- url=url("/api/users/login"),
- headers={"Content-Type": "application/json"},
- json={
- "username": "admin",
- "password": "123456",
- }
- )
- assert response.status_code < 400
- response_token = jmespath.search("token", response.json())
- class Clazz:
- token = response_token
- jwt_headers = _jwt_headers(response_token)
- return Clazz
使用:
- from loguru import logger
- def test_login(login):
- logger.info(login.token)
用例級(jí)別復(fù)用
a_test.py,定義1條測試用例test_a(),使用faker_ch生成隨機(jī)name,通過env_vars.put()方法寫入TepVar.vars_中:
- def test_a(faker_ch, env_vars):
- name = faker_ch.name()
- env_vars.put("name", name)
reuse_a_test.py,定義另外1條測試用例test(),import test_a后手動(dòng)調(diào)用執(zhí)行,從TepVar.vars_中讀取name:
- from tests.sample.case_reuse.a_test import test_a
- def test(faker_ch, env_vars):
- test_a(faker_ch, env_vars)
- print(env_vars.get("name"))
注意test_a()函數(shù)參數(shù)引用的所有fixture,需要在test()函數(shù)參數(shù)中重新申明一遍,比如示例中的(faker_ch, env_vars)。
tep是借助conftest.py和fixture,用類變量來做的,參考了JMeter BeanShell的vars。
也可以外接redis。
tep0.6.0更新
tep用戶手冊(cè)是根據(jù)0.5.3版本寫的,現(xiàn)在更新了0.6.0版本,一是支持本文提到的3個(gè)級(jí)別復(fù)用,微調(diào)了fixtures,二是把項(xiàng)目腳手架代碼盡量封裝到tep中,減少后續(xù)升級(jí)成本。涉及到4個(gè)文件:conftest.py、fixture_admin.py、fixture_login.py、fixture_your_name.py。
更新tep
- pip install tep==0.6.0
- 如果還沒有用過tep,使用這條命令安裝后,執(zhí)行tep startproject project_name就可以創(chuàng)建0.6.0版本的項(xiàng)目腳手架,包含了預(yù)置代碼結(jié)構(gòu)和sample測試用例。
- 如果已經(jīng)安裝了tep,也需要執(zhí)行這條命令升級(jí)0.6.0版本。
老項(xiàng)目升級(jí)(可選)
老項(xiàng)目升級(jí)也很簡單,先在項(xiàng)目根目錄執(zhí)行命令:
- tep -U
它會(huì)自動(dòng)替換conftest.py,考慮到老項(xiàng)目fixtures已經(jīng)有真實(shí)數(shù)據(jù)了,這里給出了version0.6.0文件包,命令執(zhí)行后在項(xiàng)目根目錄生成:
把老項(xiàng)目的真實(shí)數(shù)據(jù)提取出來,手動(dòng)替換一下就可以了:
小結(jié)
本文介紹了如何使用pytest測試框架實(shí)現(xiàn)變量、接口、用例3個(gè)級(jí)別復(fù)用,給出了在tep中的使用示例,然后提供了安裝升級(jí)tep0.6.0的方法。這套思路借鑒了JMeter和HttpRunner的部分設(shè)計(jì)思想,以及我使用過的接口測試平臺(tái)經(jīng)驗(yàn),在pytest上實(shí)踐了一下。tep只是測試工具,本質(zhì)上還是寫pytest,感興趣可以試一下哦。
參考資料:源碼 https://github.com/dongfanger/tep