Python + Pytest接口自動化測試方案的實現(xiàn)
前言
Postman 僅適合單接口調(diào)試,面對批量回歸、多環(huán)境驗證和持續(xù)集成場景,手工操作效率極低且易出錯。本文帶你從零搭建一套企業(yè)級可落地的 Python + Pytest 接口自動化測試框架,覆蓋接口封裝、數(shù)據(jù)驅(qū)動、報告可視化、CI/CD 集成全流程,可直接用于小型項目,也可平滑擴展至大型分布式系統(tǒng)。
技術(shù)選型與優(yōu)勢對比
我們選擇以下技術(shù)棧,兼顧易用性、擴展性和生態(tài)成熟度:
| 技術(shù)工具 | 核心作用 | 選型優(yōu)勢 |
|---|---|---|
| Python 3.8+ | 腳本開發(fā)語言 | 語法簡潔、第三方庫豐富、測試領(lǐng)域生態(tài)完善 |
| Requests | HTTP 請求發(fā)送 | 最流行的 HTTP 客戶端,API 簡單易用 |
| Pytest | 測試用例管理與執(zhí)行 | 比 unittest 更靈活,支持參數(shù)化、fixture、插件擴展 |
| Allure | 測試報告生成 | 可視化效果好,支持用例分類、失敗截圖、歷史趨勢 |
| YAML | 測試數(shù)據(jù)與配置管理 | 可讀性強,適合存儲結(jié)構(gòu)化數(shù)據(jù) |
| Jenkins | 持續(xù)集成 | 開源免費,支持定時構(gòu)建、代碼觸發(fā)、報告集成 |
標(biāo)準(zhǔn)化項目結(jié)構(gòu)
采用分層設(shè)計思想,將配置、接口、用例、工具、數(shù)據(jù)分離,保證框架的可維護性:
api_auto_test/ ├── config/ # 環(huán)境配置目錄 │ └── config.yaml # 多環(huán)境配置(開發(fā)/測試/生產(chǎn)) ├── api/ # 接口封裝層(所有業(yè)務(wù)接口) │ ├── __init__.py │ └── login_api.py # 登錄接口封裝 ├── testcases/ # 測試用例層(僅寫用例邏輯) │ ├── __init__.py │ └── test_login.py # 登錄模塊測試用例 ├── utils/ # 工具層(通用方法) │ ├── __init__.py │ ├── request_util.py # HTTP 請求封裝 │ ├── assert_util.py # 統(tǒng)一斷言工具 │ └── log_util.py # 日志工具(可選) ├── data/ # 測試數(shù)據(jù)層(數(shù)據(jù)驅(qū)動) │ └── login_data.yaml # 登錄模塊測試數(shù)據(jù) ├── reports/ # 測試報告輸出目錄 ├── requirements.txt # 項目依賴清單 └── pytest.ini # Pytest 全局配置文件
環(huán)境搭建與依賴安裝
1. 基礎(chǔ)環(huán)境要求
- Python 3.8 及以上版本
- pip 包管理工具
2. 安裝依賴包
執(zhí)行以下命令一鍵安裝所有依賴:
pip install requests pytest pyyaml allure-pytest
3. 生成依賴清單
方便后續(xù)團隊協(xié)作和 CI 集成:
pip freeze > requirements.txt
核心模塊實現(xiàn)
5.1 多環(huán)境配置管理
在 config/config.yaml 中配置多環(huán)境信息,支持一鍵切換:
# 環(huán)境配置:dev-開發(fā)環(huán)境 test-測試環(huán)境 prod-生產(chǎn)環(huán)境
active_env: "test"
env:
dev:
base_url: "https://dev-api.example.com"
timeout: 10
test:
base_url: "https://api.example.com"
timeout: 10
prod:
base_url: "https://prod-api.example.com"
timeout: 155.2 通用請求工具封裝
在 utils/request_util.py 中封裝 HTTP 請求,增加異常處理和日志打印:
import requests
import yaml
import logging
from typing import Dict, Any
# 配置日志
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
class RequestUtil:
def __init__(self):
# 加載配置文件
with open("../config/config.yaml", "r", encoding="utf-8") as f:
self.config = yaml.safe_load(f)
# 獲取當(dāng)前激活的環(huán)境
self.active_env = self.config["active_env"]
self.base_url = self.config["env"][self.active_env]["base_url"]
self.timeout = self.config["env"][self.active_env]["timeout"]
def send_request(
self,
method: str,
path: str,
headers: Dict[str, str] = None,
params: Dict[str, Any] = None,
json: Dict[str, Any] = None,
data: Any = None,
**kwargs
) -> requests.Response:
"""
統(tǒng)一發(fā)送 HTTP 請求
:param method: 請求方法 GET/POST/PUT/DELETE
:param path: 接口路徑
:param headers: 請求頭
:param params: URL 參數(shù)
:param json: JSON 格式請求體
:param data: 表單格式請求體
:return: 響應(yīng)對象
"""
url = self.base_url + path
logger.info(f"請求地址: {method} {url}")
logger.info(f"請求參數(shù): params={params}, json={json}")
try:
resp = requests.request(
method=method,
url=url,
headers=headers,
params=params,
json=json,
data=data,
timeout=self.timeout,
**kwargs
)
logger.info(f"響應(yīng)狀態(tài)碼: {resp.status_code}")
logger.info(f"響應(yīng)內(nèi)容: {resp.text[:500]}") # 只打印前500字符,避免日志過長
return resp
except requests.exceptions.Timeout:
logger.error(f"請求超時: {url}")
raise
except requests.exceptions.ConnectionError:
logger.error(f"連接失敗: {url}")
raise
except Exception as e:
logger.error(f"請求異常: {str(e)}")
raise
5.3 業(yè)務(wù)接口層封裝
在 api/login_api.py 中封裝登錄接口,遵循一個接口一個方法的原則:
from utils.request_util import RequestUtil
class LoginApi:
def __init__(self):
self.request = RequestUtil()
def login(self, username: str, password: str):
"""
登錄接口
:param username: 用戶名
:param password: 密碼
:return: 響應(yīng)對象
"""
path = "/api/v1/login"
payload = {
"username": username,
"password": password
}
return self.request.send_request(
method="POST",
path=path,
json=payload
)
5.4 數(shù)據(jù)驅(qū)動測試數(shù)據(jù)
在 data/login_data.yaml 中管理測試數(shù)據(jù),實現(xiàn)數(shù)據(jù)與腳本分離:
- case_name: 正常登錄-正確用戶名密碼 username: "test01" password: "123456" expect_status: 200 expect_code: 0 expect_msg: "登錄成功" - case_name: 登錄失敗-密碼錯誤 username: "test01" password: "wrong123" expect_status: 200 expect_code: 1001 expect_msg: "密碼錯誤" - case_name: 登錄失敗-用戶名不存在 username: "nonexist" password: "123456" expect_status: 200 expect_code: 1002 expect_msg: "用戶不存在" - case_name: 登錄失敗-用戶名為空 username: "" password: "123456" expect_status: 200 expect_code: 1003 expect_msg: "用戶名不能為空"
5.5 測試用例編寫
在 testcases/test_login.py 中編寫測試用例,使用 Pytest 參數(shù)化實現(xiàn)數(shù)據(jù)驅(qū)動:
import pytest
import yaml
from api.login_api import LoginApi
# 加載測試數(shù)據(jù)
def load_login_data():
with open("../data/login_data.yaml", "r", encoding="utf-8") as f:
return yaml.safe_load(f)
class TestLogin:
def setup_class(self):
"""測試類執(zhí)行前的初始化操作"""
self.login_api = LoginApi()
@pytest.mark.parametrize("case", load_login_data(), ids=[case["case_name"] for case in load_login_data()])
def test_login_cases(self, case):
"""登錄接口測試用例"""
# 發(fā)送請求
resp = self.login_api.login(
username=case["username"],
password=case["password"]
)
# 斷言
assert resp.status_code == case["expect_status"]
assert resp.json()["code"] == case["expect_code"]
assert case["expect_msg"] in resp.json()["msg"]
5.6 統(tǒng)一斷言工具
在 utils/assert_util.py 中封裝常用斷言方法,統(tǒng)一斷言邏輯:
import requests
from typing import Any
def assert_status_code(resp: requests.Response, expect_code: int = 200):
"""斷言響應(yīng)狀態(tài)碼"""
assert resp.status_code == expect_code, f"狀態(tài)碼錯誤,預(yù)期:{expect_code},實際:{resp.status_code}"
def assert_response_code(resp: requests.Response, expect_code: int = 0):
"""斷言業(yè)務(wù)響應(yīng)碼"""
assert resp.json()["code"] == expect_code, f"業(yè)務(wù)碼錯誤,預(yù)期:{expect_code},實際:{resp.json()['code']}"
def assert_response_contains(resp: requests.Response, key: str, value: Any):
"""斷言響應(yīng)體包含指定鍵值對"""
assert key in resp.json(), f"響應(yīng)體中不存在鍵:{key}"
assert resp.json()[key] == value, f"鍵值錯誤,預(yù)期:{value},實際:{resp.json()[key]}"
def assert_response_msg_contains(resp: requests.Response, expect_msg: str):
"""斷言響應(yīng)消息包含指定內(nèi)容"""
assert expect_msg in resp.json()["msg"], f"響應(yīng)消息不包含:{expect_msg},實際:{resp.json()['msg']}"
測試執(zhí)行與報告生成
1. 基礎(chǔ)執(zhí)行命令
在項目根目錄執(zhí)行以下命令運行所有測試用例:
pytest -v
2. 生成 Allure 測試報告
# 執(zhí)行測試并生成 Allure 原始數(shù)據(jù) pytest -v --alluredir=reports/allure-results # 啟動本地服務(wù)查看報告 allure serve reports/allure-results # 生成靜態(tài) HTML 報告(可部署到服務(wù)器) allure generate reports/allure-results -o reports/allure-report --clean
Pytest 全局配置
在 pytest.ini 中配置 Pytest 全局參數(shù),簡化執(zhí)行命令:
[pytest]
# 默認(rèn)命令行參數(shù):-s 輸出print信息 --tb=short 簡化錯誤堆棧
addopts = -s --tb=short --alluredir=reports/allure-results
# 指定測試用例搜索路徑
testpaths = testcases
# 指定測試文件命名規(guī)則
python_files = test_*.py
# 指定測試類命名規(guī)則
python_classes = Test*
# 指定測試方法命名規(guī)則
python_functions = test_*
# 標(biāo)記用例(用于分組執(zhí)行)
markers =
smoke: 冒煙測試用例
regression: 回歸測試用例Jenkins CI/CD 持續(xù)集成
將框架集成到 Jenkins,實現(xiàn)代碼提交自動觸發(fā)測試和定時回歸測試:
- 安裝插件:在 Jenkins 插件管理中安裝
Allure Plugin、Git Plugin - 新建自由風(fēng)格項目
- 配置源碼管理:填寫 Git 倉庫地址和分支
- 添加構(gòu)建步驟:執(zhí)行 Shell 命令
# 安裝依賴 pip install -r requirements.txt # 執(zhí)行測試 pytest
- 配置構(gòu)建后操作:添加
Allure Report,指定報告路徑為reports/allure-results - 可選配置:
- 構(gòu)建觸發(fā)器:設(shè)置定時構(gòu)建(如每天凌晨 2 點執(zhí)行回歸測試)
- 構(gòu)建通知:配置郵件通知,構(gòu)建失敗時發(fā)送郵件給相關(guān)人員
常見問題 FAQ
Allure 安裝失敗怎么辦?
- Windows:下載 Allure 二進制包,解壓后將 bin 目錄添加到系統(tǒng)環(huán)境變量
- Mac:執(zhí)行
brew install allure - Linux:執(zhí)行
sudo apt install allure
運行用例提示文件路徑錯誤?
- 確保在項目根目錄執(zhí)行 pytest 命令
- 將相對路徑改為絕對路徑,或使用
os.path模塊動態(tài)獲取路徑
中文亂碼問題?
- 在打開文件時指定
encoding="utf-8" - 在 pytest.ini 中添加
env = LANG=zh_CN.UTF-8
- 在打開文件時指定
如何處理需要 Token 的接口?
- 將登錄獲取 Token 的操作封裝為 Fixture,在需要的用例中引用
- 將 Token 保存到全局變量或配置文件中,供后續(xù)接口使用
結(jié)語
接口自動化不是簡單的“寫腳本”,而是構(gòu)建一套可持續(xù)維護、可擴展、可集成的質(zhì)量保障體系。本文提供的方案是一個基礎(chǔ)框架,你可以根據(jù)項目實際需求進行擴展,比如增加數(shù)據(jù)庫操作、接口簽名、文件上傳下載等功能。
到此這篇關(guān)于Python + Pytest接口自動化測試方案的實現(xiàn)的文章就介紹到這了,更多相關(guān)Python Pytest接口自動化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用python+requests+pytest實現(xiàn)接口自動化
- Python+Requests+PyTest+Excel+Allure?接口自動化測試實戰(zhàn)
- python+pytest接口自動化之session會話保持的實現(xiàn)
- python+pytest接口自動化參數(shù)關(guān)聯(lián)
- python+pytest接口自動化之日志管理模塊loguru簡介
- python+pytest接口自動化之token關(guān)聯(lián)登錄的實現(xiàn)
- python使用pytest接口自動化測試的使用
- python+requests+pytest接口自動化的實現(xiàn)示例
相關(guān)文章
Python機器學(xué)習(xí)之基于Pytorch實現(xiàn)貓狗分類
看了許多關(guān)于PyTorch的入門文章,大抵是從torchvision.datasets中自帶的數(shù)據(jù)集進行訓(xùn)練,導(dǎo)致很難把PyTorch運用于自己的數(shù)據(jù)集上,真正地靈活運用PyTorch,本文詳細(xì)介紹了怎么利用Pytorch實現(xiàn)貓狗分類,需要的朋友可以參考下2021-06-06
使用python接受tgam的腦波數(shù)據(jù)實例
這篇文章主要介紹了使用python接受tgam的腦波數(shù)據(jù)實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
使用Pandas處理時間序列數(shù)據(jù)Time Series詳解
SQLAlchemy是Python中最流行的ORM(對象關(guān)系映射)框架之一,它提供了高效且靈活的數(shù)據(jù)庫操作方式,本文將介紹如何使用SQLAlchemy ORM進行數(shù)據(jù)庫操作,有需要的可以了解下2025-11-11
python之PyInstaller(將Python腳本打包為可執(zhí)行文件方式)
PyInstaller將Python腳本打包為跨平臺可執(zhí)行文件,自動處理依賴庫,支持單文件/目錄模式,便于分發(fā),適用于GUI、數(shù)據(jù)文件處理及多平臺部署,優(yōu)化體積與權(quán)限問題2025-09-09
django2+uwsgi+nginx上線部署到服務(wù)器Ubuntu16.04
這篇文章主要介紹了django2+uwsgi+nginx上線部署到服務(wù)器Ubuntu16.04,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
python神經(jīng)網(wǎng)絡(luò)AlexNet分類模型訓(xùn)練貓狗數(shù)據(jù)集
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)AlexNet分類模型訓(xùn)練貓狗數(shù)據(jù)集,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05

