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 参数正确,且测试执行未跳过。

selenium 文章被收录于专栏

selenium 入门到精通

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

相关推荐

评论
点赞
4
分享

创作者周榜

更多
牛客网
牛客企业服务