当前位置:首页>python>Python+Pytest+Allure+Playwright 自动化测试框架搭建教程

Python+Pytest+Allure+Playwright 自动化测试框架搭建教程

  • 2026-09-10 02:46:53
Python+Pytest+Allure+Playwright 自动化测试框架搭建教程

Python + Pytest + Allure + Playwright 自动化测试框架搭建教程

本文详细介绍如何搭建一个企业级的自动化测试框架,包含 Python + Pytest + Allure + Playwright。


一、技术栈介绍

1.1 各技术简介

技术 作用 特点
Python 编程语言 简单易学、生态丰富
Pytest 测试框架 简洁强大、插件丰富
Allure 测试报告 美观直观、支持历史趋势
Playwright 自动化工具 跨浏览器、自动等待

1.2 框架架构

自动化测试框架/
├── core/                  # 核心模块
│   ├── base.py           # 基类封装
│   ├── driver.py         # 浏览器驱动
│   └── logger.py         # 日志管理
├── pages/                # 页面对象
│   ├── base_page.py     # 页面基类
│   └── demo_page.py     # 具体页面
├── testcases/           # 测试用例
│   ├── test_login.py
│   └── test_search.py
├── utils/               # 工具类
│   ├── config.py       # 配置管理
│   └── excel_helper.py # 数据驱动
├── data/                # 测试数据
│   └── test_data.xlsx
├── reports/             # 测试报告
├── requirements.txt    # 依赖
└── pytest.ini          # 配置文件

二、环境准备

2.1 安装 Python

# 检查 Python 版本
python3 --version

# 建议使用 Python 3.8+

2.2 创建虚拟环境

# 创建项目目录
mkdir auto_framework && cd auto_framework

# 创建虚拟环境
python3 -m venv venv

# 激活虚拟环境
# Linux/Mac:
source venv/bin/activate
# Windows:
venv\Scripts\activate

2.3 安装依赖

pip install pytest playwright allure-pytest pytest-playwright

# 初始化 Playwright
playwright install chromium

三、核心配置

3.1 requirements.txt

pytest==7.4.3
playwright==1.40.0
allure-pytest==2.13.2
pytest-html==4.1.1
pytest-xdist==3.5.0
pytest-repeat==0.9.3
python-dotenv==1.0.0
openpyxl==3.1.2
loguru==0.7.2

3.2 pytest.ini

[pytest]
# 测试路径
testpaths = testcases

# 文件匹配
python_files = test_*.py
python_classes = Test*
python_functions = test_*

# 标记
markers =
    smoke: 冒烟测试
    regression: 回归测试
    login: 登录相关
    slow: 慢速测试

# 日志
log_cli = true
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S

# 报告
addopts = -v --tb=short --html=reports/report.html --self-contained-html

3.3 .env 配置文件

# .env 文件
ENV=TEST
BASE_URL=https://demo.test.com
BROWSER=chromium
HEADLESS=true
TIMEOUT=30000

四、核心代码实现

4.1 浏览器驱动封装 (core/driver.py)

import os
from playwright.sync_api import sync_playwright
from dotenv import load_dotenv

load_dotenv()

class BrowserDriver:
    """浏览器驱动管理"""
    
    @staticmethod
    def get_browser():
        """获取浏览器实例"""
        playwright = sync_playwright().start()
        browser = playwright.chromium.launch(
            headless=os.getenv("HEADLESS", "true").lower() == "true",
            args=['--disable-blink-features=AutomationControlled']
        )
        return playwright, browser
    
    @staticmethod
    def get_context(browser):
        """获取浏览器上下文"""
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            locale='zh-CN'
        )
        return context
    
    @staticmethod
    def get_page(context):
        """获取新页面"""
        page = context.new_page()
        page.set_default_timeout(int(os.getenv("TIMEOUT", "30000")))
        return page

4.2 页面基类 (pages/base_page.py)

from playwright.sync_api import Page
from loguru import logger

class BasePage:
    """页面对象基类"""
    
    def __init__(self, page: Page):
        self.page = page
    
    def goto(self, url: str):
        """跳转URL"""
        logger.info(f"打开页面: {url}")
        self.page.goto(url)
    
    def click(self, selector: str):
        """点击元素"""
        logger.info(f"点击元素: {selector}")
        self.page.click(selector)
    
    def fill(self, selector: str, value: str):
        """输入文本"""
        logger.info(f"输入内容到 {selector}: {value}")
        self.page.fill(selector, value)
    
    def get_text(self, selector: str) -> str:
        """获取文本"""
        return self.page.text_content(selector)
    
    def wait_for_selector(self, selector: str, timeout: int = 30000):
        """等待元素出现"""
        self.page.wait_for_selector(selector, timeout=timeout)
    
    def screenshot(self, name: str = "screenshot"):
        """截图"""
        self.page.screenshot(path=f"reports/screenshots/{name}.png")
    
    def is_visible(self, selector: str) -> bool:
        """检查元素是否可见"""
        return self.page.is_visible(selector)

4.3 日志配置 (core/logger.py)

import sys
from loguru import logger
import os

# 移除默认处理器
logger.remove()

# 控制台输出
logger.add(
    sys.stdout,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>",
    level="INFO"
)

# 文件输出
log_dir = "reports/logs"
os.makedirs(log_dir, exist_ok=True)
logger.add(
    f"{log_dir}/{{time:YYYY-MM-DD}}.log",
    rotation="00:00",
    retention="30 days",
    level="DEBUG",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}"
)

五、测试用例示例

5.1 conftest.py ( fixtures )

import pytest
from playwright.sync_api import sync_playwright
from core.driver import BrowserDriver
from core.logger import logger
import os

@pytest.fixture(scope="session")
def browser():
    """浏览器 fixture"""
    playwright, browser = BrowserDriver.get_browser()
    yield browser
    browser.close()
    playwright.stop()

@pytest.fixture(scope="function")
def page(browser):
    """页面 fixture"""
    context = browser.new_context(
        viewport={'width': 1920, 'height': 1080}
    )
    page = context.new_page()
    yield page
    context.close()

@pytest.fixture(scope="function", autouse=True)
def test_info(request):
    """打印测试信息"""
    logger.info(f"开始执行: {request.node.name}")
    yield
    logger.info(f"结束执行: {request.node.name}")

5.2 登录测试用例

import pytest
from pages.login_page import LoginPage
from pages.home_page import HomePage
from core.logger import logger

class TestLogin:
    """登录测试"""
    
    @pytest.mark.login
    def test_login_success(self, page):
        """测试登录成功"""
        login_page = LoginPage(page)
        home_page = HomePage(page)
        
        # 执行登录
        login_page.goto("https://demo.test.com/login")
        login_page.login("testuser", "password123")
        
        # 断言
        assert home_page.is_logged_in(), "登录失败"
        logger.info("登录成功 ✓")
    
    @pytest.mark.login
    def test_login_failed(self, page):
        """测试登录失败"""
        login_page = LoginPage(page)
        
        login_page.goto("https://demo.test.com/login")
        login_page.login("wronguser", "wrongpass")
        
        # 断言登录失败提示
        assert login_page.get_error_msg() == "用户名或密码错误"
        logger.info("登录失败用例通过 ✓")

六、Allure 报告配置

6.1 生成 Allure 报告

# 运行测试并生成 Allure 数据
pytest testcases/ --alluredir=reports/allure-results

# 生成 HTML 报告
allure serve reports/allure-results

6.2 添加测试描述

import allure

@allure.title("登录成功测试")
@allure.description("验证用户使用正确账号密码可以成功登录")
@allure.severity(allure.severity_level.BLOCKER)
@allure.feature("登录功能")
@allure.story("用户登录")
def test_login_success(page):
    """测试登录成功"""
    pass

6.3 附件支持

def test_with_screenshot(page):
    """带截图的测试"""
    page.goto("https://example.com")
    
    # 添加截图
    page.screenshot(path="screenshot.png")
    allure.attach.file("screenshot.png", attachment_type=allure.attachment_type.PNG)
    
    # 添加日志
    allure.attach("这是测试日志", name="日志", attachment_type=allure.attachment_type.TEXT)

七、数据驱动测试

7.1 CSV 数据驱动

import pytest
import csv

@pytest.mark.parametrize("username,password,expected", [
    ("user1", "pass1", "success"),
    ("user2", "pass2", "fail"),
]
)

def test_login_data_driven(username, password, expected):
    """CSV数据驱动测试"""
    print(f"Testing: {username} / {password}")

7.2 Excel 数据驱动

import openpyxl

def get_test_data():
    """从Excel读取测试数据"""
    wb = openpyxl.load_workbook("data/test_data.xlsx")
    ws = wb.active
    
    data = []
    for row in ws.iter_rows(min_row=2, values_only=True):
        data.append(row)
    return data

@pytest.mark.parametrize("username,password,expected", get_test_data())
def test_login_excel(username, password, expected):
    """Excel数据驱动"""
    print(f"Testing: {username}")

八、CI/CD 集成

8.1 GitHub Actions

name: Auto Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      
      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          playwright install chromium
      
      - name: Run tests
        run: pytest testcases/ --alluredir=reports/allure-results
      
      - name: Upload Allure results
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: allure-results
          path: reports/allure-results

8.2 Jenkinsfile

pipeline {
    agent any
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Install') {
            steps {
                sh 'pip install -r requirements.txt'
                sh 'playwright install chromium'
            }
        }
        
        stage('Test') {
            steps {
                sh 'pytest testcases/ --alluredir=reports/allure-results'
            }
        }
        
        stage('Report') {
            steps {
                allure includeProperties: false, results: [[path: 'reports/allure-results']], report: 'reports/allure-report'
            }
        }
    }
}

九、常用命令汇总

9.1 测试运行命令

# 运行所有测试
pytest

# 运行指定文件
pytest testcases/test_login.py

# 运行指定标记
pytest -m smoke

# 跳过标记
pytest -m "not slow"

# 并行执行
pytest -n 4

# 失败重试
pytest --reruns 3

# 生成HTML报告
pytest --html=reports/report.html

# 生成Allure报告
pytest --alluredir=reports/allure-results

9.2 Allure 报告命令

# 生成报告
allure generate reports/allure-results -o reports/allure-report

# 打开报告
allure open reports/allure-report

# 启动服务
allure serve reports/allure-results

十、常见问题

Q1: Playwright 浏览器下载失败

解决:

playwright install chromium --with-deps

Q2: Allure 报告中文乱码

解决:

allure generate -c -Dallure.results.directory=reports/allure-results -Dallure.link.issue.pattern=https://jira.test.com/browse/{}

Q3: 元素找不到

解决: 使用自动等待

page.wait_for_load_state("networkidle")
page.click("selector", timeout=10000)

Q4: 截图保存失败

解决: 确保目录存在

os.makedirs("reports/screenshots", exist_ok=True)

十一、总结

本框架特点:

✅ 结构清晰 - Page Object 模式 ✅ 易于维护 - 页面元素与逻辑分离 ✅ 报告美观 - Allure 集成 ✅ 数据驱动 - 支持 Excel/CSV ✅ CI/CD 集成 - 支持 GitHub Actions/Jenkins ✅ 日志完善 - 详细的执行日志

快去搭建你的自动化测试框架吧!

需要帮助随时问我!

最新文章

随机文章