--
:
--
:
--
第七阶段:最佳实践与框架设计
最后更新于:
第七阶段:最佳实践与框架设计
一、测试框架设计原则
1.1 分层架构
1pytest_project/
2├── src/ # 源代码
3├── tests/ # 测试代码
4│ ├── unit/ # 单元测试
5│ ├── api/ # 接口测试
6│ └── ui/ # UI测试
7├── config/ # 配置文件
8├── data/ # 测试数据
9├── logs/ # 日志
10└── reports/ # 报告1.2 可维护性
- 代码结构清晰,易于扩展
- 使用描述性命名
- 避免重复代码
- 使用fixture复用逻辑
1.3 可配置性
- 支持不同环境切换
- 使用配置文件管理参数
- 支持命令行参数覆盖
1.4 报告能力
- 生成详细的测试报告
- 包含失败截图
- 支持多种报告格式
二、配置管理
2.1 使用YAML配置文件
1# config/config.yaml
2api:
3 base_url: http://127.0.0.1:8000
4 timeout: 30
5 retries: 3
6
7database:
8 host: localhost
9 port: 5432
10 name: test_db
11
12logging:
13 level: INFO
14 format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
15
16test:
17 parallel: 4
18 report_dir: reports2.2 配置加载模块
1# src/config.py
2import yaml
3import os
4
5def load_config(config_path: str = None) -> dict:
6 if config_path is None:
7 config_path = os.path.join(os.path.dirname(__file__), '..', 'config', 'config.yaml')
8
9 with open(config_path, 'r', encoding='utf-8') as f:
10 return yaml.safe_load(f)
11
12def get_api_base_url() -> str:
13 config = load_config()
14 return config.get('api', {}).get('base_url', 'http://127.0.0.1:8000')2.3 使用fixture加载配置
1# tests/conftest.py
2import pytest
3from src.config import load_config
4
5@pytest.fixture(scope="session")
6def config():
7 return load_config()
8
9@pytest.fixture(scope="session")
10def api_base_url(config):
11 return config.get('api', {}).get('base_url', 'http://127.0.0.1:8000')三、测试数据管理
3.1 使用JSON测试数据
1// data/test_data.json
2{
3 "users": [
4 {"name": "测试用户1", "email": "test1@example.com", "vip": true},
5 {"name": "测试用户2", "email": "test2@example.com", "vip": false}
6 ],
7 "orders": [
8 {"user_id": "1", "items": [{"name": "商品A", "price": 100}]}
9 ]
10}3.2 测试数据加载
1# src/config.py
2import json
3
4def get_test_data(data_path: str = None) -> dict:
5 if data_path is None:
6 data_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'test_data.json')
7
8 with open(data_path, 'r', encoding='utf-8') as f:
9 return json.load(f)3.3 使用测试数据的fixture
1@pytest.fixture(scope="session")
2def test_data():
3 return get_test_data()
4
5@pytest.fixture(params=get_test_data()["users"])
6def test_user_data(request):
7 return request.param四、服务自动管理
4.1 自动启动/停止服务
1# tests/conftest.py
2import pytest
3import subprocess
4import time
5import sys
6import requests
7
8@pytest.fixture(scope="session")
9def fastapi_server(api_base_url):
10 server_process = subprocess.Popen(
11 [sys.executable, "-m", "uvicorn", "api.main:app", "--host", "127.0.0.1", "--port", "8000"],
12 stdout=subprocess.PIPE,
13 stderr=subprocess.PIPE,
14 cwd=os.path.dirname(os.path.dirname(__file__))
15 )
16
17 retries = 10
18 for _ in range(retries):
19 try:
20 response = requests.get(api_base_url)
21 if response.status_code == 200:
22 break
23 except requests.exceptions.ConnectionError:
24 pass
25 time.sleep(1)
26 else:
27 server_process.terminate()
28 raise RuntimeError("Failed to start FastAPI server")
29
30 yield server_process
31
32 server_process.terminate()
33 server_process.wait()4.2 依赖服务的fixture
1@pytest.fixture(scope="session")
2def api_client(fastapi_server, api_base_url):
3 session = requests.Session()
4 session.base_url = api_base_url
5 yield session
6 session.close()五、CI/CD集成
5.1 GitHub Actions配置
1# .github/workflows/pytest.yml
2name: Pytest CI
3
4on:
5 push:
6 branches: [ main, develop ]
7 pull_request:
8 branches: [ main, develop ]
9
10jobs:
11 test:
12 runs-on: ubuntu-latest
13
14 steps:
15 - uses: actions/checkout@v4
16
17 - name: Set up Python
18 uses: actions/setup-python@v5
19 with:
20 python-version: '3.9'
21
22 - name: Install dependencies
23 run: |
24 python -m pip install --upgrade pip
25 pip install -r requirements.txt
26
27 - name: Install Playwright browsers
28 run: playwright install --with-deps chromium
29
30 - name: Run unit tests
31 run: pytest tests/unit/ -v --cov=src --cov-report=html
32
33 - name: Run API tests
34 run: pytest tests/api/ -v --html=reports/api_report.html
35
36 - name: Run UI tests
37 run: pytest tests/ui/ -v --browser=chromium --html=reports/ui_report.html
38
39 - name: Upload reports
40 uses: actions/upload-artifact@v4
41 with:
42 name: test-reports
43 path: reports/
44
45 - name: Upload coverage report
46 uses: actions/upload-artifact@v4
47 with:
48 name: coverage-report
49 path: htmlcov/5.2 Jenkins配置
1pipeline {
2 agent any
3
4 stages {
5 stage('Checkout') {
6 steps {
7 git url: 'https://github.com/your-repo/pytest-project.git'
8 }
9 }
10
11 stage('Install Dependencies') {
12 steps {
13 sh 'pip install -r requirements.txt'
14 }
15 }
16
17 stage('Run Tests') {
18 steps {
19 sh 'pytest -v --html=reports/report.html'
20 }
21 }
22
23 stage('Archive Reports') {
24 steps {
25 archiveArtifacts artifacts: 'reports/**'
26 }
27 }
28 }
29}六、依赖管理
6.1 requirements.txt
1pytest>=8.0.0
2pytest-html>=4.0.0
3pytest-xdist>=3.0.0
4pytest-cov>=4.0.0
5pytest-mock>=3.0.0
6pytest-base-url>=2.0.0
7pytest-playwright>=0.7.0
8requests>=2.28.0
9fastapi>=0.100.0
10uvicorn>=0.20.0
11PyYAML>=6.0.06.2 虚拟环境
1# 创建虚拟环境
2python -m venv venv
3
4# 激活虚拟环境
5# Windows
6venv\Scripts\activate
7
8# Linux/macOS
9source venv/bin/activate
10
11# 安装依赖
12pip install -r requirements.txt
13
14# 导出依赖
15pip freeze > requirements.txt七、日志系统
7.1 配置日志
1import logging
2
3logging.basicConfig(
4 level=logging.INFO,
5 format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
6 handlers=[
7 logging.FileHandler("logs/test.log"),
8 logging.StreamHandler()
9 ]
10)
11
12logger = logging.getLogger(__name__)7.2 在测试中使用日志
1def test_example(logger):
2 logger.info("开始测试")
3 # 测试代码
4 logger.info("测试完成")八、易错点与注意事项
8.1 框架设计常见错误
- 过度设计:设计过于复杂,难以维护
- 重复造轮子:没有使用现成的插件和工具
- 缺乏文档:代码没有足够的注释和文档
- 硬编码:配置和测试数据硬编码在代码中
- 缺乏容错:没有处理异常和边界情况
8.2 CI/CD常见错误
- 环境不一致:CI环境与开发环境不一致
- 依赖缺失:忘记安装依赖或浏览器
- 超时问题:测试执行时间过长导致超时
- 报告丢失:没有正确保存测试报告
8.3 最佳实践
- 保持框架简洁,避免过度设计
- 使用现成的插件和工具
- 编写清晰的文档和注释
- 使用配置文件管理参数
- 在CI/CD环境中使用无头模式
九、小结
本阶段学习了pytest的最佳实践和框架设计,包括:
- 测试框架设计原则
- 配置管理和测试数据管理
- 服务自动管理
- CI/CD集成
- 依赖管理
- 日志系统
📡
👤
作者:
阿海
🌐
版权:
本站文章除特别声明外,均采用
CC BY-NC-SA 4.0
协议,转载请注明来自
阿海 Blog!
- 01JMeter界面详解 2026-07-11
- 02性能测试学习路线 2026-07-11
- 03JMeter线程组配置详解 2026-07-11