测试框架:pytest(Python)
HTTP 库:requests
测试报告:pytest-html + Allure(可视化报告)
CI 平台: GitHub Actions
被测接口:测试 /auth/login 和 /user/{id} 接口
一、项目结构
.github/
workflows/
api-tests.yml # CI工作流
tests/
test_auth.py # 认证接口测试
test_user_api.py # 用户接口测试
requirements.txt # Python依赖
.env.example # 环境变量示例
二、GitHub Actions 工作流配置
(.github/workflows/api-tests.yml)
name: API Test Suite
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 8 * * 1-5' # 工作日每天早8点运行
jobs:
run-api-tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10']
# 多环境测试矩阵
environment: [staging, preprod]
env:
API_BASE_URL: ${{
matrix.environment == 'staging' && 'https://api.staging.example.com' ||
matrix.environment == 'preprod' && 'https://api.preprod.example.com'
}}
PYTHON_VERSION: ${{ matrix.python-version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
# 安装测试工具
pip install pytest pytest-xdist allure-pytest requests pytest-dotenv
- name: Run API tests
env:
API_AUTH_TOKEN: ${{ secrets.API_AUTH_TOKEN }}
# 从GitHub Secrets获取敏感信息
TEST_USER: ${{ secrets.TEST_USER }}
TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
run: |
# 并行运行测试 (4个worker)
pytest tests/ \
--alluredir=allure-results \
-n 4 \
--junitxml=junit-results.xml \
-v
- name: Upload Allure results
uses: actions/upload-artifact@v3
if: always() # 即使测试失败也上传
with:
name: allure-results-${{ matrix.environment }}
path: allure-results
- name: Publish Allure Report
uses: simple-elf/allure-report-action@v1
if: success() # 只有测试成功才生成报告
with:
allure_results: allure-results
repo_token: ${{ secrets.GITHUB_TOKEN }}
public_url: https://your-username.github.io/your-repo
- name: Upload JUnit results
uses: actions/upload-artifact@v3
with:
name: junit-results-${{ matrix.environment }}
path: junit-results.xml
- name: Notify Slack on failure
if: failure()
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_MESSAGE: "🔥 *API Tests Failed* (${{ matrix.environment }})\nBranch: ${{ github.ref }}\nCommit: ${{ github.sha }}\nWorkflow: ${{ github.workflow }}\nDetails: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
SLACK_COLOR: danger
- name: Notify Slack on success
if: success()
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_MESSAGE: "✅ *API Tests Passed* (${{ matrix.environment }})\nBranch: ${{ github.ref }}\nCommit: ${{ github.sha }}\nReport: https://your-username.github.io/your-repo"
SLACK_COLOR: good
三、测试代码示例 (tests/test_auth.py)
import os
import pytest
import requests
import allure
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
BASE_URL = os.getenv("API_BASE_URL", "https://api.example.com")
AUTH_TOKEN = os.getenv("API_AUTH_TOKEN")
TEST_USER = os.getenv("TEST_USER")
TEST_PASSWORD = os.getenv("TEST_PASSWORD")
@allure.feature("认证API")
class TestAuthAPI:
@allure.story("用户登录")
@allure.severity(allure.severity_level.CRITICAL)
def test_login_success(self):
"""测试有效凭据登录成功"""
payload = {
"username": TEST_USER,
"password": TEST_PASSWORD
}
with allure.step("发送登录请求"):
response = requests.post(
f"{BASE_URL}/auth/login",
json=payload,
timeout=10
)
with allure.step("验证响应"):
assert response.status_code == 200
json_data = response.json()
assert "access_token" in json_data
assert "refresh_token" in json_data
assert json_data["token_type"] == "Bearer"
# 附加响应详情到报告
allure.attach(response.text, name="响应数据", attachment_type=allure.attachment_type.JSON)
@allure.story("无效登录")
@pytest.mark.parametrize("invalid_creds", [
{"username": "invalid", "password": TEST_PASSWORD},
{"username": TEST_USER, "password": "wrongpassword"},
{"username": "", "password": TEST_PASSWORD},
{"username": TEST_USER, "password": ""}
])
def test_login_failure(self, invalid_creds):
"""测试无效凭据登录失败"""
with allure.step(f"使用无效凭据登录: {invalid_creds}"):
response = requests.post(
f"{BASE_URL}/auth/login",
json=invalid_creds,
timeout=8
)
with allure.step("验证错误响应"):
assert response.status_code == 401
assert "error" in response.json()
allure.attach(response.text, name="错误响应")
四、环境变量配置 (.env.example)
# 测试环境配置示例
API_BASE_URL=https://api.staging.example.com
API_AUTH_TOKEN=your_auth_token_here
TEST_USER=testuser@example.com
TEST_PASSWORD=securePassword123
五、 依赖文件 (requirements.txt)
pytest==7.4.0
requests==2.31.0
allure-pytest==2.13.2
pytest-xdist==3.3.1
python-dotenv==1.0.0
pytest-dotenv==1.0.0
GitHub 配置步骤
设置 Secrets:
仓库设置 → Secrets and variables → Actions → New repository secret
添加以下 secrets:
API_AUTH_TOKEN:接口认证令牌
TEST_USER:测试用户名
TEST_PASSWORD:测试密码
SLACK_WEBHOOK:Slack 通知的 Webhook URL
启用 GitHub Pages(用于 Allure 报告):
仓库设置 → Pages → Build and deployment
Source: GitHub Actions
分支保护规则(可选):
仓库设置 → Branches → Add branch protection rule
选择 main 分支
勾选 "Require status checks to pass before merging"