1. 程式人生 > >tep0.6.0更新聊聊pytest變數介面用例3個級別複用

tep0.6.0更新聊聊pytest變數介面用例3個級別複用

tep是一款測試工具,在pytest測試框架基礎上集成了第三方包,提供專案腳手架,幫助以寫Python程式碼方式,快速實現自動化專案落地。fixture是pytest核心技術,本文聊聊如何使用fixture完成變數、介面、用例3個級別複用。 # 技術原理 fixture是一種特殊函式,實現了依賴注入,pytest規定,只要在`conftest.py`模組中定義了fixture,作為引數傳給測試函式`test(fixture_name)`就可以使用,無需`import`。tep在`conftest.py`上封裝了一層`fixtures`,類似於Django初始化資料載入的`fixtures`,定義了`env_vars`環境變數,預置了登入介面等。整體思路如下圖所示: - 實線:表示fixture流轉,從`tep.fixture`預置fixture,到`fixtures`,到`conftest.py`,到`tests`。 - 虛線:表示動態變數流轉,參考JMeter `vars.put()`和`vars.get()`,實現用例級別複用。 - 藍色線:表示靜態變數流轉,參考JMeter`自定義使用者變數`,實現變數級別複用。
## tep.fixture `tep.fixture`第一塊內容是預置fixture的實現程式碼,如`url`、`faker_ch`等,對使用者隱藏。第二塊內容是類`TepVar`,預置了1個Python字典`vars_`和2個存取方法`put()`、`get()`,劃分了一塊key-value形式儲存區域。 ## fixtures `fixtures`是一個包,裡面包括多個`fixture_*.py`格式的Python模組,定義的全部都是fixture,只對外提供`fixture`,不提供`function`。 ## 自動註冊 `conftest.py`是pytest的特殊檔案,檔名固定,tep在其中實現了自動註冊功能,它會自動查詢`fixtures`目錄下,所有以`fixture_`開頭,以`.py`結尾的Python模組進行匯入,無需手動新增。註冊後,`tests`才能夠找到`fixtures`中定義的`fixture`,否則報錯`fixture not found`。 ## tests `tests`存放所有測試用例,tep建議每個Python模組中只定義1個`test()`函式,用例分離,獨立執行。 >
參考了`HttpRunner`每個`yaml`檔案1條用例的做法。複雜場景可以定義多個測試`test()`函式或`Test`類,pytest都支援。 # 使用示例 ## 變數級別複用 **函式區域性變數** ```python 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()) ``` 函式內部變數,作用域是整條測試用例,可以在多個介面之間進行復用,比如引數化和關聯:
**全域性環境變數** ```python #!/usr/bin/python # encoding=utf-8 """ 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 ``` 使用: ```python def test(env_vars, env_vars_your_name): print(env_vars.common_var) print(env_vars_your_name.my_var) ``` 全域性環境變數由`fixtures`提供:
核心資料是`env_vars.Clazz`類裡面的`mapping`、`domain`、`mysql_engine`等屬性:
這麼做的目的是為了在PyCharm中敲程式碼,輸入`.`後能自動帶出來,提高編碼效率。 `fixture_admin.py`建議由管理員維護專案級別的公共變數,`fixture_your_name.py`由團隊成員定義自己的環境變數,避免衝突。它們還有一個區別是`fixture_admin.py`的`env_vars`繼承了`tep.fixture.TepVar`,支援`env_vars.put()`和`env_vars.get()`。 > 變數都由`fixture`提供。 ## 介面級別複用 tep預置登入介面`fixture_login.py`已經實現了介面級別複用,其他介面可以參照實現: ```python 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 ``` 使用: ```python from loguru import logger def test_login(login): logger.info(login.token) ``` ## 用例級別複用 `a_test.py`,定義1條測試用例`test_a()`,使用`faker_ch`生成隨機`name`,通過`env_vars.put()`方法寫入`TepVar.vars_`中: ```python 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`後手動呼叫執行,從`TepVar.vars_`中讀取`name`: ```python 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()`函式引數引用的所有fixture,需要在`test()`函式引數中重新申明一遍,比如示例中的`(faker_ch, env_vars)`。 tep是藉助`conftest.py`和`fixture`,用類變數來做的,參考了JMeter BeanShell的`vars`。 > 也可以外接`redis`。 # tep0.6.0更新 tep使用者手冊是根據`0.5.3`版本寫的,現在更新了`0.6.0`版本,一是支援本文提到的3個級別複用,微調了`fixtures`,二是把專案腳手架程式碼儘量封裝到`tep`中,減少後續升級成本。涉及到4個檔案:`conftest.py`、`fixture_admin.py`、`fixture_login.py`、`fixture_your_name.py`。 **更新tep** ```shell pip install tep==0.6.0 ``` - 如果還沒有用過tep,使用這條命令安裝後,執行`tep startproject project_name`就可以建立`0.6.0`版本的專案腳手架,包含了預置程式碼結構和sample測試用例。 - 如果已經安裝了tep,也需要執行這條命令升級`0.6.0`版本。 **老專案升級(可選)** 老專案升級也很簡單,先在專案根目錄執行命令: ```shell tep -U ``` 它會自動替換`conftest.py`,考慮到老專案`fixtures`已經有真實資料了,這裡給出了`version0.6.0`檔案包,命令執行後在專案根目錄生成:
把老專案的真實資料提取出來,手動替換一下就可以了:
# 小結 本文介紹瞭如何使用`pytest`測試框架實現變數、介面、用例3個級別複用,給出了在`tep`中的使用示例,然後提供了安裝升級`tep0.6.0`的方法。這套思路借鑑了`JMeter`和`HttpRunner`的部分設計思想,以及我使用過的介面測試平臺經驗,在pytest上實踐了一下。tep只是測試工具,本質上還是寫pytest,感興趣可以試一下哦。 > 參考資料: > > 原始碼 https://github.com/dongfa