Pytest+Selenium构建126邮箱UI自动化测试框架实战
1. 项目概述最近在测试领域摸爬滚打多年发现UI自动化测试已经成为测试工程师必备的核心技能之一。今天想分享一个基于PytestSelenium的实战项目通过126邮箱的完整测试案例带大家从零构建一个可落地的自动化测试框架。这个项目不是简单的Demo而是一个具备完整功能的测试框架包含测试数据管理Excel驱动页面对象封装PageObject模式测试报告生成pytest-html邮件通知yagmail异常处理机制常用工具封装键盘模拟、剪贴板操作等2. 环境准备与配置2.1 基础环境搭建首先需要准备测试环境这是自动化测试的基础保障# Python环境建议3.6 python --version # 安装核心测试库 pip install pytest selenium pytest-html openpyxl yagmail pypiwin32 # 浏览器驱动配置 # Chrome驱动下载地址https://chromedriver.chromium.org/downloads # 将下载的chromedriver.exe放在Python安装目录下的Scripts文件夹中注意浏览器驱动版本必须与本地安装的浏览器版本匹配否则会出现兼容性问题。建议使用Chrome稳定版。2.2 项目目录结构设计良好的目录结构是维护大型测试项目的基础PytestAutoTestFrameWork/ ├── config/ # 配置文件 │ ├── __init__.py │ ├── conf.py # 路径配置 │ └── config.ini # 测试配置 ├── data/ # 测试数据 │ ├── __init__.py │ └── tcData.xlsx # Excel测试数据 ├── Page/ # 页面对象 │ ├── BasePage.py # 基础页面类 │ ├── ContactPage.py # 联系人页面 │ ├── HomePage.py # 首页 │ ├── LoginPage.py # 登录页面 │ └── SendMailPage.py # 发件页面 ├── report/ # 测试报告 ├── TestCases/ # 测试用例 │ ├── __init__.py │ ├── conftest.py # pytest配置 │ ├── test_confactCase.py │ ├── test_loginCase.py │ └── test_sendMailCase.py ├── util/ # 工具类 │ ├── clipboard.py # 剪贴板操作 │ ├── keyboard.py # 键盘模拟 │ ├── parseConFile.py # 配置文件解析 │ └── parseExcelFile.py # Excel解析 ├── conftest.py # 全局pytest配置 ├── pytest.ini # pytest运行配置 └── RunTestCase.py # 用例执行入口3. 核心组件实现3.1 WebDriver二次封装在BasePage.py中我们对Selenium WebDriver进行了深度封装增加了以下关键功能class BasePage(object): def __init__(self, driver, outTime30): self.driver driver self.outTime outTime self.byDic { id: By.ID, name: By.NAME, class_name: By.CLASS_NAME, xpath: By.XPATH, link_text: By.LINK_TEXT } def findElement(self, by, locator): 智能等待元素查找 try: element WebDriverWait(self.driver, self.outTime).until( lambda x: x.find_element(by, locator)) return element except TimeoutException: print(f定位元素超时: {locator}) raise def click(self, by, locator): 增强型点击操作 element self.findElement(by, locator) try: element.click() except ElementClickInterceptedException: self.driver.execute_script(arguments[0].click();, element)实战经验在click方法中添加JS点击是为了解决某些情况下元素被遮挡的问题这是UI自动化测试中常见的坑。3.2 页面对象模式实现以登录页面为例展示PageObject模式的实现class LoginPage(BasePage): # 从配置文件中读取元素定位 frame BasePage.cf.getLocatorsOrAccount(LoginPageElements, frame) username BasePage.cf.getLocatorsOrAccount(LoginPageElements, username) password BasePage.cf.getLocatorsOrAccount(LoginPageElements, password) loginBtn BasePage.cf.getLocatorsOrAccount(LoginPageElements, loginBtn) def login(self, userName, passWord): 登录业务流程封装 self.loadUrl(https://mail.126.com) self.switchToFrame(*self.frame) self.clear(*self.username) self.sendKeys(*self.username, userName) self.sendKeys(*self.password, passWord) self.click(*self.loginBtn) self.switchToDefaultFrame()3.3 测试数据驱动通过Excel管理测试数据实现数据与代码分离class ParseExcel(object): def __init__(self): self.wk load_workbook(excelPath) self.excelFile excelPath def getSheetByName(self, sheetName): 获取指定sheet页数据 return self.wk[sheetName] def getAllValuesOfSheet(self, sheet): 获取sheet页所有测试数据 allValues [] for row in range(2, sheet.max_row 1): rowValues [] for column in range(1, sheet.max_column 1): value sheet.cell(row, column).value rowValues.append(value if value is not None else ) allValues.append(tuple(rowValues)) return allValuesExcel测试数据示例用例编号用户名密码预期结果login_01correct_usercorrect_pwd登录成功login_02wrong_userany_pwd用户名不存在4. 测试用例设计与实现4.1 登录功能测试# test_loginCase.py import pytest from Page.LoginPage import LoginPage pytest.mark.parametrize(username,password,expected, [ (correct_user, correct_pwd, None), # 成功用例 (wrong_user, any_pwd, 用户名不存在) # 失败用例 ]) def test_login(driver, username, password, expected): 登录功能测试 login_page LoginPage(driver) login_page.login(username, password) if expected: assert login_page.getErrorText() expected else: assert 收件箱 in driver.page_source4.2 发送邮件测试# test_sendMailCase.py import pytest from Page.LoginPage import LoginPage from Page.HomePage import HomePage from Page.SendMailPage import SendMailPage pytest.fixture(scopemodule) def login(driver): login_page LoginPage(driver) login_page.login(test_user, test_pwd) yield # 退出登录等清理操作 def test_send_mail(login, driver): 发送邮件测试 home_page HomePage(driver) home_page.selectMenu(mailList) mail_page SendMailPage(driver) mail_page.sendMail( Addressrecipientexample.com, Subject自动化测试邮件, Text这是一封由自动化测试发送的邮件 ) assert 发送成功 in mail_page.getSuccessText()5. 高级功能实现5.1 测试报告生成配置pytest-html生成美观的测试报告# pytest.ini [pytest] addopts --htmlreport/report.html --self-contained-html testpaths TestCases python_files test_*.py python_classes Test* python_functions test_*5.2 邮件通知功能使用yagmail自动发送测试报告# util/sendMailForReport.py import yagmail def send_report(): yag yagmail.SMTP( usersender126.com, passwordyour_password, hostsmtp.126.com ) contents [ 本次自动化测试报告请查收, 测试结果见附件, /path/to/report.html ] yag.send( torecipientexample.com, subject自动化测试报告, contentscontents )6. 常见问题与解决方案6.1 元素定位失败问题问题现象NoSuchElementException: Unable to locate element...解决方案增加显式等待时间检查iframe嵌套使用更稳定的定位方式如# 不推荐 driver.find_element_by_xpath(//div[classlogin]/input[3]) # 推荐 driver.find_element(By.CSS_SELECTOR, .login-btn)6.2 浏览器兼容性问题问题现象脚本在Chrome运行正常但在Firefox失败解决方案确保浏览器驱动版本匹配添加浏览器特定的处理逻辑if browser_type firefox: # Firefox特定处理 driver.find_element(...).send_keys(Keys.ENTER) else: # Chrome处理 driver.find_element(...).click()6.3 测试数据管理问题问题现象测试数据变更导致大量测试用例失败解决方案使用数据工厂模式生成测试数据实现数据版本控制添加数据有效性检查def validate_test_data(data): required_fields [username, password] for field in required_fields: if field not in data or not data[field]: raise ValueError(f测试数据缺少必填字段: {field})7. 项目优化建议7.1 引入日志系统添加详细的日志记录方便问题排查import logging logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(automation.log), logging.StreamHandler() ] ) logger logging.getLogger(__name__) # 在关键操作中添加日志 logger.info(开始执行登录操作) login_page.login(username, password) logger.info(登录操作完成)7.2 实现失败重试机制通过pytest插件实现自动重试# pytest.ini [pytest] addopts --reruns 2 --reruns-delay 17.3 添加可视化监控使用Allure生成更美观的测试报告pip install allure-pytest pytest --alluredir./allure-results allure serve ./allure-results8. 完整执行流程准备测试环境编写测试用例执行测试命令python RunTestCase.py查看测试报告分析测试结果修复问题并回归测试这个框架在实际项目中已经验证过稳定性能够支持复杂的UI自动化测试需求。通过合理的扩展还可以集成API测试、性能测试等形成完整的测试解决方案。