tep0.6.0更新聊聊pytest變數介面用例3個級別複用
阿新 • • 發佈:2021-01-06
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