头像
淇迹时刻
-- : -- : --
切换主题色
-- : -- : --

第七阶段:最佳实践与框架设计

最后更新于:

第七阶段:最佳实践与框架设计

一、测试框架设计原则

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 可维护性

  1. 代码结构清晰,易于扩展
  2. 使用描述性命名
  3. 避免重复代码
  4. 使用fixture复用逻辑

1.3 可配置性

  1. 支持不同环境切换
  2. 使用配置文件管理参数
  3. 支持命令行参数覆盖

1.4 报告能力

  1. 生成详细的测试报告
  2. 包含失败截图
  3. 支持多种报告格式

二、配置管理

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: reports

2.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.0

6.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 框架设计常见错误

  1. 过度设计:设计过于复杂,难以维护
  2. 重复造轮子:没有使用现成的插件和工具
  3. 缺乏文档:代码没有足够的注释和文档
  4. 硬编码:配置和测试数据硬编码在代码中
  5. 缺乏容错:没有处理异常和边界情况

8.2 CI/CD常见错误

  1. 环境不一致:CI环境与开发环境不一致
  2. 依赖缺失:忘记安装依赖或浏览器
  3. 超时问题:测试执行时间过长导致超时
  4. 报告丢失:没有正确保存测试报告

8.3 最佳实践

  1. 保持框架简洁,避免过度设计
  2. 使用现成的插件和工具
  3. 编写清晰的文档和注释
  4. 使用配置文件管理参数
  5. 在CI/CD环境中使用无头模式

九、小结

本阶段学习了pytest的最佳实践和框架设计,包括:

  • 测试框架设计原则
  • 配置管理和测试数据管理
  • 服务自动管理
  • CI/CD集成
  • 依赖管理
  • 日志系统
最新文章