- 1)项目背景
- 2)项目功能介绍
- 登陆
- 写博客/编辑已存在博客
- 删除博客
- 注销
- 2)基于项目功能设计相关测试用例
- 3)基于测试用例编写自动化测试
- 准备工作
- 登陆界面相关
- 博客首页相关
- 博客详情页相关
- 编辑博客相关
- 删除博客相关
- 注销相关
- 4)基于个人博客系统的性能测试
- 准备工作
- 性能测试报告
项目背景
随着自媒体行业快速发展,个人创作者对博客发布平台的需求日益多元化,越来越多的用户需要用到博客来记录学习的过程,以及把个人的心得写成技术博客分享出来供大家学习和参考,又或者把博客当成自己学习中的日记,总之博客对于现在的互联网用户来说,博客是一个于学习、参考、记录方面不可或缺的平台,本项目简单来说就是博客平台的精简版。
1.本项目个人博客系统采用前后端分离的方法来实现,同时使用了数据库来存储相关的数据,同时将其部署到云服务器上。前端主要有四个页面构成:登录页、博客首页、博客详情页以及博客编辑页,以上模拟实现了最精简的个人博客系统。
2.该个人博客系统主要实现个人用户简单的博客记录,时间、标题、内容以及发布者等都可以进行详细地查看。
项目功能介绍
该个人博客系统主要实现了以下几个功能:登录、写博客/编辑已存在博客、删除博客、注销等功能
登陆
写博客/编辑已存在博客
删除博客
注销
基于项目功能设计相关测试用例
基于测试用例编写自动化测试
该项目由Selenium库进行测试web自动化测试,使用语言为Python。
准备工作
Selenium是广泛使用的模拟浏览器运行的库,它是一个用于Web应用程序测试的工具。 Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,并且支持大多数现代 Web 浏览器。
先安装好Python以及IDE(Pycharm),打开Pycharm软件,在终端中使用pip命令安装浏览器驱动管理,命令为pip insatll webdriver-manager
,安装好之后继续安装Selenium库,命令为pip insatll selenium==4.0.0
创建并初始化浏览器驱动,因为在运行每个自动化测试用例之前都需要进行创建浏览器驱动,运行所有的测试方法结束之后需要释放浏览器驱动,所以创建一个类来初始化浏览器驱动和释放浏览器驱动,这个类用单例模式,只提供一个对象供其他测试方法使用,另外写一个截图方法来实时查看测试中出现的情况
import sys
import os.path
from datetime import datetimefrom selenium import webdriver
from selenium.webdriver.edge.options import Options
from selenium.webdriver.edge.service import Service
from webdriver_manager.microsoft import EdgeChromiumDriverManager# 创建一个浏览器对象
class Driver:driver = ""def __init__(self):options = Options()self.driver = webdriver.Edge(service=Service(EdgeChromiumDriverManager().install()),options=options)self.driver.implicitly_wait(7)def GetScreenShot(self):# 创建屏幕截图# 截图的路径:../images/2025-07-11/2025-07-11-140735.pngdirname = datetime.now().strftime("%Y-%m-%d")# 如果不存在当天的截图存放路径文件就创建if not os.path.exists("../images/"+dirname):os.mkdir("../images/"+dirname)# 截图的名称:2025-07-11-140735.pngfilename = sys._getframe().f_back.f_code.co_name+"-"+datetime.now().strftime("%Y-%m-%d-%H%M%S"+".png")self.driver.save_screenshot("../images/"+dirname+"/"+filename)#单例模式创建一个驱动对象供所有测试使用
BlogDriver = Driver()
登陆界面相关
import time
from selenium.webdriver.common.by import By
from Common.Utils import BlogDriver#博客登陆测试
class BlogLogin:driver = ""url = ""def __init__(self):self.driver = BlogDriver.driverself.url = "http://8.137.19.140:9090/blog_login.html"self.driver.get(self.url)#正确登陆的测试用例#输入正确的账号和密码def LoginSucTest(self):self.driver.find_element(By.CSS_SELECTOR,"#username").clear()self.driver.find_element(By.CSS_SELECTOR,"#password").clear()self.driver.find_element(By.CSS_SELECTOR,"#username").send_keys("lisi")self.driver.find_element(By.CSS_SELECTOR,"#password").send_keys("123456")self.driver.find_element(By.CSS_SELECTOR,"#submit").click()time.sleep(3)#登陆后页面能找到昵称就是成功登陆,否则登陆失败self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.left > div > h3")# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# #返回登陆页面# self.driver.back()# time.sleep(5)# self.driver.quit()# 异常登陆的测试案例def LoginFailTest(self):# 输入正确的账号和错误的密码#连续多次send_keys会出现关键词拼接的现象,而不是直接替换,如果想重新在输入框中输入内容,需要先清空该输入框self.driver.find_element(By.CSS_SELECTOR,"#username").clear()self.driver.find_element(By.CSS_SELECTOR,"#username").send_keys("lisi")#输入错误的密码self.driver.find_element(By.CSS_SELECTOR,"#password").clear()self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")self.driver.find_element(By.CSS_SELECTOR, "#submit").click()#出现警告弹窗 账号或密码错误time.sleep(1)alert = self.driver.switch_to.alertalert_text = alert.text #保存弹窗文本信息以此来判断是否登陆成功alert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()#检查是否符合预期assert alert_text == "密码错误"# 返回登陆页面,再测试下一种情况# 输入错误的账号和正确的密码self.driver.find_element(By.CSS_SELECTOR,"#username").clear()self.driver.find_element(By.CSS_SELECTOR,"#username").send_keys("wangwu")#输入正确的密码self.driver.find_element(By.CSS_SELECTOR,"#password").clear()self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123456")self.driver.find_element(By.CSS_SELECTOR, "#submit").click()#出现警告弹窗 账号或密码错误time.sleep(1)alert = self.driver.switch_to.alertalert_text = alert.text # 保存弹窗文本信息以此来判断是否登陆成功alert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 检查是否符合预期assert alert_text == "用户不存在"# 输入错误的账号和错误的密码self.driver.find_element(By.CSS_SELECTOR, "#username").clear()self.driver.find_element(By.CSS_SELECTOR, "#username").send_keys("wangwu")# 输入错误的密码self.driver.find_element(By.CSS_SELECTOR, "#password").clear()self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")self.driver.find_element(By.CSS_SELECTOR, "#submit").click()# 出现警告弹窗 账号或密码错误time.sleep(1)alert = self.driver.switch_to.alertalert_text = alert.text #保存弹窗文本信息以此来判断是否登陆成功alert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 检查是否符合预期assert alert_text == "用户不存在"# 账号为空,密码随便写# 账号随便写,密码为空# 两种情况都是一样的,合并为一个测试self.driver.find_element(By.CSS_SELECTOR, "#username").clear()self.driver.find_element(By.CSS_SELECTOR, "#password").clear()self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")self.driver.find_element(By.CSS_SELECTOR, "#submit").click()# 出现警告弹窗 账号或密码为空time.sleep(1)alert = self.driver.switch_to.alertalert_text = alert.text #保存弹窗文本信息以此来判断是否登陆成功alert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 检查是否符合预期assert alert_text == "账号或密码不能为空"# 账号和密码都为空self.driver.find_element(By.CSS_SELECTOR, "#username").clear()self.driver.find_element(By.CSS_SELECTOR, "#password").clear()self.driver.find_element(By.CSS_SELECTOR, "#submit").click()# 出现警告弹窗 账号或密码为空time.sleep(1)alert = self.driver.switch_to.alertalert_text = alert.text #保存弹窗文本信息以此来判断是否登陆成功alert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 检查是否符合预期assert alert_text == "账号或密码不能为空"# self.driver.quit()# login = BlogLogin()
# login.LoginFailTest()
# login.LoginSucTest()
博客首页相关
import time
from selenium.webdriver.common.by import By
from Common.Utils import BlogDriver# 博客列表测试
class BlogList:driver = ""url = ""def __init__(self):self.driver=BlogDriver.driverself.url = "http://8.137.19.140:9090/blog_list.html"self.driver.get(self.url)#测试首页---登陆状态下def ListTestByLogin(self):# 测试个人信息# 头像、昵称、文章、分类是否存在#检查头像是否存在self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.left > div > img")#检查昵称是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > h3")#检查github地址是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > a")#检查文章是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > div:nth-child(4) > span:nth-child(1)")#检查分类是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > div:nth-child(4) > span:nth-child(2)")# 测试博客列表#检查博客标题是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div:nth-child(3) > div.title")#检查博客发布时间是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div:nth-child(3) > div.date")#检查博客内容是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div:nth-child(3) > div.desc")#检查"查看全文"按钮是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.right > div:nth-child(3) > a")# 测试菜单栏#检查主页按钮是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.nav > a:nth-child(4)")#检查写博客按钮是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.nav > a:nth-child(5)")#检查注销按钮是否存在self.driver.find_element(By.CSS_SELECTOR, "body > div.nav > a:nth-child(6)")# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# BlogDriver.driver.quit()# 测试首页---未登陆状态下# 未登录状态下打开博客首页会跳转到登陆界面# 根据网页来判断def ListTestByUnlogin(self):self.driver.back()# 访问博客首页urlself.driver.get(self.url)time.sleep(2)# 获取当前url,看看是否跳转到了登录页cur_url = self.driver.current_urlprint(cur_url)# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 检查是否未登录assert cur_url == "http://8.137.19.140:9090/blog_list.html"# time.sleep(3)# self.driver.quit()# BlogList=BlogList()
# BlogList.ListTestByLogin()
# BlogList.ListTestByUnlogin()
博客详情页相关
import time
from selenium.webdriver.common.by import By
from Common.Utils import BlogDriver# 博客详情页测试
class BlogDetail:driver = ""url = ""def __init__(self):self.driver=BlogDriver.driverself.url = "http://8.137.19.140:9090/blog_detail.html?blogId=116661"self.driver.get(self.url)# 博客详情页测试 --- 登陆状态下def DetailTestByLogin(self):# 检查博客标题self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.title")# 检查博客发布时间self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.date")# 检查博客内容self.driver.find_element(By.CSS_SELECTOR,"#detail > p")# 检查编辑博客按钮是否存在self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.operating > button:nth-child(1)")# 检查删除博客按钮是否存在self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.operating > button:nth-child(2)")# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 博客详情页测试 --- 未登陆状态下# 直接跳转到登陆界面def DetailTestByUnLogin(self):# 访问博客详情页urlself.driver.get(self.url)time.sleep(2)# 获取当前url,看看是否跳转到了登录页cur_url = self.driver.current_urlprint(cur_url)# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 检查是否未登录assert cur_url == "http://8.137.19.140:9090/blog_detail.html?blogId=116646"# BlogDetail = BlogDetail()
# BlogDetail.DetailTestByLogin()
# BlogDetail.DetailTestByUnLogin()
编辑博客相关
import time
from selenium.webdriver.common.by import By
from Common.Utils import BlogDriver# 博客编辑页测试
class BlogEdit:driver = ""url = ""def __init__(self):self.driver=BlogDriver.driverself.url = "http://8.137.19.140:9090/blog_edit.html"self.driver.get(self.url)#博客编辑页测试 --- 登陆状态下正常发布博客def NormalEditTestByLogin(self):# self.driver.find_element(By.CSS_SELECTOR, "body > div.nav > a:nth-child(5)").click()# 检查博客标题栏,并填写标题self.driver.find_element(By.CSS_SELECTOR,"#title").send_keys("这是一个测试")# 检查博客输入内容区域# 找到编辑区域,输入博客内容(编辑区域不可操作)# 菜单栏元素无法定位# 博客系统的编辑内容区域默认就不为空,可以暂时不做处理# 直接点击发布按钮发布博客self.driver.find_element(By.CSS_SELECTOR, "#submit").click()# 检查已发布博客是否存在博客首页blog_title= self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div:nth-child(4) > div.title").textprint(blog_title)assert blog_title == "这是一个测试"# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()#博客编辑页测试 --- 登陆状态下异常发布博客def NotNormalEditTestByLogin(self):# 博客标题和内容都不输入,直接点击发布按钮发布博客self.driver.find_element(By.CSS_SELECTOR, "#submit").click()# 出现警告弹窗无法提交,页面依然是博客编辑页面time.sleep(2)alert = self.driver.switch_to.alertalert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 获取当前页面url,判断是否还在博客编辑页面cur_url = self.driver.current_urlassert cur_url == self.url#博客编辑页测试 --- 未登陆状态下正常发布博客# 点击提交按钮会直接跳转到登陆页面def NormalEditTestByUnLogin(self):# 检查博客标题栏,并填写标题self.driver.find_element(By.CSS_SELECTOR, "#title").send_keys("这是一个测试2")# 检查博客输入内容区域# 找到编辑区域,输入博客内容(编辑区域不可操作)# 菜单栏元素无法定位# 博客系统的编辑内容区域默认就不为空,可以暂时不做处理# 直接点击发布按钮发布博客self.driver.find_element(By.CSS_SELECTOR, "#submit").click()time.sleep(2)# 获取当前页面url,判断是否会直接跳转到博客登陆页面# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()cur_url = self.driver.current_urlprint(cur_url)assert cur_url == "http://8.137.19.140:9090/blog_login.html"#博客编辑页测试 --- 未登陆状态下异常发布博客# 点击提交按钮也是会直接跳转到登陆页面def NotNormalEditTestByUnLogin(self):# 博客标题和内容都不输入,直接点击发布按钮发布博客self.driver.find_element(By.CSS_SELECTOR, "#submit").click()time.sleep(2)# 获取当前页面url,判断是否会直接跳转到博客登陆页面# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()cur_url = self.driver.current_urlprint(cur_url)assert cur_url == "http://8.137.19.140:9090/blog_login.html"# BlogEdit = BlogEdit()
# BlogEdit.NormalEditTestByLogin()
# BlogEdit.NotNormalEditTestByLogin()
删除博客相关
import time
from selenium.webdriver.common.by import By
from Common.Utils import BlogDriver# 删除博客测试
class BlogDel:driver = ""url = ""def __init__(self):self.driver=BlogDriver.driverself.url = "http://8.137.19.140:9090/blog_detail.html?blogId=116665"self.driver.get(self.url)# 删除博客测试 --- 登陆状态下def BlogDelByLogin(self):# 检查博客标题self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.title")# 检查博客发布时间self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.date")# 检查博客内容self.driver.find_element(By.CSS_SELECTOR,"#h2-u5728u8FD9u91CCu5199u4E0Bu4E00u7BC7u535Au5BA2")# 检查编辑博客按钮是否存在self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.operating > button:nth-child(1)")# 检查删除博客按钮是否存在self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.operating > button:nth-child(2)")# 找到删除按钮 点击删除后,出现警告弹窗,确认删除后,返回博客列表self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.operating > button:nth-child(2)").click()alert = self.driver.switch_to.alert# 取消删除,页面依然是博客编辑页面alert.dismiss()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 获取当前页面urlcur_url1 = self.driver.current_urlassert cur_url1 == self.url# 确认删除,页面跳转为博客列表页self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div > div.operating > button:nth-child(2)").click()alert = self.driver.switch_to.alertalert.accept()# 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 获取当前页面urlcur_url2 = self.driver.current_urlassert cur_url2 == self.urlprint("123")# 删除博客测试 --- 未登陆状态下# 直接跳转到登陆界面def BlogDelByUnLogin(self):time.sleep(2)# 获取当前页面urlcur_url = self.driver.current_urlprint(cur_url)# 检查是否跳转到登陆页面assert cur_url == "http://8.137.19.140:9090/blog_login.html"# BlogDel = BlogDel()
# BlogDel.BlogDelByLogin()
注销相关
import timefrom selenium.webdriver.common.by import Byfrom Common.Utils import BlogDriver# 注销按钮测试
class ExitBlog:driver = ""url = ""def __init__(self):self.driver=BlogDriver.driverself.url = "http://8.137.19.140:9090/blog_list.html"self.driver.get(self.url)# 对注销按钮进行测试 --- 登陆状态下def ExitBlogTest(self):# 找到注销按钮并点击self.driver.find_element(By.CSS_SELECTOR,"body > div.nav > a:nth-child(6)").click()time.sleep(2)# # 添加屏幕截图来实时查看当时的场景BlogDriver.GetScreenShot()# 获取当前页面urlcur_url = self.driver.current_urlprint(cur_url)# 判断是否跳转到登陆页面assert cur_url == "http://8.137.19.140:9090/blog_login.html"# ExitBlog = ExitBlog()
# ExitBlog.ExitBlogTest()
另外创建一个文件专门用来执行脚本、以及浏览器驱动的退出
from Common.Utils import BlogDriver
from Tests.BlogDel import BlogDel
from Tests.BlogDetail import BlogDetail
from Tests.BlogEdit import BlogEdit
from Tests.BlogList import BlogList
from Tests.BlogLogin import BlogLogin
from Tests.ExitBlog import ExitBlogif __name__ == "__main__":BlogLogin().LoginFailTest()# BlogLogin().LoginSucTest()# 登陆成功状态下,进行博客首页的测试# BlogList().ListTestByLogin()# 未登陆状态下,进行博客首页的测试# BlogList().ListTestByUnlogin()# 登陆成功状态下,进行博客详情页的测试# BlogDetail().DetailTestByLogin()# 未登陆状态下,进行博客详情页的测试# BlogDetail().DetailTestByUnLogin()# 登陆成功状态下,进行博客编辑页正常发布的测试# BlogEdit().NormalEditTestByLogin()# 登陆成功状态下,进行博客编辑页异常发布的测试# BlogEdit().NotNormalEditTestByLogin()# 未登陆状态下,进行博客编辑页正常发布的测试# BlogEdit().NormalEditTestByUnLogin()# 未登陆状态下,进行博客编辑页异常发布的测试# BlogEdit().NotNormalEditTestByUnLogin()# 登陆成功状态下,进行博客删除页面的测试包含(取消删除和确认删除)# BlogDel().BlogDelByLogin()# 未登陆状态下,进行博客删除页面测试会直接跳转到登陆页面# BlogDel().BlogDelByUnLogin()# 登陆成功状态下,测试点击注销按钮后是否会跳转到登陆页面# ExitBlog().ExitBlogTest()# 最后程序统一退出BlogDriver.driver.quit()
基于个人博客系统的性能测试
性能测试的目的是确保软件系统在实际运行中具备良好的响应速度、稳定性、可扩展性和资源利用率,从而满足业务需求和用户期望,支撑系统的长期稳定运行。
准备工作
安装好Java以及jmeter工具,jmeter需要下载插件功能,下载网址为https://jmeter-plugins.org/install/Install/
,下载好之后,进入jmeter安装Custom Thread Groups和Page DataExtractor插件。
性能测试报告
JMeter测试报告是⼀个全⾯⽽详细的⽂档,它提供了关于测试执⾏结果的详细信息,帮助⽤⼾全⾯评 估系统的性能并进⾏性能优化。
⽣成性能测试报告命令:在终端执行命令 Jmeter -n -t 脚本⽂件 -l ⽇志⽂件 -e -o ⽬录
-n : ⽆图形化运⾏
-t : 被运⾏的脚本
-l : 将运⾏信息写⼊⽇志⽂件,后缀为 jtl 的⽇志⽂件
-e : ⽣成测试报告
-o : 指定报告输出⽬录
本项目性能测试报告如下:
性能分析主要几个方面:
1)响应时间:如果相应时间超过了要求,代表性能到达了瓶颈
2)错误率:检查高并发场景下,系统是否能够正常处理业务
3)吞吐量:吞吐量越⼤,性能越好;吞吐量相对稳定或者变低,可能系统达到了性能瓶颈