ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

博客系统 Web自动化测试项目报告

博客系统 Web自动化测试项目报告 博客系统 Web 自动化测试项目报告一、项目概述1.1 项目名称博客系统 Web 自动化测试项目1.2 项目类型Web UI 自动化测试项目1.3 项目背景本项目针对一个基于浏览器访问的博客管理系统进行自动化测试主要验证用户登录、博客列表查看、博客详情查看以及博客发布等核心业务功能。项目使用 Python 编写测试脚本基于 Selenium WebDriver 驱动 Chrome 浏览器模拟真实用户在网页中的操作流程并通过元素定位、页面跳转、文本断言、弹窗处理等方式验证系统功能是否符合预期。该项目主要用于熟悉以下测试开发工作Web 页面元素定位浏览器自动化操作用户登录流程测试正向和反向测试用例设计页面跳转验证博客发布流程验证JavaScript 编辑器交互处理浏览器弹窗处理测试截图保存测试结果分析和缺陷定位。1.4 项目目标本项目的主要目标如下验证博客系统的核心功能是否能够正常使用验证错误账号或错误密码时系统是否给出正确提示验证登录成功后页面是否正确跳转验证博客列表页面是否能够正常加载验证博客详情内容是否正确展示验证用户是否可以成功发布博客验证博客发布后的成功提示和页面跳转提高回归测试效率减少人工重复操作积累 Selenium Web 自动化测试实践经验。二、项目环境2.1 测试环境项目内容操作系统Windows开发工具PyCharm编程语言Python自动化框架Selenium WebDriver浏览器Google Chrome浏览器驱动ChromeDriverPython 环境Python 3.11测试对象博客系统 Web 页面页面协议HTTP测试地址http://47.108.157.13:8090项目目录pythonProject2测试目录tests2.2 主要依赖项目主要使用以下技术和库selenium核心 Selenium 模块包括fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasEC各模块作用如下模块作用webdriver启动和控制 Chrome 浏览器By提供元素定位方式WebDriverWait实现显式等待expected_conditions判断页面元素、弹窗和页面状态是否满足条件time在特殊场景下进行短暂等待execute_script通过 JavaScript 操作复杂页面元素三、被测系统功能分析博客系统主要包含以下功能模块3.1 登录功能用户通过登录页面输入用户名和密码点击登录按钮进入博客系统。测试内容包括正确用户名和正确密码登录错误密码登录登录成功后的页面跳转登录失败时的错误提示登录状态下的页面访问权限。3.2 博客列表功能登录成功后系统跳转到博客列表页面。测试内容包括博客列表页面能否正常访问博客标题是否正常显示博客列表页面的基本布局是否正常博客数据是否能够加载页面跳转地址是否正确。3.3 博客详情功能用户从博客列表进入某篇博客详情页查看博客完整内容。测试内容包括详情页是否能够正常打开博客标题是否正确博客正文是否正确列表页和详情页之间的跳转是否正常。3.4 博客发布功能登录用户进入博客编辑页面填写博客标题和正文点击“发布文章”按钮完成博客发布。测试内容包括博客标题输入博客正文输入Markdown 编辑器交互发布按钮点击发布成功弹窗发布后页面跳转新博客是否出现在博客列表中发布博客标题是否正确。3.5 注销功能系统页面提供注销入口用于退出当前登录状态。测试内容包括点击注销按钮页面是否返回登录页登录状态是否被清除注销后是否还能直接访问需要登录的页面。四、自动化测试框架设计4.1 项目目录结构项目目录可以整理为以下形式pythonProject2 │ ├─ tests │ ├─ BlogDriver.py │ ├─ BlogLogin.py │ ├─ BlogList.py │ ├─ BlogDetail.py │ ├─ BlogEdit.py │ └─ RunTest.py │ ├─ screenshots │ └─ ... │ └─ .venv各文件职责如下文件职责RunTest.py测试执行入口统一调用各个测试方法BlogDriver.py浏览器驱动初始化、浏览器关闭、截图等公共操作BlogLogin.py登录相关测试BlogList.py博客列表页面测试BlogDetail.py博客详情页面测试BlogEdit.py博客发布页面测试screenshots保存测试过程截图4.2 测试执行流程整体测试流程如下启动浏览器 ↓ 进入博客系统 ↓ 执行错误密码登录测试 ↓ 验证登录失败提示 ↓ 执行正确账号登录 ↓ 验证跳转到博客列表页 ↓ 执行博客列表测试 ↓ 执行博客详情测试 ↓ 进入博客编辑页 ↓ 填写博客标题和正文 ↓ 点击发布按钮 ↓ 处理“博客发表成功”弹窗 ↓ 验证跳转到博客列表页 ↓ 验证新博客标题 ↓ 保存截图 ↓ 结束测试五、测试用例设计5.1 登录模块测试用例用例编号测试功能测试步骤预期结果LOGIN-001正确账号登录输入正确用户名和密码点击登录登录成功并跳转到博客列表页LOGIN-002错误密码登录输入正确用户名和错误密码点击登录页面提示“密码不正确”LOGIN-003错误用户名登录输入不存在的用户名和密码页面提示登录失败LOGIN-004用户名为空不输入用户名点击登录页面提示用户名不能为空或阻止提交LOGIN-005密码为空输入用户名不输入密码页面提示密码不能为空或阻止提交LOGIN-006登录成功页面验证登录成功后获取当前 URLURL 应包含blog_list.htmlLOGIN-007登录失败页面验证使用错误密码登录页面不应进入博客列表页5.1.1 错误密码测试错误密码场景属于反向测试主要验证系统是否能够正确识别非法登录信息。示例断言actualself.driver.find_element(By.CSS_SELECTOR,body).textassert密码不正确inactual该测试可以防止以下问题错误密码也能登录错误提示不显示错误提示内容错误页面跳转到错误页面前端校验失效。5.2 博客列表模块测试用例用例编号测试功能测试步骤预期结果LIST-001打开博客列表登录成功后进入列表页页面正常加载LIST-002页面地址验证获取当前页面 URLURL 包含blog_list.htmlLIST-003博客标题验证获取第一篇博客标题标题正常显示LIST-004博客列表内容验证检查列表区域文本页面存在博客内容LIST-005博客跳转详情点击博客标题成功进入博客详情页LIST-006页面基本元素验证查找导航、列表和博客标题页面核心元素存在示例页面地址断言print(当前页面地址,self.driver.current_url)assertblog_list.htmlinself.driver.current_url5.3 博客详情模块测试用例用例编号测试功能测试步骤预期结果DETAIL-001打开博客详情在列表页点击博客详情页正常打开DETAIL-002详情标题验证获取详情页标题标题与列表页一致DETAIL-003正文内容验证获取博客正文正文正常显示DETAIL-004页面地址验证获取当前 URLURL 包含详情页地址DETAIL-005返回列表页点击返回或主页返回博客列表页详情页测试重点在于验证页面之间的数据一致性。博客列表页展示的标题应该与详情页展示的标题一致。5.4 博客发布模块测试用例用例编号测试功能测试步骤预期结果EDIT-001打开编辑页面点击“写博客”成功进入博客编辑页EDIT-002输入博客标题在标题框输入内容标题输入成功EDIT-003输入博客正文在编辑器中输入正文正文输入成功EDIT-004发布空博客不填写内容直接发布系统阻止发布并提示错误EDIT-005发布博客填写标题和正文后点击发布页面提示“博客发表成功”EDIT-006发布弹窗处理获取浏览器 Alert 文本Alert 内容为“博客发表成功”EDIT-007发布后页面跳转关闭成功弹窗跳转到博客列表页EDIT-008新博客标题验证查找刚发布的博客标题标题与输入内容一致EDIT-009新博客正文验证进入详情页检查正文正文与输入内容一致六、关键自动化实现6.1 显式等待项目中使用 Selenium 的显式等待来提高脚本稳定性。示例waitWebDriverWait(self.driver,10)titlewait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,#title)))显式等待的优点等待元素真正出现避免页面加载较慢导致测试失败比固定sleep更稳定可以明确等待条件减少不必要的等待时间。常用等待条件包括EC.presence_of_element_located()EC.visibility_of_element_located()EC.element_to_be_clickable()EC.alert_is_present()6.2 博客正文编辑器处理博客编辑页面使用了 Markdown 编辑器页面中存在隐藏的textarea。虽然 Selenium 可以找到该元素但它可能处于不可交互状态直接执行content.send_keys(博客正文)可能出现ElementNotInteractableException项目中使用 JavaScript 对编辑器进行处理content_text这是自动化测试发布的博客正文内容self.driver.execute_script( const content arguments[0]; const editor document.querySelector(.vditor-sv__editor textarea) || document.querySelector(.vditor-ir__editor) || document.querySelector([contenteditabletrue]) || document.querySelector(textarea); if (!editor) { throw new Error(没有找到博客正文编辑器); } editor.focus(); if (editor.tagName.toLowerCase() textarea) { const setter Object.getOwnPropertyDescriptor( HTMLTextAreaElement.prototype, value ).set; setter.call(editor, content); } else { editor.innerText content; } editor.dispatchEvent(new Event(input, { bubbles: true })); editor.dispatchEvent(new Event(change, { bubbles: true })); ,content_text)该处理方式解决了以下问题Selenium 无法直接操作隐藏文本框页面实际可编辑区域与 DOM 中的textarea不一致通过 JavaScript 修改编辑器内容触发input和change事件使前端应用能够感知内容变化。这部分内容可以作为项目中的一个技术难点进行重点介绍。6.3 浏览器 Alert 弹窗处理点击发布后页面会弹出博客发表成功如果不处理弹窗继续执行self.driver.current_url会产生UnexpectedAlertPresentException正确处理方式如下submit.click()alertWebDriverWait(self.driver,10).until(EC.alert_is_present())alert_textalert.textprint(发布提示,alert_text)assertalert_text博客发表成功alert.accept()wait.until(lambdadriver:blog_list.htmlindriver.current_url)print(发布后当前页面地址,self.driver.current_url)这里包含了三个验证点等待弹窗出现验证弹窗内容点击确定关闭弹窗。这种方式比单纯使用time.sleep()更可靠。七、测试结果7.1 当前测试结果根据项目运行过程目前已验证的场景包括模块测试结果说明错误密码登录通过页面能够显示“密码不正确”正确账号登录通过成功进入博客列表页博客列表页面通过页面地址和内容验证通过博客详情页面通过详情页面能够正常打开博客发布功能功能成功页面显示“博客发表成功”发布成功弹窗处理已定位问题需要在读取 URL 前关闭 Alert发布后标题验证待最终确认需要处理弹窗后继续执行断言7.2 测试执行中的问题问题一正文编辑器无法直接输入错误信息ElementNotInteractableException原因页面中的textarea元素虽然存在但处于隐藏或不可交互状态。真正的编辑区域由 Markdown 编辑器动态生成。解决方案使用 JavaScript 获取可编辑区域修改编辑器内容手动触发input和change事件在测试代码中兼容textarea和contenteditable元素。问题二发布成功后读取 URL 报错错误信息UnexpectedAlertPresentException原因点击发布按钮后网页弹出浏览器原生 Alert博客发表成功此时 Selenium 不能继续操作当前页面必须先处理弹窗。解决方案alertWebDriverWait(self.driver,10).until(EC.alert_is_present())assertalert.text博客发表成功alert.accept()处理完成后再获取页面地址并执行后续断言。问题三固定等待可能导致测试不稳定早期代码中使用time.sleep(2)这种方式虽然简单但存在以下问题网络较慢时等待时间不足页面加载较快时浪费时间测试结果受机器性能影响无法准确判断页面是否真正加载完成。改进方式wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,#submit)))或wait.until(lambdadriver:blog_list.htmlindriver.current_url)八、测试数据设计8.1 登录测试数据数据类型用户名密码预期结果正确数据合法账号正确密码登录成功错误密码合法账号错误密码提示密码不正确错误用户名不存在账号任意密码登录失败空用户名空正确密码提示用户名不能为空空密码合法账号空提示密码不能为空8.2 博客发布测试数据字段测试值博客标题自动化测试创建博客正文这是自动化测试发布的博客正文内容发布方式点击发布按钮预期提示博客发表成功预期跳转blog_list.html预期结果列表中出现新博客九、项目中的测试方法9.1 黑盒测试从用户角度验证博客系统功能不关注内部实现细节。主要验证输入和输出是否符合预期页面是否正确跳转提示信息是否正确博客数据是否正确展示。9.2 功能测试针对博客系统核心功能编写测试用例包括登录注销博客列表博客详情博客发布。9.3 正向测试使用正常数据验证系统功能是否能够正常完成。例如正确账号登录正确填写标题和正文正常发布博客正常查看博客详情。9.4 反向测试使用异常数据验证系统的容错能力。例如输入错误密码输入空用户名输入空密码发布空博客不处理弹窗时继续访问页面。9.5 回归测试每次修改测试脚本或页面后重新执行已有测试用例确认原有功能没有受到影响。十、项目难点和解决方案10.1 难点一页面元素定位页面中有多个结构相似的元素部分元素没有明显的唯一 ID。解决方案优先使用唯一 ID其次使用稳定的 CSS Selector避免过度依赖绝对 XPath对关键元素增加显式等待对页面结构进行分析后再确定定位表达式。例如(By.CSS_SELECTOR,#title)比复杂的层级定位更加稳定。10.2 难点二动态页面加载页面内容不是打开页面后立即出现直接查找元素可能出现NoSuchElementException解决方案wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,#title)))10.3 难点三富文本或 Markdown 编辑器编辑器表面上是一个可输入区域但实际 DOM 结构可能包含隐藏的textarea可编辑的div预览区域动态生成的内部节点。解决方案通过浏览器开发者工具分析 DOM查找contenteditable属性使用 JavaScript 处理隐藏控件触发前端需要的事件。10.4 难点四原生浏览器弹窗发布成功后浏览器弹出 Alert导致 Selenium 暂停页面操作。解决方案alertwait.until(EC.alert_is_present())assertalert.text博客发表成功alert.accept()10.5 难点五测试流程之间存在依赖博客列表测试、详情测试和发布测试需要先完成登录。解决方案统一在测试入口中控制执行顺序将登录流程封装为公共方法在每个测试开始前确认当前页面状态后续可以改造成独立测试避免用例之间相互依赖。十一、项目质量改进方向11.1 引入 Pytest目前项目采用普通 Python 方法执行测试可以进一步迁移到 Pytest。例如importpytestclassTestBlog:deftest_login_success(self):passdeftest_blog_list(self):passdeftest_blog_publish(self):pass使用 Pytest 后可以获得自动发现测试用例更清晰的测试报告Fixture 管理浏览器参数化测试失败重试标记测试用例与 CI 工具集成。11.2 使用 Fixture 管理浏览器生命周期示例importpytestfromseleniumimportwebdriverpytest.fixturedefdriver():driverwebdriver.Chrome()driver.maximize_window()yielddriver driver.quit()这样可以统一管理浏览器启动浏览器关闭测试前置条件测试后清理工作。11.3 引入 Page Object Model可以将页面操作和测试断言分离。示例目录pages ├─ login_page.py ├─ blog_list_page.py ├─ blog_detail_page.py └─ blog_edit_page.py tests ├─ test_login.py ├─ test_blog_list.py ├─ test_blog_detail.py └─ test_blog_edit.py页面对象示例classBlogEditPage:def__init__(self,driver):self.driverdriverdefinput_title(self,title):self.driver.find_element(By.CSS_SELECTOR,#title).send_keys(title)defclick_submit(self):self.driver.find_element(By.CSS_SELECTOR,#submit).click()这样可以降低页面结构变化对测试代码的影响。11.4 增加日志记录可以使用 Python 的logging模块importlogging logging.basicConfig(levellogging.INFO,format%(asctime)s - %(levelname)s - %(message)s)logging.info(开始执行博客发布测试)logging.info(博客标题输入完成)logging.info(发布成功提示已确认)日志可以帮助定位测试执行到哪个步骤哪一步出现异常当前页面地址当前使用的测试数据页面跳转是否成功。11.5 自动生成测试报告可以使用pytest--htmlreport.html或者使用 Allurepytest--alluredirallure-results allure serve allure-results测试报告中可以包含用例名称执行结果错误信息截图执行时间测试步骤环境信息。11.6 接入持续集成后续可以将项目接入 Jenkins 或 GitHub Actions实现提交代码 ↓ 自动安装依赖 ↓ 启动测试环境 ↓ 执行自动化测试 ↓ 生成测试报告 ↓ 发送测试结果十二、项目成果通过本项目完成了博客系统核心功能的自动化验证主要成果如下实现了基于 Selenium 的浏览器自动化测试完成登录模块正向和反向测试完成博客列表页面测试完成博客详情页面测试完成博客发布流程测试实现页面元素定位和文本断言实现页面跳转地址验证实现浏览器 Alert 弹窗处理解决 Markdown 编辑器无法直接输入的问题使用显式等待提高测试稳定性实现测试截图保存根据测试异常定位页面交互和脚本问题对自动化测试过程中的异常进行了分析和修复具备从测试执行、问题定位到脚本改进的完整实践经验。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进