一、项目背景
随着现代互联网的快速发展,实时通信系统(如聊天应用)已成为人们日常交流的重要工具。多用户网页聊天室项目旨在为用户提供一个基于Web的实时聊天平台,支持用户之间的即时通信、好友管理和历史消息记录查看。为了提升用户体验并确保系统的稳定性,本项目引入了自动化测试流程,通过自动化测试实现对核心功能的高效验证,减少手动测试的重复工作,提高测试效率,确保在不同环境下系统功能的正常运行。
聊天室采用了Spring MVC作为后端框架,通过WebSocket实现消息的实时传输,前端使用原生HTML和CSS构建用户界面。项目的自动化测试部分通过Selenium编写,结合Python语言进行测试脚本开发,覆盖了用户登录、好友管理、消息传输等核心功能模块,确保用户能够在各类浏览器和网络条件下获得一致、流畅的聊天体验。
二、测试主要任务
1.功能测试
1.1编写手工测试用例
设计测试用例方法主要从 功能测试、界面测试、性能测试、兼容性测试、易用性测试、安全测试、弱网测试等七个方面进行设计,但个人博客的测试主要就是针对核心功能进行测试脑图展示如下:
1.2实际执行用例
1.2.1登录
(1)介绍
用户名以及密码已经在后端写入了数据库是已经存在的,登录成功后就会跳转到聊天页面;
(2)测试用例展示
a)界面
b)输入正确的账号和密码(以用户"zhangsan"为例):
预期结果:出现登录成功的弹窗,点击后,跳转到博客列表页。
实际结果如下:
c)输入错误的账号或密码
预期结果:提示用户登录失败。
实际结果如下:
1.2.2聊天消息列表展示
(1)介绍
可以在列表页(主页)查看有限数量的聊天,其包括联系人名称、及最近一条消息内容。并且点击对应联系人之后会跳转到相应的聊天详情页。
(2)测试用例展示
a)列表页界面(显示消息等)
b)跳转到相应的聊天详情页
以点击“zhaoliu”为例:
1.2.3聊天消息详情页展示
(1)介绍
可以在详情页。查看具体聊天内容,其包括联系人名称、及聊天内容。
(2)测试用例展示
a)以“lisi”为例
1.2.4联系人页展示
(1)介绍
可以在联系人页展示查看联系人,其包括联系人名称。并且点击相应联系人后会跳转到相应聊天详情页。
(2)测试用例展示
a)查看联系人
b)点击跳转到相应聊天详情页(以“lisi”为例)
1.2.5信息的编辑与发送
(1)介绍
可以在信息的编辑与发送页进行信息的操作,其包括编辑内容与发送内容。
(2)测试用例展示
a)页面元素
b)编辑与发送内容
1.2.6搜索框
(1)介绍
可以搜索内容(未完善)输入内容点击“放大镜”按钮
(2)测试用例展示
a)页面元素
b)输入内容搜索(失效)
2.使用Selenium进行Web自动化测试
2.1 创建驱动和释放驱动类
创建一个驱动类(自定义名为Untils),在对聊天登录页、聊天列表页、聊天编辑页、聊天详情页,搜索框这几个页面分别进行测试时,都有一个初始化动作(创建驱动)和退出动作(退出浏览器),那么我们便可以把创建驱动和释放驱动这个操作放在一个类中,并设置驱动对象为静态的,就可以让创建和销毁驱动的步骤执行一次,其他类如果需要驱动直接继承该类。并且,创建屏幕截图功能以便更好地观察自动化测试代码如下:
import datetime
import os.path
import sys
from PIL import ImageGrab
#创建一个浏览器对象
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(service = Service(ChromeDriverManager().install()),options = options)
self.driver.implicitly_wait(5)
def getScreeShot(self):
#创建屏幕截图
dirname = datetime.datetime.now().strftime("%Y-%m-%d")
if not os.path.exists("../images/" + dirname):
os.mkdir("../images/" + dirname)
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)
def get_alert_image(self):
'''
截图包含弹窗的页面
后续需要截图弹窗的时候调用这个方法
:return:
'''
# 创建屏幕截图
dirname = datetime.datetime.now().strftime("%Y-%m-%d")
if not os.path.exists("../images/" + dirname):
os.mkdir("../images/" + dirname)
filename = sys._getframe().f_back.f_code.co_name + "-" + datetime.datetime.now().strftime(
"%Y-%m-%d-%H%M%S") + ".png"
screenshot = ImageGrab.grab()
screenshot.save("../images/"+dirname+"/"+filename)
ChatDriver = Driver()
2.2聊天室“登录“自动化测试
①创建一个聊天登录页面测试类(自定义名为ChatLogin)继承Utils类,得到驱动
②创建 LoginSucTest()方法
③在这个界面下分别对打开网页是否正常,并使用参数化注解对登录正常模块、登录异常模块分别进行测试
④注意清空内容后才能再次输入用户名以及密码
代码如下:
#测试聊天室登陆页面
import time
from lib2to3.pgen2 import driver
from selenium.webdriver.common.by import By
from common.Utils import Driver, ChatDriver
class ChatLogin:
url = ""
driver = ""
ChatDriver = ""
def __init__(self):
self.url = "http://127.0.0.1:8080/login.html"
self.ChatDriver = Driver()
self.driver = self.ChatDriver.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("123")
self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
# 切换到警告框
time.sleep(3)
alert = self.driver.switch_to.alert
text = alert.text
#print(f"警告框中的文本: {text}") # 打印获取到的文本
alert.accept()
assert text == "登录成功!"
# 添加屏幕截图
ChatDriver.get_alert_image()
#返回登录页面
self.driver.back()
#未成功登录的测试用例
def LoginFailTest(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("123")
self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
# 切换到警告框
time.sleep(2)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "登录失败!"
# 添加屏幕截图
ChatDriver.get_alert_image()
alert.accept()
#账号密码为空
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("")
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
time.sleep(2)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前输入的用户名或者密码为空!"
# 添加屏幕截图
ChatDriver.get_alert_image()
alert.accept()
#账号为空,密码正确
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("")
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
time.sleep(2)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前输入的用户名或者密码为空!"
# 添加屏幕截图
ChatDriver.get_alert_image()
alert.accept()
#异常密码
# 账号正确,密码错误
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("1234")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
# 切换到警告框
time.sleep(2)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "登录失败!"
# 添加屏幕截图
ChatDriver.get_alert_image()
alert.accept()
# 账号密码为空
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("")
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
time.sleep(2)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前输入的用户名或者密码为空!"
# 添加屏幕截图
ChatDriver.get_alert_image()
alert.accept()
# 账号正确,密码为空
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("")
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
time.sleep(2)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前输入的用户名或者密码为空!"
# 添加屏幕截图
ChatDriver.get_alert_image()
alert.accept()
#不点击登录按钮
#正确的账号密码
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("1234")
#self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
self.driver.find_element(By.CSS_SELECTOR,"body > div.nav")
#错误的账号正确的密码
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("zhangsan123")
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123")
# self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
self.driver.find_element(By.CSS_SELECTOR, "body > div.nav")
#正确的账号错误的密码
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("1234")
# self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
self.driver.find_element(By.CSS_SELECTOR, "body > div.nav")
# 添加屏幕截图
ChatDriver.get_alert_image()
Login = ChatLogin()
Login.LoginSucTest()
#Login.LoginFailTest()
2.3聊天消息列表自动化测试
代码如下:
import time
from telnetlib import EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from common.Utils import ChatDriver
#消息列表测试用例
class ChatList:
url=""
driver=""
def __init__(self):
self.url = "http://127.0.0.1:8080/client.html"
self.driver = ChatDriver.driver
self.driver.get(self.url)
def ListTestByLogin(self):
#登录状态下消息列表
#检查元素
#个人信息
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.user")
#搜索框
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search")
#搜索按钮
self.driver.find_element(By.CSS_SELECTOR," body > div.client - container > div > div.left > div.search > button")
#聊天按钮
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.tab > div.tab-session")
#联系人列表按钮
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.tab > div.tab-friend")
#聊天人名称
self.driver.find_element(By.CSS_SELECTOR,"#session-list > li:nth-child(1) > h3")
#最近聊天内容
self.driver.find_element(By.CSS_SELECTOR,"#session-list > li:nth-child(1) > p")
#添加屏幕截图
ChatDriver.getScreeShot()
self.driver.back()
#未登录状态下消息列表
def ListTestByNotLogin(self):
newurl = "http://127.0.0.1:8080/client.html"
self.driver.get(newurl)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前用户未登录!"
# 添加屏幕截图
ChatDriver.getScreeShot()
alert.accept()
#回到登录界面
self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
# 切换到警告框
# 等待警告框出现
try:
WebDriverWait(self.driver, 10).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
except Exception as e:
print(f"警告框未出现或已关闭: {e}")
alert = self.driver.switch_to.alert
alert.accept()
2.3聊天消息详情页自动化测试
class ChatDetails:
url=""
driver=""
def __init__(self):
self.url="http://127.0.0.1:8080/client.html"
self.driver=ChatDriver.driver
self.driver.get(self.url)
#登录状态下聊天详情页
def DetailsTestByLogin(self):
self.driver.find_element(By.CSS_SELECTOR,"#session-list > li.selected").click()
#检查元素
#聊天对象名称
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.title")
#账号名称
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.message-show > div:nth-child(1) > div > h4")
#账号聊天内容
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.message-show > div:nth-child(1) > div > p")
#聊天对象名称
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.message-show > div:nth-child(3) > div > h4")
#对象聊天内容
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.message-show > div:nth-child(3) > div > p")
#添加屏幕截图
ChatDriver.getScreeShot()
self.driver.back()
#未登录状态下聊天详情页
def DetailsTestNotByLogin(self):
newurl = "http://127.0.0.1:8080/client.html"
self.driver.get(newurl)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前用户未登录!"
# 添加屏幕截图
ChatDriver.getScreeShot()
alert.accept()
# 回到登录界面
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
# 切换到警告框
# 等待警告框出现
try:
WebDriverWait(self.driver, 10).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
except Exception as e:
print(f"警告框未出现或已关闭: {e}")
alert = self.driver.switch_to.alert
alert.accept()
2.4联系人页自动化测试
class ContactList:
url=""
driver=""
def __init__(self):
self.driver = ChatDriver.driver
def ContactTestByLogin(self):
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.tab > div.tab-friend").click()
#检查元素
#用户名称
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.user")
#搜索框
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search")
#搜索按钮
self.driver.find_element(By.CSS_SELECTOR,"body > div.client - container > div > div.l")
#聊天按钮
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.tab > div.tab-session")
#联系人列表按钮
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.tab > div.tab-friend")
#联系人姓名
self.driver.find_element(By.CSS_SELECTOR,"#friend-list > li:nth-child(1)")
#获取联系人名称
actal1=self.driver.find_element(By.CSS_SELECTOR,"#friend-list > li:nth-child(1)").text
self.driver.find_element(By.CSS_SELECTOR,"#friend-list > li:nth-child(1)").click()
actal2=self.driver.find_element(By.CSS_SELECTOR,"#session-list > li.selected > h3").text
assert actal1 == actal2
print("Before printing actal1")
print(f"{actal1}")
print("Before printing actal2")
print(f"{actal2}")
# 添加屏幕截图
ChatDriver.getScreeShot()
#未登录
def ContactTestByNotLogin(self):
newurl = "http://127.0.0.1:8080/client.html"
self.driver.get(newurl)
time.sleep(3)
# 添加屏幕截图
ChatDriver.get_alert_image()
time.sleep(3)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前用户未登录!"
alert.accept()
# 回到登录界面
self.driver.find_element(By.CSS_SELECTOR, "#submit").click()
# 切换到警告框
alert = self.driver.switch_to.alert
alert.accept()
Login = ContactList()
# Login.ContactTestByLogin()
2.5信息编辑于发送页自动化测试
class ContactList:
url=""
driver=""
def __init__(self):
self.url="http://127.0.0.1:8080/client.html"
self.driver = ChatDriver.driver
self.driver.get(self.url)
def InforTestByLogin(self):
# 检查元素
#输入框
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > textarea")
#发送按钮
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.ctrl > button")
#登录状态下,正常发送信息
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > textarea").send_keys("我是张三,晚上不辞")
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.ctrl > button").click()
actal=self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.message-show > div:nth-child(52) > div > p").text
# 添加屏幕截图
ChatDriver.getScreeShot()
assert actal == "我是张三,晚上不辞"
#登录状态下,异常发送信息
#输入信息不点击
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > textarea").send_keys("我是张三,晚上不辞")
#空白信息点击
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > textarea").send_keys("")
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.right > div.ctrl > button").click()
#未登录状态
def InforTestByNotLogin(self):
newurl = "http://127.0.0.1:8080/client.html"
self.driver.get(newurl)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前用户未登录!"
# 添加屏幕截图
ChatDriver.getScreeShot()
alert.accept()
#回到登录界面
self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
# 切换到警告框
# 等待警告框出现
try:
WebDriverWait(self.driver, 10).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
except Exception as e:
print(f"警告框未出现或已关闭: {e}")
alert = self.driver.switch_to.alert
alert.accept()
2.6 搜索框自动化测试、
class ContactList:
url=""
driver=""
def __init__(self):
self.url="http://127.0.0.1:8080/client.html"
self.driver = ChatDriver.driver
self.driver.get(self.url)
#登录状态正常搜索
def SearchBoxByLogin(self):
#搜索
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > input[type=text]").clear()
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > input[type=text]").send_keys("zhangsan")
#点击
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > button").click()
#登录状态异常搜索
#空白内容,点击搜索
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > input[type=text]").clear()
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > input[type=text]")
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > button").click()
#输入内容,不点击搜索
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > input[type=text]").clear()
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > input[type=text]").send_keys("zhangsan")
self.driver.find_element(By.CSS_SELECTOR,"body > div.client-container > div > div.left > div.search > button")
#未登录状态
def SearchTestByNotLogin(self):
newurl = "http://127.0.0.1:8080/client.html"
self.driver.get(newurl)
alert = self.driver.switch_to.alert
text = alert.text
assert text == "当前用户未登录!"
# 添加屏幕截图
ChatDriver.getScreeShot()
alert.accept()
#回到登录界面
self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
# 切换到警告框
# 等待警告框出现
try:
WebDriverWait(self.driver, 10).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
except Exception as e:
print(f"警告框未出现或已关闭: {e}")
alert = self.driver.switch_to.alert
alert.accept()
3.自动化测试特点与亮点
- 模块化设计:测试分为多个独立模块,易于扩展和维护。
- 覆盖全面:测试了登录失败、成功,以及联系人列表等功能。
- 异常处理完善:通过
try-except
确保异常发生时资源正常释放。 - 可扩展性强:独立的类和方法封装,方便复用和添加新测试。
- 使用 Selenium 自动化框架:模拟真实用户操作,提高测试效率和可靠性。
特点:
- 模块化和分离关注点:分模块设计,便于管理和扩展。
- 错误处理机制:防止测试失败影响整体流程。
- 测试多场景覆盖:登录成功、失败等多场景测试。
4. 测试中遇到的bug及原因
隐式等待有时会改变代码执行顺序出现报错,可加入强制等待,确保页面加载完成,提高自动化的稳定性。