跳到主要内容
Web 项目 UI 自动化测试实战:从零搭建博客系统测试框架 | 极客日志
Python 大前端
Web 项目 UI 自动化测试实战:从零搭建博客系统测试框架 基于 Python 和 Selenium 构建博客系统 UI 自动化测试框架。涵盖环境配置、公共工具封装、核心模块用例开发及报告生成。实现登录、列表、详情、编辑等功能的自动化验证,包含异常场景处理与截图追溯,支持一键执行与 CI/CD 集成,提升回归测试效率。
星落 发布于 2026/3/28 更新于 2026/4/25 1 浏览前言
在软件开发流程中,重复的手动测试不仅耗时耗力,还容易出现遗漏。对于 Web 项目开发,尤其是涉及登录、列表展示、编辑提交等核心流程时,引入自动化测试能有效提升回归效率。本文将以一个基于 C++ 后端的 Web 博客系统为例,分享如何用 Python 搭建一套完整的 UI 自动化测试框架,从用例设计到脚本开发,再到报告落地,全程实战且代码可直接复用。
一、项目背景与测试规划
1.1 项目介绍
本次实战的被测对象是一个 Web 博客系统,核心功能模块包括:登录、博主信息、博客列表、博客编辑、博客详情。系统支持登录后查看和编辑,未登录用户访问受限功能时会触发登录提示。
1.2 测试目标
验证核心功能的稳定性和正确性;实现关键流程自动化执行,减少手动成本;快速定位迭代中的回归问题;输出清晰的测试报告支撑上线决策。
1.3 测试范围与用例设计
自动化测试聚焦核心流程和高频场景。我们设计了覆盖正常与异常场景的测试用例,例如正常登录、密码错误、账号为空、未登录访问受限页面等。
二、环境搭建
开始编码前,需完成环境配置。确保已安装 Python 3.8 及以上版本。
2.1 安装核心依赖包
使用 pip 安装所需库:
pip install selenium==4.10.0
pip install webdriver-manager==4.0.0
2.2 浏览器配置
以 Chrome 浏览器(推荐 110+)为例。利用 webdriver-manager 自动管理驱动,无需手动下载 ChromeDriver,解决版本匹配问题。
2.3 项目目录结构设计
清晰的目录结构是框架可维护的关键。建议采用以下结构:
blog_auto_test/
├── common/
│ └── Utils.py
├── cases/
│ ├── BlogLogin.py
│ ├── BlogList.py
│ ├── BlogEdit.py
│ └── BlogDetail.py
├── images/
├── reports/
└── RunCases.py
三、核心模块开发:封装公共工具
编写具体用例前,先封装公共工具类,避免重复编码。核心功能包括驱动创建、截图、异常处理等。
3.1 驱动管理与截图工具封装
文件路径:common/Utils.py
import datetime
import os.path
import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.common.exceptions import WebDriverException
:
driver =
( ):
:
options = webdriver.ChromeOptions()
options.add_argument( )
options.add_argument( )
options.add_argument( )
.driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
.driver.set_page_load_timeout( )
.driver.implicitly_wait( )
( )
WebDriverException e:
( )
Exception e:
( )
( ):
:
dirname = datetime.datetime.now().strftime( )
screenshot_dir =
os.path.exists(screenshot_dir):
os.makedirs(screenshot_dir)
case_name = sys._getframe().f_back.f_code.co_name
filename =
screenshot_path = os.path.join(screenshot_dir, filename)
.driver.save_screenshot(screenshot_path)
( )
screenshot_path
Exception e:
( )
( ):
.driver:
.driver.quit()
( )
blog_driver = Driver()
class
Driver
"""驱动管理类:创建浏览器驱动、截图、关闭驱动等功能封装"""
None
def
__init__
self
try
'--ignore-certificate-errors'
'--disable-gpu'
'window-size=1920,1080'
self
self
10
self
5
print
f"驱动初始化成功!ChromeDriver 版本:{self.driver.capabilities['chrome' ]['chromedriverVersion' ]} "
except
as
print
f"驱动初始化失败:{str (e)} "
raise
except
as
print
f"未知错误:{str (e)} "
raise
def
get_screen_shot
self
"""截图功能:按日期创建文件夹,文件名包含用例名和时间戳"""
try
'%Y-%m-%d'
f"../images/{dirname} "
if
not
f"{case_name} -{datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S' )} .png"
self
print
f"截图成功!路径:{screenshot_path} "
return
except
as
print
f"截图失败:{str (e)} "
return
None
def
quit_driver
self
"""关闭驱动,释放资源"""
if
self
self
print
"🔌 驱动已关闭,资源释放完成"
3.2 优化点说明
驱动全局共享 :通过全局实例确保所有用例使用同一浏览器,提高效率。
异常处理 :捕获常见异常并打印日志,方便定位。
灵活配置 :预留无头模式、窗口大小等选项,适应不同环境。
截图优化 :按日期分类存储,便于追溯。
四、测试用例开发 按照测试规划,逐个模块编写用例。遵循'前置条件→操作步骤→断言验证'逻辑。
4.1 登录模块测试 import time
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from common.Utils import blog_driver
class BlogLogin :
def __init__ (self ):
self .login_url = "http://192.168.47.135:8653/blog_system/blog_login.html"
self .driver = blog_driver.driver
self .driver.get(self .login_url)
print (f"打开登录页面:{self.login_url} " )
def clear_input (self ):
username_input = self .driver.find_element(By.CSS_SELECTOR, "#username" )
password_input = self .driver.find_element(By.CSS_SELECTOR, "#password" )
username_input.clear()
password_input.clear()
print ("清空账号密码输入框" )
def login_suc_test (self, username="admin" , password="123" ):
try :
print (f"\n===== 执行正常登录测试(账号:{username} )=====" )
self .clear_input()
self .driver.find_element(By.CSS_SELECTOR, "#username" ).send_keys(username)
self .driver.find_element(By.CSS_SELECTOR, "#password" ).send_keys(password)
self .driver.find_element(By.CSS_SELECTOR, "#submit" ).click()
time.sleep(2 )
avatar_element = self .driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > img" )
assert avatar_element.is_display()
print (f"正常登录测试通过!{username} 账号登录成功" )
blog_driver.get_screen_shot()
self .driver.back()
time.sleep(1 )
except NoSuchElementException:
print (f"正常登录测试失败:未找到博主头像元素" )
blog_driver.get_screen_shot()
raise
except AssertionError:
print (f"正常登录测试失败:博主头像元素不可见" )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"正常登录测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def login_fail_test (self, username="admin" , password="111" , expect_msg="用户名或密码错误!" ):
try :
print (f"\n===== 执行异常登录测试(账号:{username} )=====" )
self .clear_input()
self .driver.find_element(By.CSS_SELECTOR, "#username" ).send_keys(username)
self .driver.find_element(By.CSS_SELECTOR, "#password" ).send_keys(password)
self .driver.find_element(By.CSS_SELECTOR, "#submit" ).click()
time.sleep(1 )
actual_msg = self .driver.find_element(By.CSS_SELECTOR, "body" ).text
assert expect_msg in actual_msg, f"错误提示不匹配!预期:{expect_msg} ,实际:{actual_msg} "
print (f"异常登录测试通过!错误提示符合预期" )
blog_driver.get_screen_shot()
self .driver.back()
time.sleep(1 )
except (NoSuchElementException, AssertionError) as e:
print (f"异常登录测试失败:{str (e)} " )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"异常登录测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def login_empty_username_test (self ):
print (f"\n===== 执行账号为空登录测试 =====" )
self .clear_input()
self .driver.find_element(By.CSS_SELECTOR, "#password" ).send_keys("123" )
self .driver.find_element(By.CSS_SELECTOR, "#submit" ).click()
time.sleep(1 )
assert self .driver.current_url == self .login_url, "账号为空时页面不应跳转"
print (f"账号为空登录测试通过!页面未跳转" )
blog_driver.get_screen_shot()
def login_empty_password_test (self ):
print (f"\n===== 执行密码为空登录测试 =====" )
self .clear_input()
self .driver.find_element(By.CSS_SELECTOR, "#username" ).send_keys("admin" )
self .driver.find_element(By.CSS_SELECTOR, "#submit" ).click()
time.sleep(1 )
assert self .driver.current_url == self .login_url, "密码为空时页面不应跳转"
print (f"密码为空登录测试通过!页面未跳转" )
blog_driver.get_screen_shot()
if __name__ == "__main__" :
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
login_test.login_suc_test("lisi" , "123" )
login_test.login_fail_test("admin" , "111" , "用户名或密码错误!" )
login_test.login_empty_username_test()
login_test.login_empty_password_test()
blog_driver.quit_driver()
4.2 博客列表模块测试 import time
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from common.Utils import blog_driver, Driver
from cases.BlogLogin import BlogLogin
class BlogList :
def __init__ (self ):
self .list_url = "http://192.168.47.135:8653/blog_system/blog_list.html"
self .driver = blog_driver.driver
print (f"博客列表页 URL:{self.list_url} " )
def list_login_status_test (self ):
try :
print (f"\n===== 执行登录状态下博客列表测试 =====" )
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
self .driver.get(self .list_url)
print (f"已登录,访问列表页:{self.list_url} " )
time.sleep(2 )
avatar_element = self .driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > img" )
assert avatar_element.is_displayed(), "博主头像未显示,登录状态可能失效"
first_blog = self .driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div:nth-child(1) > a" )
assert first_blog.is_displayed(), "第一篇博客链接未找到"
all_blogs = self .driver.find_elements(By.CSS_SELECTOR, "body > div.container > div.right > div" )
blog_count = len (all_blogs)
assert blog_count > 10 , f"博客数量不足 10 篇,实际数量:{blog_count} "
first_blog.click()
time.sleep(2 )
assert self .driver.title == "博客详情页" , f"跳转失败,当前页面标题:{self.driver.title} "
blog_driver.get_screen_shot()
print ("===== 登录状态下博客列表测试通过 =====" )
except (NoSuchElementException, AssertionError) as e:
print (f"登录状态下博客列表测试失败:{str (e)} " )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"登录状态下博客列表测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def list_unlogin_status_test (self ):
try :
print (f"\n===== 执行未登录状态下博客列表测试 =====" )
blog_driver.quit_driver()
new_driver = Driver()
self .driver = new_driver.driver
self .driver.get(self .list_url)
print (f"未登录,直接访问列表页:{self.list_url} " )
time.sleep(2 )
assert self .driver.current_url == "http://192.168.47.135:8653/blog_system/blog_login.html" ,
f"未跳转至登录页,当前 URL:{self.driver.current_url} "
new_driver.get_screen_shot()
new_driver.quit_driver()
print ("===== 未登录状态下博客列表测试通过 =====" )
except AssertionError as e:
print (f"未登录状态下博客列表测试失败:{str (e)} " )
raise
except Exception as e:
print (f"未登录状态下博客列表测试异常:{str (e)} " )
raise
if __name__ == "__main__" :
list_test = BlogList()
list_test.list_login_status_test()
list_test.list_unlogin_status_test()
4.3 博客详情模块测试 import time
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from common.Utils import blog_driver, Driver
from cases.BlogLogin import BlogLogin
from cases.BlogList import BlogList
class BlogDetail :
def __init__ (self, blog_id=15 ):
self .detail_url = f"http://192.168.47.135:8653/blog_system/blog_detail.html?blogId={blog_id} "
self .driver = blog_driver.driver
self .blog_id = blog_id
print (f"博客详情页 URL(ID:{blog_id} ):{self.detail_url} " )
def detail_login_status_test (self ):
try :
print (f"\n===== 执行登录状态下博客详情测试(ID:{self.blog_id} )=====" )
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
list_test = BlogList()
list_test.driver.get(list_test.list_url)
time.sleep(2 )
first_blog = list_test.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div:nth-child(1) > a" )
first_blog.click()
time.sleep(2 )
assert self .driver.title == "博客详情页" , f"当前页面不是详情页,标题:{self.driver.title} "
blog_title = self .driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div > h3" )
assert blog_title.is_displayed(), "博客标题未显示"
publish_date = self .driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div > div.date" )
assert publish_date.is_displayed(), "发布日期未显示"
blog_content = self .driver.find_element(By.CSS_SELECTOR, "#content" )
assert blog_content.is_displayed(), "博客正文未显示"
blog_driver.get_screen_shot()
print ("===== 登录状态下博客详情测试通过 =====" )
except (NoSuchElementException, AssertionError) as e:
print (f"登录状态下博客详情测试失败:{str (e)} " )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"登录状态下博客详情测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def detail_unlogin_status_test (self ):
try :
print (f"\n===== 执行未登录状态下博客详情测试(ID:{self.blog_id} )=====" )
blog_driver.quit_driver()
new_driver = Driver()
self .driver = new_driver.driver
self .driver.get(self .detail_url)
print (f"未登录,直接访问详情页:{self.detail_url} " )
time.sleep(2 )
assert self .driver.current_url == "http://192.168.47.135:8653/blog_system/blog_login.html" ,
f"未跳转至登录页,当前 URL:{self.driver.current_url} "
new_driver.get_screen_shot()
new_driver.quit_driver()
print ("===== 未登录状态下博客详情测试通过 =====" )
except AssertionError as e:
print (f"未登录状态下博客详情测试失败:{str (e)} " )
raise
except Exception as e:
print (f"未登录状态下博客详情测试异常:{str (e)} " )
raise
if __name__ == "__main__" :
detail_test = BlogDetail(blog_id=15 )
detail_test.detail_login_status_test()
detail_test.detail_unlogin_status_test()
4.4 博客编辑模块测试 import time
import datetime
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from common.Utils import blog_driver, Driver
from cases.BlogLogin import BlogLogin
class BlogEdit :
def __init__ (self ):
self .edit_url = "http://192.168.47.135:8653/blog_system/blog_edit.html"
self .driver = blog_driver.driver
print (f"博客编辑页 URL:{self.edit_url} " )
def edit_login_normal_submit_test (self ):
try :
print (f"\n===== 执行登录状态下正常提交博客测试 =====" )
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
self .driver.get(self .edit_url)
time.sleep(2 )
title_input = self .driver.find_element(By.CSS_SELECTOR, "#title" )
content_input = self .driver.find_element(By.CSS_SELECTOR, "#content" )
submit_btn = self .driver.find_element(By.CSS_SELECTOR, "#submit" )
blog_title = f"自动化测试实战_测试博客_{datetime.datetime.now().strftime('%Y%m%d%H%M%S' )} "
blog_content = "这是一篇通过自动化测试脚本提交的博客,用于验证编辑模块的正常提交功能。"
title_input.clear()
title_input.send_keys(blog_title)
content_input.clear()
content_input.send_keys(blog_content)
submit_btn.click()
time.sleep(3 )
assert self .driver.title == "博客列表页" , f"提交后未跳转至列表页,当前标题:{self.driver.title} "
all_blogs = self .driver.find_elements(By.CSS_SELECTOR, "body > div.container > div.right > div > a" )
blog_titles = [blog.text for blog in all_blogs]
assert blog_title in blog_titles, f"新增博客未在列表中显示(标题:{blog_title} )"
blog_driver.get_screen_shot()
print ("===== 登录状态下正常提交博客测试通过 =====" )
except (NoSuchElementException, AssertionError) as e:
print (f"正常提交博客测试失败:{str (e)} " )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"正常提交博客测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def edit_login_no_title_submit_test (self ):
try :
print (f"\n===== 执行登录状态下无标题提交博客测试 =====" )
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
self .driver.get(self .edit_url)
time.sleep(2 )
content_input = self .driver.find_element(By.CSS_SELECTOR, "#content" )
submit_btn = self .driver.find_element(By.CSS_SELECTOR, "#submit" )
blog_content = "这是无标题提交测试的内容,预期提交失败。"
content_input.clear()
content_input.send_keys(blog_content)
submit_btn.click()
time.sleep(1 )
assert self .driver.current_url == self .edit_url, f"无标题提交时页面不应跳转,当前 URL:{self.driver.current_url} "
blog_driver.get_screen_shot()
print ("===== 登录状态下无标题提交博客测试通过 =====" )
except AssertionError as e:
print (f"无标题提交博客测试失败:{str (e)} " )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"无标题提交博客测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def edit_login_no_content_submit_test (self ):
try :
print (f"\n===== 执行登录状态下无内容提交博客测试 =====" )
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
self .driver.get(self .edit_url)
time.sleep(2 )
title_input = self .driver.find_element(By.CSS_SELECTOR, "#title" )
submit_btn = self .driver.find_element(By.CSS_SELECTOR, "#submit" )
blog_title = "无内容提交测试的标题"
title_input.clear()
title_input.send_keys(blog_title)
submit_btn.click()
time.sleep(1 )
assert self .driver.current_url == self .edit_url, f"无内容提交时页面不应跳转,当前 URL:{self.driver.current_url} "
blog_driver.get_screen_shot()
print ("===== 登录状态下无内容提交博客测试通过 =====" )
except AssertionError as e:
print (f"无内容提交博客测试失败:{str (e)} " )
blog_driver.get_screen_shot()
raise
except Exception as e:
print (f"无内容提交博客测试异常:{str (e)} " )
blog_driver.get_screen_shot()
raise
def edit_unlogin_submit_test (self ):
try :
print (f"\n===== 执行未登录状态下提交博客测试 =====" )
blog_driver.quit_driver()
new_driver = Driver()
self .driver = new_driver.driver
self .driver.get(self .edit_url)
time.sleep(2 )
title_input = self .driver.find_element(By.CSS_SELECTOR, "#title" )
content_input = self .driver.find_element(By.CSS_SELECTOR, "#content" )
submit_btn = self .driver.find_element(By.CSS_SELECTOR, "#submit" )
title_input.send_keys("未登录提交测试" )
content_input.send_keys("未登录状态下不应提交成功" )
submit_btn.click()
time.sleep(2 )
assert self .driver.current_url == "http://192.168.47.135:8653/blog_system/blog_login.html" ,
f"未登录提交应跳转至登录页,当前 URL:{self.driver.current_url} "
new_driver.get_screen_shot()
new_driver.quit_driver()
print ("===== 未登录状态下提交博客测试通过 =====" )
except AssertionError as e:
print (f"未登录提交博客测试失败:{str (e)} " )
raise
except Exception as e:
print (f"未登录提交博客测试异常:{str (e)} " )
raise
if __name__ == "__main__" :
edit_test = BlogEdit()
edit_test.edit_login_normal_submit_test()
edit_test.edit_login_no_title_submit_test()
edit_test.edit_login_no_content_submit_test()
edit_test.edit_unlogin_submit_test()
五、测试用例执行入口 为了方便执行所有测试用例,创建一个统一的执行入口文件 RunCases.py,按模块顺序执行测试。
import sys
import time
from common.Utils import blog_driver
from cases.BlogLogin import BlogLogin
from cases.BlogList import BlogList
from cases.BlogDetail import BlogDetail
from cases.BlogEdit import BlogEdit
def run_all_cases ():
print ("=" *50 )
print ("开始执行博客系统自动化测试用例" )
print (f"执行时间:{time.strftime('%Y-%m-%d %H:%M:%S' )} " )
print ("=" *50 )
test_results = {"passed" : 0 , "failed" : 0 , "total" : 0 }
try :
print ("\n" + "=" *30 )
print ("开始执行登录模块测试" )
print ("=" *30 )
login_test = BlogLogin()
login_test.login_suc_test("admin" , "123" )
test_results["passed" ] += 1
login_test.login_suc_test("lisi" , "123" )
test_results["passed" ] += 1
login_test.login_fail_test("admin" , "111" , "用户名或密码错误!" )
test_results["passed" ] += 1
login_test.login_empty_username_test()
test_results["passed" ] += 1
login_test.login_empty_password_test()
test_results["passed" ] += 1
print ("\n" + "=" *30 )
print ("开始执行博客列表模块测试" )
print ("=" *30 )
list_test = BlogList()
list_test.list_login_status_test()
test_results["passed" ] += 1
list_test.list_unlogin_status_test()
test_results["passed" ] += 1
print ("\n" + "=" *30 )
print ("开始执行博客详情模块测试" )
print ("=" *30 )
detail_test = BlogDetail(blog_id=15 )
detail_test.detail_login_status_test()
test_results["passed" ] += 1
detail_test.detail_unlogin_status_test()
test_results["passed" ] += 1
print ("\n" + "=" *30 )
print ("开始执行博客编辑模块测试" )
print ("=" *30 )
edit_test = BlogEdit()
edit_test.edit_login_normal_submit_test()
test_results["passed" ] += 1
edit_test.edit_login_no_title_submit_test()
test_results["passed" ] += 1
edit_test.edit_login_no_content_submit_test()
test_results["passed" ] += 1
edit_test.edit_unlogin_submit_test()
test_results["passed" ] += 1
except Exception as e:
print (f"\n测试执行过程中出现异常:{str (e)} " )
test_results["failed" ] += 1
finally :
test_results["total" ] = test_results["passed" ] + test_results["failed" ]
blog_driver.quit_driver()
print ("\n" + "=" *50 )
print ("博客系统自动化测试执行完成" )
print ("=" *50 )
print (f"总用例数:{test_results['total' ]} " )
print (f"通过用例数:{test_results['passed' ]} " )
print (f"失败用例数:{test_results['failed' ]} " )
pass_rate = (test_results['passed' ] / test_results['total' ]) * 100 if test_results['total' ] > 0 else 100
print (f"测试通过率:{pass_rate:.2 f} %" )
print ("=" *50 )
if test_results["failed" ] > 0 :
sys.exit(1 )
else :
sys.exit(0 )
if __name__ == "__main__" :
run_all_cases()
六、测试报告生成 测试执行完成后,需要生成一份规范的测试报告。以下是基于本次实战的报告模板,可根据实际项目调整。
【测试报告】博客系统 UI 自动化测试报告
1. 报告基本信息 项目名称 博客系统(C++ 后端 Web 项目) 版本号 V1.0 发布类型 分级发布 测试负责人 [测试负责人] 测试完成日期 [当前日期] 联系方式 [联系方式] 评审人 [评审人员] 批准人 [批准人]
2. 项目背景
2.1 测试目标及测试任务概括 测试目标 :验证博客系统核心功能(登录、列表、详情、编辑)的正确性和稳定性,实现关键流程自动化,减少手动测试成本。测试任务 :设计并执行 UI 自动化测试用例,覆盖正常场景与异常场景,生成测试报告并跟踪问题修复。
2.2 被测系统及相关信息 被测系统:博客系统(Web 端);系统地址:[系统地址];依赖环境:Chrome 浏览器 110+、Python 3.8+、Selenium 4.10.0。
3. 测试安排 模块 子模块 前端开发 后端开发 提测时间 测试负责人 进度 备注 登录模块 登录功能 [开发人员] [开发人员] [日期] [负责人] 测试完成 覆盖正常/异常登录 博客列表模块 列表展示、跳转 [开发人员] [开发人员] [日期] [负责人] 测试完成 登录/未登录状态 博客详情模块 详情展示 [开发人员] [开发人员] [日期] [负责人] 测试完成 登录/未登录状态 博客编辑模块 编辑、提交 [开发人员] [开发人员] [日期] [负责人] 测试完成 正常/异常提交
4. 测试结果汇总
4.1 测试用例执行情况 模块 用例总数 通过数 失败数 通过率 登录模块 5 5 0 100.00% 博客列表模块 2 2 0 100.00% 博客详情模块 2 2 0 100.00% 博客编辑模块 5 5 0 100.00% 总计 14 14 0 100.00%
4.2 缺陷统计与分析 本次自动化测试未发现新增缺陷;历史缺陷修复验证:所有已提交的缺陷均已修复,且在本次自动化测试中无回归。
4.3 截图示例 测试场景 截图路径 说明 admin 账号正常登录成功 images/[日期]/loginSucTest-[时间].png 跳转至列表页,显示博主头像 密码错误异常登录 images/[日期]/loginFailTest-[时间].png 显示'用户名或密码错误!' 博客列表页正常展示 images/[日期]/listLoginStatusTest-[时间].png 博客数量大于 10 篇 编辑博客正常提交 images/[日期]/editLoginNormalSubmitTest-[时间].png 新增博客显示在列表页
5. 测试结论与建议
5.1 测试结论 博客系统核心功能(登录、列表、详情、编辑)的 UI 自动化测试已全部完成,14 条用例全部通过,通过率 100%;系统在测试场景下运行稳定,未出现功能异常、崩溃等问题;自动化测试框架运行正常,能够准确执行测试用例、捕获异常并生成截图,可支撑后续迭代的回归测试。
5.2 后续建议 扩展用例覆盖范围:新增博客删除、修改密码、评论等功能的自动化用例;集成 CI/CD 流程:将自动化测试脚本集成到 Jenkins 等工具,实现每次代码提交后自动执行测试;优化框架稳定性:增加重试机制(如元素未找到时自动重试)、日志详细程度优化;定期维护用例:当系统 UI 发生变更时,及时更新用例中的元素选择器,确保自动化用例的有效性。
相关免费在线工具 curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online