Python + Selenium + Pytest 自动化测试实战示例
1. 环境准备
# 安装依赖库
pip install selenium pytest pytest-html webdriver-manager
2. 项目结构
automation_framework/
├── conftest.py
├── pages/
│ ├── __init__.py
│ └── login_page.py
├── tests/
│ ├── __init__.py
│ └── test_login.py
├── utils/
│ └── webdriver_factory.py
└── reports/ (自动生成)
3. 核心组件实现
a. 浏览器驱动管理 (utils/webdriver_factory.py)
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
class WebDriverFactory:
@staticmethod
def get_driver(browser="chrome"):
if browser.lower() == "firefox":
return webdriver.Firefox(
executable_path=GeckoDriverManager().install()
)
else:
return webdriver.Chrome(
executable_path=ChromeDriverManager().install()
)
b. 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.url = "https://example.com/login"
def open(self):
self.driver.get(self.url)
def enter_username(self, username):
self.driver.find_element(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 WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.CLASS_NAME, "error-message"))
).text
c. 测试配置 (conftest.py)
import pytest
from utils.webdriver_factory import WebDriverFactory
@pytest.fixture(scope="function")
def browser(request):
driver = WebDriverFactory.get_driver()
driver.maximize_window()
yield driver
driver.quit()
@pytest.fixture
def login_page(browser):
page = LoginPage(browser)
page.open()
return page
4. 测试用例实现 (tests/test_login.py)
import pytest
class TestLogin:
@pytest.mark.parametrize("username, password", [
("admin", "correct_password"),
("test_user", "valid_pass123")
])
def test_valid_login(self, login_page, username, password):
login_page.enter_username(username)
login_page.enter_password(password)
login_page.click_login()
assert "Dashboard" in login_page.driver.title
def test_invalid_password(self, login_page):
login_page.enter_username("admin")
login_page.enter_password("wrong_pass")
login_page.click_login()
assert "Invalid credentials" in login_page.get_error_message()
def test_empty_fields(self, login_page):
login_page.click_login()
error_text = login_page.get_error_message()
assert "Username is required" in error_text
assert "Password is required" in error_text
5. 运行测试
# 执行所有测试并生成HTML报告
pytest --html=reports/report.html --self-contained-html
6. 测试报告示例
执行后将在 reports/ 目录生成交互式HTML报告:
- 包含通过/失败的测试用例统计
- 每个测试步骤的详细日志
- 失败用例的屏幕截图
7. 关键设计要点
-
分层架构:
- Page Object 封装页面交互
- 测试用例专注业务逻辑验证
- 驱动管理独立于测试逻辑
-
参数化测试:
@pytest.mark.parametrize("username, password", [ ("user1", "pass1"), ("user2", "pass2") ]) -
智能等待机制:
WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, "element")) ) -
失败自动截图 (在
conftest.py中添加):@pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() if report.when == "call" and report.failed: driver = item.funcargs["browser"] driver.save_screenshot(f"reports/screenshot_{item.name}.png")
8. 高级功能扩展
-
跨浏览器测试:
pytest --browser=firefox -
API 集成测试:
def test_login_api(api_client): response = api_client.post("/login", json={"username": "test", "password": "pass"}) assert response.status_code == 200 assert "auth_token" in response.json() -
持续集成配置 (Jenkinsfile 示例):
pipeline { agent any stages { stage('Test') { steps { sh 'pip install -r requirements.txt' sh 'pytest --html=report.html' } post { always { publishHTML target: [ allowMissing: true, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'reports', reportFiles: 'report.html', reportName: 'HTML Report' ] } } } } }
最佳实践建议:
- 使用
pytest-xdist实现并行测试- 敏感数据(如密码)通过
.env文件管理- 元素定位器统一管理在
locators.py文件中- 添加
@pytest.mark.flaky(retries=2)处理偶发失败- 使用
Allure框架生成更专业的测试报告
1643

被折叠的 条评论
为什么被折叠?



