Python + Selenium + Pytest + Allure实现UI自动化

以下是使用 Python + Selenium + Pytest + Allure 实现 UI 自动化的详细步骤指南:

1. 环境准备

1.1 安装 Python

  • 下载并安装 Python,建议使用 Python 3.8+。
  • 配置 Python 环境变量。

1.2 安装依赖库

pip install pytest selenium allure-pytest webdriver-manager
  • pytest: 测试框架
  • selenium: 浏览器自动化工具
  • allure-pytest: 生成 Allure 报告
  • webdriver-manager: 自动管理浏览器驱动

2. 项目结构

project/
├── conftest.py          # pytest 配置和共享 fixture
├── pages/               # 页面对象模型 (Page Object Model)
│   ├── __init__.py
│   └── login_page.py
├── tests/               # 测试用例
│   └── test_login.py
├── requirements.txt     # 依赖列表
└── allure-results/      # Allure 报告数据(自动生成)

3. 编写 Fixture

在 conftest.py 中配置浏览器驱动和测试失败自动截图:

import pytest
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service as ChromeService
import allure

@pytest.fixture(scope="function")
def browser(request):
    # 初始化浏览器(自动下载驱动)
    options = webdriver.ChromeOptions()
    options.add_argument("--headless")  # 无头模式(可选)
    driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=options)
    
    # 最大化窗口
    driver.maximize_window()
    
    # 失败时截图
    yield driver
    if request.node.rep_call.failed:
        allure.attach(
            driver.get_screenshot_as_png(),
            name="screenshot",
            attachment_type=allure.attachment_type.PNG
        )
    driver.quit()

# Hook 函数捕获测试结果
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    rep = outcome.get_result()
    setattr(item, "rep_" + rep.when, rep)

4. 实现页面对象模型 (Page Object)

在 pages/login_page.py 中封装登录页面逻辑:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)
    
    def open(self, url):
        self.driver.get(url)
    
    def enter_username(self, username):
        self.wait.until(EC.visibility_of_element_located((By.ID, "username"))).send_keys(username)
    
    def enter_password(self, password):
        self.driver.find_element(By.ID, "password").send_keys(password)
    
    def click_login(self):
        self.driver.find_element(By.XPATH, "//button[@type='submit']").click()
    
    def get_error_message(self):
        return self.wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "error-message"))).text

5. 编写测试用例

在 tests/test_login.py 中编写测试逻辑:

import allure
import pytest
from pages.login_page import LoginPage

@allure.feature("登录功能")
class TestLogin:
    @allure.story("用户登录成功")
    @allure.severity(allure.severity_level.CRITICAL)
    def test_login_success(self, browser):
        login_page = LoginPage(browser)
        with allure.step("1. 打开登录页面"):
            login_page.open("https://example.com/login")
        with allure.step("2. 输入用户名和密码"):
            login_page.enter_username("valid_user")
            login_page.enter_password("valid_pass")
        with allure.step("3. 点击登录按钮"):
            login_page.click_login()
        with allure.step("4. 验证登录成功"):
            assert "Dashboard" in browser.title

    @allure.story("用户登录失败")
    @pytest.mark.parametrize("username, password, error_msg", [
        ("invalid_user", "wrong_pass", "用户名或密码错误"),
        ("", "valid_pass", "用户名不能为空")
    ])
    def test_login_failure(self, browser, username, password, error_msg):
        login_page = LoginPage(browser)
        login_page.open("https://example.com/login")
        login_page.enter_username(username)
        login_page.enter_password(password)
        login_page.click_login()
        assert error_msg in login_page.get_error_message()

6. 运行测试并生成报告

6.1 执行测试

pytest tests/test_login.py --alluredir=./allure-results

6.2 查看 Allure 报告

allure serve ./allure-results
  • 自动打开浏览器展示交互式报告。

7. 高级配置

7.1 Headless 模式

在 conftest.py 的浏览器初始化中添加无头模式选项:

options.add_argument("--headless")
options.add_argument("--disable-gpu")

7.2 参数化测试

使用 @pytest.mark.parametrize 覆盖多组数据:

@pytest.mark.parametrize("username, password", [("user1", "pass1"), ("user2", "pass2")])
def test_multiple_users(self, username, password):
    # 测试逻辑

7.3 集成到 CI/CD

在 GitHub Actions 中添加步骤:

- name: Run Tests
  run: |
    pytest tests/ --alluredir=./allure-results
- name: Generate Report
  run: |
    allure generate ./allure-results -o ./allure-report --clean

常见问题

  1. 元素定位失败使用显式等待 (WebDriverWait) 代替硬编码等待 (time.sleep).优先使用 ID 或 CSS 选择器,避免脆弱的 XPath.
  2. 浏览器驱动问题使用 webdriver-manager 自动管理驱动版本。
  3. 报告无数据确保 --alluredir 参数正确,且测试执行未跳过。

进阶高级测试工程师 文章被收录于专栏

《高级软件测试工程师》专栏旨在为测试领域的从业者提供深入的知识和实践指导,帮助大家从基础的测试技能迈向高级测试专家的行列。 在本专栏中,主要涵盖的内容: 1. 如何设计和实施高效的测试策略; 2. 掌握自动化测试、性能测试和安全测试的核心技术; 3. 深入理解测试驱动开发(TDD)和行为驱动开发(BDD)的实践方法; 4. 测试团队的管理和协作能力。 ——For.Heart

全部评论
大佬写得很好
点赞 回复 分享
发布于 03-11 11:15 上海

相关推荐

面试题概要(基于参考文本) --- 一、个人背景与基础能力 1. 自我介绍考察点     - 教育背景与实验室经历(人工智能实验室、算法竞赛)     - 技术栈掌握情况(Java/Spring后端开发、Python自动化测试)     - 实习经验与项目角色(高顿教育测试实习生、接口/UI自动化)   2. 实习与职业规划     - 实习时间短的原因(学校安排、地理位置)     - 毕业后的职业方向(明确选择测试岗位,侧重自动化测试)     - 当前技术学习重点(测试理论、自动化框架搭建)   --- 二、项目经验与技术实践 1. 实验室项目(Web端开发与测试)     - 技术难点:前后端协作问题、质量保障缺失(未联调/自测)     - 解决方案:学习测试方法论(等价类划分、因果图)、设计用例     - 成果:接口自动化测试(Pytest + Requests + YAML驱动)   2. 企业级项目(高顿教育测试实习)     - 核心模块:       - OSS文件上传接口测试(AI校验、恶意文件检测)       - 直播间预定与推流任务异常(定时任务逻辑优化)       - 优惠券发放与页面交互验证     - 自动化工具链:       - 接口自动化(基于平台/Swagger文档导入)       - UI自动化(Sonic真机平台、ConceptsJS框架 + XPath定位)       - 脚本维护(配置文件管理、失败重试/截图机制)   3. 自动化测试能力     - 技术栈:Python(Pytest)、JS(ConceptsJS)、Postman/JMeter     - 成功率与问题:90%通过率,偶发服务器压力导致的失败     - 与企业实践差异:平台化工具 vs 自研脚本的维护成本   --- 三、测试理论与场景设计 1. 测试用例设计(购买大会员场景)     - 基本流程验证:页面跳转、支付方式调用、金额计算(优惠券/积分)     - 异常场景覆盖:       - 网络波动(弱网/断网支付中断)       - 支付失败/取消订单(误开通会员风险)       - 订阅续费逻辑(自动扣款校验)     - 非功能测试:       - 安全性测试(敏感信息加密、环境风险拦截)       - 性能测试(高并发支付场景)   2. 测试方法论应用     - 等价类划分(合法/非法文件格式测试)     - 因果图(直播间预定与导流任务的条件组合)   --- 四、编码能力与问题解决 1. 算法题表现     - 题目:最长连续序列(数组排序后动态规划思路)     - 考察点:       - 排序API熟练度(Java `Arrays.sort()` 误写为 `sort()`)       - 逻辑实现(DP数组记录连续长度,取最大值)     - 临场问题:依赖AI辅助编码导致基础语法生疏   2. 工具使用与反思     - AI辅助编码的利弊(效率提升 vs 基础能力弱化)     - 自研项目与学习路径(开源测试框架研究、TestNG集成)   --- 五、综合评价与建议 1. 面试官反馈     - 优势:       - 项目经验丰富(实验室+企业级场景)       - 自动化工具链的实践与快速学习能力     - 待提升:       - 测试理论深度(如故障演练、全链路压测)       - 编码基础巩固(减少对AI工具的过度依赖)   2. 候选人提问     - 团队业务方向(OGV内容生态、大会员/C端测试重点)     - 技术栈细节(Web/App自动化框架选型、平台化工具 vs 自研)     - 入职安排(最快到岗时间、实习期任务分配)   --- 六、面试流程总结 - 时长:约45分钟  - 考察维度:技术深度(50%)、项目经验(30%)、逻辑思维(20%)  - 后续流程:结果通知周期(1周内)、潜在入职时间(3天内到岗)   --- 此概要可用于复盘面试表现或指导后续测试岗位面试准备,重点需强化理论体系与手写代码能力。
查看23道真题和解析
点赞 评论 收藏
分享
评论
点赞
8
分享

创作者周榜

更多
牛客网
牛客企业服务