tep0.9.5更新了以下內容:
- 自定義request請求日誌
- Allure報告新增request描述
- 猴子補丁擴充套件request
- fixtures支援多層級目錄
- FastAPI替代Flask
升級tep到0.9.5版本,使用tep startproject demo
建立專案腳手架,開箱即用以上新功能。
1.自定義request請求日誌
tep預設的request請求日誌如下所示:
2022-01-22 20:00:26.335 | INFO | tep.client:tep_request_monkey_patch:44 - method:"post" url:"http://127.0.0.1:5000/login" headers:{"Content-Type": "application/json"} json:{"username": "dongfanger", "password": "123456"} status:200 response:{"token":"de2e3ffu29"} elapsed:0.000s
全部都在一行,假如想換行顯示,那麼可以在utils/http_client.py
檔案中修改request_monkey_patch程式碼:
在測試程式碼中把from tep.client import request
改成from utils.http_client import request
:
日誌就會變成換行顯示了:
2022-01-22 20:04:05.379 | INFO | utils.http_client:request_monkey_patch:38 -
method:"post"
headers:{"Content-Type": "application/json"}
json:{"username": "dongfanger", "password": "123456"}
status:200
response:{"token":"de2e3ffu29"}
elapsed:0.000s
2.Allure報告新增request描述
tep的Allure報告預設會有個request & response
:
可以給request新增desc引數,在Allure測試報告中新增描述:
執行以下命令,然後開啟Allure測試報告:
pytest -s test_request_monkey_patch.py --tep-reports
3.猴子補丁擴充套件request
前面的“自定義request請求日誌”和“Allure報告新增request描述”已經展示瞭如何通過猴子補丁擴充套件日誌和擴充套件報告,您還可以為request擴充套件更多想要的功能,只需要實現utils/http_client.py
裡面的request_monkey_patch函式即可:
#!/usr/bin/python
# encoding=utf-8
import decimal
import json
import time
import allure
from loguru import logger
from tep import client
from tep.client import TepResponse
def request_monkey_patch(req, *args, **kwargs):
start = time.process_time()
desc = ""
if "desc" in kwargs:
desc = kwargs.get("desc")
kwargs.pop("desc")
response = req(*args, **kwargs)
end = time.process_time()
elapsed = str(decimal.Decimal("%.3f" % float(end - start))) + "s"
log4a = "{}\n{}status:{}\nresponse:{}\nelapsed:{}"
try:
kv = ""
for k, v in kwargs.items():
# if not json, str()
try:
v = json.dumps(v, ensure_ascii=False)
except TypeError:
v = str(v)
kv += f"{k}:{v}\n"
if args:
method = f'\nmethod:"{args[0]}" '
else:
method = ""
request_response = log4a.format(method, kv, response.status_code, response.text, elapsed)
logger.info(request_response)
allure.attach(request_response, f'{desc} request & response', allure.attachment_type.TEXT)
except AttributeError:
logger.error("request failed")
except TypeError:
logger.warning(log4a)
return TepResponse(response)
def request(method, url, **kwargs):
client.tep_request_monkey_patch = request_monkey_patch
return client.request(method, url, **kwargs)
4.fixtures支援多層級目錄
tep之前一直只能支援fixtures的根目錄的fixture_*.py
檔案自動匯入,現在能支援多層級目錄了:
測試程式碼test_multi_fixture.py
:
#!/usr/bin/python
# encoding=utf-8
def test(fixture_second, fixture_three):
pass
能執行成功。自動匯入多層目錄的程式碼實現如下:
# 自動匯入fixtures
_fixtures_dir = os.path.join(_project_dir, "fixtures")
for root, _, files in os.walk(_fixtures_dir):
for file in files:
if file.startswith("fixture_") and file.endswith(".py"):
full_path = os.path.join(root, file)
import_path = full_path.replace(_fixtures_dir, "").replace("\\", ".").replace("/", ".").replace(".py", "")
try:
fixture_path = "fixtures" + import_path
exec(f"from {fixture_path} import *")
except:
fixture_path = ".fixtures" + import_path
exec(f"from {fixture_path} import *")
5.FastAPI替代Flask
因為HttpRunner用的FastAPI,所以我也把Flask替換成了FastAPI,在utils/fastapi_mock.py
檔案中可以找到程式碼實現的簡易Mock:
#!/usr/bin/python
# encoding=utf-8
import uvicorn
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/login")
async def login(req: Request):
body = await req.json()
if body["username"] == "dongfanger" and body["password"] == "123456":
return {"token": "de2e3ffu29"}
return ""
@app.get("/searchSku")
def search_sku(req: Request):
if req.headers.get("token") == "de2e3ffu29" and req.query_params.get("skuName") == "電子書":
return {"skuId": "222", "price": "2.3"}
return ""
@app.post("/addCart")
async def add_cart(req: Request):
body = await req.json()
if req.headers.get("token") == "de2e3ffu29" and body["skuId"] == "222":
return {"skuId": "222", "price": "2.3", "skuNum": "3", "totalPrice": "6.9"}
return ""
@app.post("/order")
async def order(req: Request):
body = await req.json()
if req.headers.get("token") == "de2e3ffu29" and body["skuId"] == "222":
return {"orderId": "333"}
return ""
@app.post("/pay")
async def pay(req: Request):
body = await req.json()
if req.headers.get("token") == "de2e3ffu29" and body["orderId"] == "333":
return {"success": "true"}
return ""
if __name__ == '__main__':
uvicorn.run("fastapi_mock:app", host="127.0.0.1", port=5000)
最後,感謝@zhangwk02提交的Pull requests,雖然寫的程式碼被我全部優化了,但是提供了很棒的想法和動力。