目录
2.2 使用Selenium进行Web自动化测试(Python)
2.2.1 安装WebDriverManager驱动管理程序和selenium 类库
1.项目背景
基于jQuery框架来实现的个人博客系统,由五个类构成:用户登录(BlogLogin.py)、博客列表(BlogList)、博客编辑(BlogEdit)、博客详情(BlogDetail)、博客运行测试(RunTest.py)。登录即可查看自己与其他用户已发布的博客,也可以使用自己的账号发布博客,通过使用Selenium定位web元素、对获取到的元素进行操作等,对个人博客系统进行测试。
该博客系统的测试核心包括用户登录、博客列表展示、用户信息验证、博客数量统计、查看全文功能、详情页内容显示、写博客、删除博客、编辑并发布博客以及退出账号等功能。此系统支持发布个人博客,并记录博客的发布日期、时间、标题及发布者信息。
2.项目简介
2.1 功能测试
2.1.1测试用例思维导图
2.1.2 执行测试用例
1.登录测试
(1)概况
用户名和密码已存储在数据库中,登录成功后会自动跳转到博客列表页;当用户点击“注销”按钮时,将会自动重定向至登录页面。
(2)测试用例展示
(a)界面
(b) 输入正确的账号和密码(账号:lisi或Zhangsan,密码:123456)
预期结果:跳转到博客列表页
实际结果展示:
(c) 输出错误的账号
实际结果展示:
输出错误的账号
实际结果展示:
2. 博客列表页测试
(1)概况
登录成功后,系统将自动跳转至博客列表页面。在此页面中,用户能够查看多项信息:当前已发布的博客数量、用户的个人头像与用户名。此外,还能浏览到所发布博客的部分概要信息,包括每篇博客的标题、发布时间以及相关内容的简短介绍。这一设计便于用户快速了解和管理自己的博客动态。
(2)测试用例展示
(a)列表页数量与分类显示
3.博客详情页
(1)概况
选择任意一篇博客并点击“查看全文”按钮后,您将会进入博客的详情页面,在此可以完整阅读该篇博客的所有内容。如果您查看的是自己发布的博客,则拥有对该文章进行“编辑”和“删除”的权限;若博客是由其他用户发布的,则您对该篇文章仅有“只读”访问权限,无法进行编辑或删除操作。这种设置确保了内容管理的安全性和版权的尊重。
(2)测试用例展示
(a)详情页界面
①其他用户详情页界面展示
预期结果:显示标题和内容,没有”编辑“和”删除“按钮
实际结果展示:
②当前用户详情页界面展示
预期结果:显示标题和内容,有“编辑”和“删除”按钮
实际结果展示:
4.博客编辑与发布
(1)概况
(a)在博客列表页的右上角点击“写博客”,便可进入博客编辑页面,这里可以开始撰写新的博客内容。
(2)测试用例展示
(a)登录成功之后跳转到博客列表页
(b)点击”写博客“按钮,跳转到博客的编辑页
(c)输入标题和内容
预期结果:标题与内容均不能为空,且输入的字符必须合法。
实际结果展示:
(d) 点击”发布文章“按钮
预期结果:博客成功发布,并跳转到博客列表页,最后一篇博客即为最新发布的文章,显示其标题、发布时间及部分内容(如果博客内容较长,则仅显示部分内容)。
实际结果展示:
5.删除博客
(1)概况
在博客列表页中,点击任意一篇由当前账号发布的博客的“查看全文”按钮,进入博客详情页。然后,在博客详情页点击“删除”按钮,该篇博客将被删除,并自动跳转回博客列表页,此时被删除的博客不再显示在列表中。
(2)测试用例展示
(a)列表页界面展示(要删除的博客)
(b)点击”查看全文“按钮,进入博客详情页
(c)点击”删除“按钮
预期结果:删除成功,跳转到博客列表页,被删除文章不存在
实际结果:可以看到已经删除了
6.退出当前账号
(1)概况
在博客列表页点击“退出”按钮后,系统将跳转至登录界面,此时账号和密码输入框会被清空。用户可以在此界面正常地重新输入信息进行登录。
(2)测试用例展示
(a) 列表页
(b)点击右上角的”退出“按钮
预期结果:可退出当前账号,跳转到登录界面,登录界面的账号和密码输入框数据被清空
实际结果:
2.2 使用Selenium进行Web自动化测试(Python)
2.2.1 安装WebDriverManager驱动管理程序和selenium 类库
WebDriverManager是一款专为自动化测试设计的工具,用于管理Web驱动程序。在使用Selenium进行测试时,需配备与浏览器版本相匹配的驱动程序以实现对浏览器的操作。WebDriverManager能自动检测系统内已安装的浏览器,并自动下载和配置相应的驱动程序(例如ChromeDriver、FirefoxDriver等)。这种方式省去了手动下载和设置驱动程序的复杂步骤,提升了自动化测试的效率与稳定性,使得在自动化测试中使用各种浏览器变得更加简便。
2.2.2 新建项目
在项目中点击File->Settings进入界面,查看“Project:当前项目名”中是否存在selenium和webdriver-manager两个包。
2.2.3 参照测试用例,编写自动化测试脚本
请求URL访问对应的页面,进入到对应的页面之后,才可以执行一系列的测试用例。浏览器对象是每个页面都会调用的(多次创建消耗性能),所以把创建浏览器对象单独拿出来放到一个文件中,这里使用Until.py 文件,用来生成测试文件中需要用到的配置内容。有时候我们想要知道每次运行结束前的界面是什么情况,就可以使用屏幕截图来保存当时的情况。
①首先创建一个类(Driver)
②定义一个类成员和两个构造函数(一个函数是存放创建的浏览器对象与其他常用浏览器相关参数设置,一个函数是屏幕截图)
import datetime
import os.path
import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
#创建一个浏览器对象
class Driver:
driver = ""
def __init__(self):
options = webdriver.ChromeOptions()
self.driver = webdriver.Chrome(executable_path='C:\\Users\\zzc\\AppData\\Local\\Programs\\Python\\Python39\\Scripts\\chromedriver.exe')
#self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=options)
self.driver.implicitly_wait(4)
def getScreenShot(self):
#创建屏幕截图
# 图片文件名称:./2024-05-08-173456.png
dirname=datetime.datetime.now().strftime("%Y-%m-%d")
#判断dirname文件夹是否已经存在,若不存在则创建文件夹
# ../images/2024-05-08
if not os.path.exists("../images/"+dirname):
os.mkdir("../images/"+dirname)
#2024-05-08-173456.png
#图片路径:../images/调用方法-2024-05-08/2024-05-08-173456.png
#图片路径:../images/LoginSucTest-2024-05-08/2024-05-08-173456.png
#图片路径:../images/LoginFailTest-2024-05-08/2024-05-08-173456.png
filename= sys._getframe().f_back.f_code.co_name+"-"+datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S")+".png"
self.driver.save_screenshot("../images/"+dirname+"/"+filename)
# 创建Driver类的实例
BlogDriver=Driver()
2.创建一个运行文件(程序的主入口 ),运行各个测试类中的函数
①文件名为:RunTest.py
from common.Utils import BlogDriver
if __name__ == "__main__":
3.博客“登录”自动化测试
- 创建名为BlogLogin.py的新文件用于博客登录测试。
- 导入必要的模块和工具函数,包括从Until文件中获取浏览器实例的方法。
- 在BlogLogin.py中定义一个名为BlogLogin的类,封装博客登录相关的测试用例。
- 在该类中实现LoginSucTest方法测试正常登录流程,及LoginFailTest方法测试异常登录情况,并确保每次登录尝试前清空输入框内容。
- 自动化测试主要检查页面能否正常加载以及不同情境下登录功能的表现是否符合预期。
- 在RunTest.py文件中指定BlogLogin类内各测试方法的执行顺序,以逻辑顺序运行测试案例。
- 确保整个测试过程能够验证博客系统的登录功能在各种情况下的稳定性和正确性
import time
from selenium.webdriver.common.by import By
from common.Utils import BlogDriver
# 测试博客登录页面
class BlogLogin:
url = ""
driver = ""
def __init__(self):
self.url = "http://8.137.19.140:9090/blog_login.html"
self.driver = BlogDriver.driver
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("zhangsan")
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123456")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
# 能找到博客首页用户的昵称,说明登录成功,否则登录失败
self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > h3")
# 添加屏幕截图
BlogDriver.getScreenShot()
self.driver.back()
# 异常登陆的测试用例
def LoginFailTest(self):
# 若连续多次的send_keys则会出现关键词拼接,而不是替换。若要替换需要先clear
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("zhangsan")
# 错误的密码
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
# 检查登录失败
'''
弹窗直接使用css选择器是拿不到的,需要切换到弹窗
'''
# 代码执行太快,但是弹窗还没出来,所以加一个强制等待
time.sleep(3)
alter_ = self.driver.switch_to.alert
# actual = self.driver.find_element(By.CSS_SELECTOR, "body").text
'''获取弹窗的文本内容'''
actual = alter_.text
# 添加屏幕截图
'''屏幕截图需要重新写一下,当存在弹窗的时候,直接只用selenium的屏幕截图会报错,应该换其其他框架的屏幕截图'''
# BlogDriver.getScreenShot()
# 断言一下
assert actual=="密码错误"
# 关闭弹窗
alter_.accept()
# self.driver.back()
login = BlogLogin()
# zhushi
# login.LoginSucTest()
# login.LoginFailTest()
执行结果如下:
4.”博客列表页及博客列表中数量“自动化测试
- 新建一个名为
BlogList.py
的文件,用于存放博客列表页面的自动化测试代码。- 在
BlogList.py
文件中引入必要的依赖库和工具函数,例如通过Until
文件来获取浏览器操作对象。- 创建一个名为
BlogList
的测试类,用于封装与博客列表页面相关的所有测试逻辑。- 定义两个方法于
BlogList
类中:一个用于模拟登录成功后访问博客列表的情景,另一个模拟未登录状态下的访问情况。- 这些方法需要验证博客标题、内容、按钮等元素是否正确显示,并检查博客数量是否为零。
- 最后,在
RunTest.py
文件里设定各测试方法的执行顺序,确保按计划进行测试。
#博客首页测试用例
import time
from selenium.webdriver.common.by import By
from common.Utils import BlogDriver
#博客首页测试用例
class BlogList:
url=""
driver=""
def __init__(self):
self.url = "http://8.137.19.140:9090/blog_list.html"
self.driver = BlogDriver.driver
self.driver.get(self.url)
#测试首页(登录情况下)
def ListTestByLogin(self):
#测试博客标题是否存在
self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div:nth-child(1) > div.title")
#测试博客内容是否存在
self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div:nth-child(1) > div.desc")
#测试博客按钮是否存在
self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div:nth-child(1) > a")
#个人信息-检查昵称是否存在
self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.left > div > h3")
time.sleep(2)
# 检查博客数量是否为0
text = self.driver.find_element(By.CSS_SELECTOR, "body > div.container > div.left > div > div:nth-child(5)").text
print(text)
# 断言 -- 如果元素不为0,即测试通过
assert text != "0"
#添加屏幕截图
BlogDriver.getScreenShot()
#测试首页(未登录情况下)
self.driver.back()
self.driver.find_element(By.CSS_SELECTOR, "#userName").clear()
self.driver.find_element(By.CSS_SELECTOR, "#password").clear()
text = self.driver.find_element("body > div.container > div.right > div:nth-child(1) > div.desc").text()
RunTest.py
import time
from common.Utils import BlogDriver
from tests import BlogLogin, BlogList, BlogDetail, BlogEdit
if __name__ == "__main__":
BlogLogin.BlogLogin().LoginFailTest()
# 上面的弹窗没有处理
BlogLogin.BlogLogin().LoginSucTest()
# #登录成功之后就可以调用博客首页测试首页的用例(登录状态)
BlogList.BlogList().ListTestByLogin()
BlogDriver.driver.quit()
登录状态下博客列表页“测试结果:
”未登录状态下博客列表页“测试结果:
这个错误通常是由于提供的元素定位器无效或格式不正确,导致Selenium无法找到对应的页面元素。
5.”博客详情页(点击“查看全文”按钮)“自动化测试
① 创建一个名为 BlogDetail.py
的新文件,用于博客详情页的自动化测试。
② 在 BlogDetail.py
文件中导入必要的依赖库和工具函数,比如通过 Until
文件来获取浏览器实例。
③ 定义一个名为 BlogDetail
的测试类,用于包含所有关于博客详情页面的测试逻辑。
④ 在 BlogDetail
类中编写一个测试方法,该方法模拟用户登录状态下访问博客详情页的情况,并进行相关测试。
⑤ 该测试主要检查页面是否正确显示,以及点击“查看全文”按钮后能否正常跳转。
⑥ 在 RunTest.py
文件中设定各个测试方法的执行顺序,确保按照预定计划运行所有测试。
“登录状态下的博客详情页”测试:
import time
from selenium.webdriver.common.by import By
from common.Utils import BlogDriver
class BLogDetail:
url=""
driver =""
def __init__(self):
self.url = "http://8.137.19.140:9090/blog_detail.html?blogId=14619"
self.driver = BlogDriver.driver
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")
#屏幕截图
time.sleep(4)
alter_ = self.driver.switch_to.alert
'''获取弹窗的文本内容'''
actual = alter_.text
# 关闭弹窗
alter_.accept()
BlogDriver.getScreenShot()
RunTest.py
import time
from common.Utils import BlogDriver
from tests import BlogLogin, BlogList, BlogDetail, BlogEdit
if __name__ == "__main__":
BlogLogin.BlogLogin().LoginFailTest()
# 上面的弹窗没有处理
BlogLogin.BlogLogin().LoginSucTest()
# #登录成功之后就可以调用博客首页测试首页的用例(登录状态)
BlogList.BlogList().ListTestByLogin()
# BlogList.BlogList().NotLoginListTest()
BlogDetail.BLogDetail().DetailTestByLogin()
# #测试登陆状态下的博客详情页
BlogDriver.driver.quit()
“登录状态下的博客详情页”测试结果:
6.”博客的编辑与发布“自动化测试
- 创建一个名为
BlogEdit.py
的新测试文件,专门用于博客编辑页面的自动化测试。- 在
BlogEdit.py
文件中导入必要的依赖库和工具函数,包括通过Until
文件获取浏览器实例的方法。- 定义一个名为
BlogEdit
的测试类,该类将包含所有关于博客编辑与发布的测试逻辑。- 在
BlogEdit
类中编写测试方法,模拟用户登录状态下进行博客的编辑与发布流程,并验证这些操作的正确性。- 测试内容集中在检查页面显示是否正常、从列表页点击“写博客”按钮能否正确跳转至编辑页面,以及完成博客编辑后,点击“发布博客”按钮是否能成功发布博客。
- 在
RunTest.py
文件里设定各测试方法的执行顺序,确保按照设计的逻辑流程依次执行各个测试案例。
#测试博客编辑页面
from selenium.webdriver.common.by import By
from common.Utils import BlogDriver
class BlogEdit:
url = ""
driver = ""
def __init(self):
self.url="http://8.137.19.140:9090/blog_edit.html"
self.driver = BlogDriver.driver
self.driver.get(self.url)
#正确发布博客(登陆状态下)
def EditSucTestByLogin(self):
self.driver.find_element(By.CSS_SELECTOR,"#title").send_keys("自动化测试创建")
# 找到编辑区域,输入关键词(编辑区域不可操作)
# 菜单栏无法元素无法定位
# 博客系统编辑区域默认情况下就不为空,可以暂不处理
self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
# 点击完成之后出现页面的跳转,页面跳转需要加载时间,可能会出现代码执行的速度比页面渲染的速度要快,导致元素查找不到,因此可以添加等待
# 添加隐式等待和显示等待都可以,任选择一个
# 隐式等待:创建浏览器对象之后就可以加上,因为隐式等待的作用域在driver整个生命周期
# 显示等待:可以作用在当前代码中
actual = self.driver.find_element(By.CSS_SELECTOR,"body > div.container > div.right > div:nth-child(1) > div.title").text
assert actual == "自动化测试创建"
#屏幕截图
BlogDriver.getScreenShot()
RunTest.py
import time
from common.Utils import BlogDriver
from tests import BlogLogin, BlogList, BlogDetail, BlogEdit
if __name__ == "__main__":
BlogLogin.BlogLogin().LoginFailTest()
# 上面的弹窗没有处理
BlogLogin.BlogLogin().LoginSucTest()
# #登录成功之后就可以调用博客首页测试首页的用例(登录状态)
BlogList.BlogList().ListTestByLogin()
# BlogList.BlogList().NotLoginListTest()
BlogDetail.BLogDetail().DetailTestByLogin()
#博客编辑页测试用例
BlogEdit.BlogEdit().ListTestByLogin()
# #测试登陆状态下的博客详情页
BlogDriver.driver.quit()
3.自动化测试的特点与亮点
这里是根据个人项目定制的测试用例,采用Selenium自动化测试工具来实现这些测试用例(确保功能和步骤清晰明确),以便能够执行更多且更频繁的测试,使某些测试任务比手动执行更加高效。利用自动化测试,可以在设备空闲时如晚上或周末进行测试,从而更好地利用资源。通过自动化重复性任务,测试人员可以将更多精力集中在设计新测试用例上,提高测试的准确性和积极性。自动化测试不仅保证了测试的一致性和可重复性,还增加了软件的信任度,因为它提供了更客观的测试结果。然而,自动化测试也带来了成本,包括开发、运行和维护自动化测试脚本的成本,以及因软件更新而需要调整测试脚本所带来的额外维护开销。
亮点:
-
仅需初始化一次浏览器驱动,避免了在每个测试用例中重复创建驱动,从而提升了整体性能表现。
-
测试用例以独立函数的形式实现,每个函数专注于特定的功能检查点,增强了代码的可读性和维护性。
-
针对页面加载速度慢于脚本执行速度的情况,通过引入隐式等待机制,可以有效解决因页面元素未及时加载而导致的问题,进而提升自动化测试的稳定性和效率。