文章目录
- 多用户网页在线聊天室
- 一,项目概括
- 1.1 项目名称
- 1.2 测试时间
- 1.3 项目背景
- 1.3 编写目的
- 二,测试计划
- 2.1 测试环境与配置
- 2.2 测试用例
- 2.3实际执行用例
- 2.3.1登录
- 2.3.2聊天消息列表展示
- 2.3.3聊天消息详情页展示
- 2.3.4联系人页展示
- 2.3.5信息的编辑与发送
- 2.3.6搜索框
- 三、自动化测试工具
- 3.1 注入依赖
- 3.2 注册自动化测试
- 3.3 未登录情况测试
- 3.4 登录自动化测试
- 3.5 聊天室页面自动化测试
- 3.6 自动化测试结果总结
- 3.6 自动化测试结果总结
多用户网页在线聊天室
一,项目概括
1.1 项目名称
多用户网页在线聊天室
1.2 测试时间
2024.6——2024.6
1.3 项目背景
随着现代互联网的快速发展,实时通信系统已成为人们日常交流的重要工具。为了让这个聊天室既好用又稳定,项目里加了一套“自动检查”系统(自动化测试)。比如登录、加好友、发消息这些核心功能,不用手动一遍遍测,而是用写好的程序自动模拟操作,快速发现问题。这样一来,无论用哪种浏览器或者网络环境,聊天功能都能稳稳运行,用户体验更流畅。
聊天室采用了Spring MVC作为后端框架,通过WebSocket实现消息的实时传输,前端使用原生HTML和CSS构建用户界面。项目的自动化测试部分通过Selenium编写,结合Python语言进行测试脚本开发,覆盖了用户登录、好友管理、消息传输等核心功能模块,确保用户能够在各类浏览器和网络条件下获得一致、流畅的聊天体验。
1.3 编写目的
对编写的网页聊天室项目进行软件测试活动,揭示潜在问题,总结测试过程种地成功经验与不足,以便于更好的进行测试工作
二,测试计划
2.1 测试环境与配置
平台:Windows 10
浏览器:Chrome
自动化测试工具:Selenium + Junit5
2.2 测试用例
2.3实际执行用例
2.3.1登录
用户名以及密码已经在后端写入了数据库是已经存在的,登录成功后就会跳转到聊天页面
输入正确的账号和密码(以用户"zhangsan"为例):
预期结果:出现登录成功的弹窗,点击后,跳转到博客列表页。
实际结果如下:
输入错误的账号或密码
预期结果:提示用户登录失败。
实际结果如下:
2.3.2聊天消息列表展示
可以在列表页(主页)查看有限数量的聊天,其包括联系人名称、及最近一条消息内容。并且点击对应联系人之后会跳转到相应的聊天详情页。
2.3.3聊天消息详情页展示
可以在详情页。查看具体聊天内容,其包括联系人名称、及聊天内容。
2.3.4联系人页展示
可以在联系人页展示查看联系人,其包括联系人名称。并且点击相应联系人后会跳转到相应聊天详情页。
2.3.5信息的编辑与发送
可以在信息的编辑与发送页进行信息的操作,其包括编辑内容与发送内容。
2.3.6搜索框
可以搜索内容输入内容点击“放大镜”按钮
三、自动化测试工具
3.1 注入依赖
在maven—poom.xml中,引入依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<!-- 截图 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.1</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
-
单例驱动
- 自动化测试程序过程中,会频繁的使用驱动,如果频繁的创建和销毁,开销还是比较大的,因此我们可以使用懒汉模式加载驱动
- 这样可以保证驱动不会频繁创建,能减轻程序刚开始启动时的系统开销(只有用到驱动是才会加载它)
- 如果其他类需要使用到驱动的话,直接继承该类即可
-
获取屏幕截图
- 当我们测试用例出错时,我们需要查看当时网页出现的情况,那么就需要使用屏幕截图来排查问题
- 使用 getScreenshotAs 方法来保存屏幕截图,在每个测试用例执行完后进行一次屏幕截图
- 屏幕截图统一保存到一个路径下,文件名以当时时间去组织(防止保存屏幕截图出现覆盖情况)
- 综上,我们便在 AutoTestUtils类下加上保存截图的方法,方便其他类调用
package common;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class AutoTestUtils {
private static ChromeDriver driver;
public static ChromeDriver getDriver() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
if (driver == null) {
driver = new ChromeDriver(options);
//创建隐式等待,设置最长等待时间10s
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
return driver;
}
/**
* 获取屏幕截图,将用例执行结果保存下来
*/
public void getScreenShot(String str) throws IOException {
List<String> list = getTime();
String fileName = "./src/main/java/chatRoomAutoTest/" + list.get(0) + list.get(0) + "/" + str + "_" + list.get(1) + ".png";
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
//把生成的截图放入指定路径
FileUtils.copyFile(srcFile,new File(fileName));
}
//获取当前时间(记录每个屏幕截图是什么时候拍摄的)
private List<String> getTime() {
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
//保存的文件夹名 当天的年月日 + 具体时间
String fileName = sdf1.format(System.currentTimeMillis());
//保存的图片名 当天的年月日
String dirName = sdf2.format(System.currentTimeMillis());
List<String> list = new ArrayList<>();
list.add(dirName);
list.add(fileName);
return list;
}
}
3.2 注册自动化测试
此处我们创建一个 RegTest 类继承 AutoTestUtils 类得到驱动
先测试注册页面是否正常打开,输入.最后进行相应弹窗处理,进行屏幕截图
package UserTest;
import common.AutoTestUtils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.io.IOException;
import static java.lang.Thread.sleep;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegTest extends AutoTestUtils {
//获取到驱动
private static WebDriver driver = AutoTestUtils.getDriver();
/**
* 打开网页
* 注册网页一般是从登录页面进入
*/
@BeforeAll
public static void openWeb() {
//打开登录页面
driver.get("http://182.92.153.14:9091/login.html");
//再点击登录页面的注册链接按钮
driver.findElement(By.cssSelector("body > div.login-container > div > div:nth-child(4) > a")).click();
driver.manage().window().maximize();
}
/**
* 验证网页正常打开
*/
@Test
@Order(1)
public void elementsAppear() throws IOException {
//用户名输入框
driver.findElement(By.cssSelector("#username"));
//密码输入框
driver.findElement(By.cssSelector("#password"));
//注册按钮
driver.findElement(By.cssSelector("#submit"));
//登录账号链接
driver.findElement(By.cssSelector("body > div.register-container > div > div:nth-child(4) > a"));
getScreenShot(getClass().getName());
}
/**
* 注册失败测试用例
* 参数: 尝试注册已注册用户
*/
@ParameterizedTest
@CsvSource({"zhangsan,123"})
@Order(2)
public void regFunTest(String username, String passowrd) throws InterruptedException, IOException {
//输入账号
driver.findElement(By.cssSelector("#username")).sendKeys(username);
//输入密码
driver.findElement(By.cssSelector("#password")).sendKeys(passowrd);
//点击注册
driver.findElement(By.cssSelector("#submit")).click();
//等待弹窗
sleep(3000);
//期望结果
String expect = "注册失败!";
String actual = driver.switchTo().alert().getText();
Alert alert = driver.switchTo().alert();
if (alert != null) {
alert.accept();
} else {
actual = "当前用例执行失败";
}
//断言
Assertions.assertEquals(expect, actual);
//屏幕截图
getScreenShot(getClass().getName());
}
/**
* 注册成功测试用例
*/
@ParameterizedTest
@CsvSource({"lisi,123,注册成功!"})
@Order(3)
public void regTest(String username, String password,String expect) throws InterruptedException, IOException {
//拿到元素
WebElement inputUserName = driver.findElement(By.cssSelector("#username"));
WebElement inputPassword = driver.findElement(By.cssSelector("#password"));
WebElement button = driver.findElement(By.cssSelector("#submit"));
//清除输入框
inputUserName.clear();
inputPassword.clear();
//输入用例
inputUserName.sendKeys(username);
inputPassword.sendKeys(password);
//提交
button.click();
//强制等待弹窗
Thread.sleep(100);
Alert alert = driver.switchTo().alert();
//期望结果
String actual = "注册成功!";
if(alert != null) {
alert.accept();
}else {
actual = "当前用例执行失败";
}
Assertions.assertEquals(expect,actual);
//屏幕截图
getScreenShot(getClass().getName());
}
}
3.3 未登录情况测试
此处我们创建一个 InterceptTest 类继承 AutoTestUtils 类得到驱动
测试未登录情况下,打开会话页面,进行相应弹窗处理,进行屏幕截图
package UserTest;
import common.AutoTestUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.Alert;
import org.openqa.selenium.chrome.ChromeDriver;
import static java.lang.Thread.sleep;
public class InterceptTest extends AutoTestUtils {
//获取驱动
private static ChromeDriver driver = AutoTestUtils.getDriver();
@Test
public void Intercept() throws InterruptedException {
//在未登录的情况下,跳转会话页
driver.get("http://182.92.153.14:9091/client.html");
sleep(2000);
//期望结果
String expect = "当前用户未登录!";
String actual = "当前用户未登录!";
Alert alert = driver.switchTo().alert();
if (alert != null) {
alert.accept();
} else {
actual = "当前用例执行失败";
}
//屏幕截图
getScreenShot(getClass().getName());
//断言
Assertions.assertEquals(expect,actual);
}
}
3.4 登录自动化测试
此处我们创建一个 LoginTest 类继承 AutoTestUtils 类得到驱动
先测试登录页面是否正常打开,再找几个典型的用例对异常,正常登录风别进行测试
最后进行相应弹窗处理,进行屏幕截图
package UserTest;
import common.AutoTestUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.io.IOException;
import static java.lang.Thread.sleep;
public class LoginTest extends AutoTestUtils {
//获取到驱动
private static WebDriver driver = AutoTestUtils.getDriver();
/**
* 打开页面
* 注册页面一般是从登录页面进入
*/
@BeforeAll
public static void openWeb() {
//先打开登录页面
driver.get("http://182.92.153.14:9091/login.html");
driver.manage().window().maximize();
}
/**
* 检测登录页面是否能正常打开
*/
@Test
@Order(1)
public void elementsAppear() throws IOException {
//用户名输入框
driver.findElement(By.cssSelector("#username"));
//密码输入框
driver.findElement(By.cssSelector("#password"));
//注册账号链接
driver.findElement(By.cssSelector("body > div.login-container > div > div:nth-child(4) > a"));
//登录按钮
driver.findElement(By.cssSelector("#submit"));
//屏幕截图
getScreenShot(getClass().getName());
}
/**
* 异常测试登录功能
* 参数一:尝试登录未注册用户
* 参数二:密码输入错误,登录账号
*/
@ParameterizedTest
@CsvSource({"zhang,123","zhangsan,123456"})
@Order(2)
public void loginAbnormalTest(String username,String password) throws InterruptedException, IOException {
//拿到元素
WebElement inputUserName = driver.findElement(By.cssSelector("#username"));
WebElement inputPassword = driver.findElement(By.cssSelector("#password"));
WebElement button = driver.findElement(By.cssSelector("#submit"));
//清除用户名,密码
inputUserName.clear();
inputPassword.clear();
//输入账号,密码
inputUserName.sendKeys(username);
inputPassword.sendKeys(password);
//点击登录
button.click();
//等待弹窗
sleep(3000);
//期望结果
String expect = "登录失败!";
String actual = "登录失败!";
Alert alert = driver.switchTo().alert();
if(alert != null) {
alert.accept();
} else {
actual = "当前用例执行失败!";
}
Assertions.assertEquals(expect,actual);
//屏幕截图
getScreenShot(getClass().getName());
}
/**
* 正常登录测试
*/
@ParameterizedTest
@CsvSource({"'zhangsan','123','登陆成功'"})
@Order(3)
public void loginNormalTest(String userName,String password,String expect) throws InterruptedException, IOException {
//发现元素
WebElement inputUserName = driver.findElement(By.cssSelector("#username"));
WebElement inputPassword = driver.findElement(By.cssSelector("#password"));
WebElement button = driver.findElement(By.cssSelector("#submit"));
//清除用户名密码
inputUserName.clear();
inputPassword.clear();
//输入用户名,密码
inputUserName.sendKeys(userName);
inputPassword.sendKeys(password);
//点击登录
button.click();
//等待弹窗
sleep(3000);
//期望结果
String actual = driver.switchTo().alert().getText();
//断言
Assertions.assertEquals(expect,actual);
//处理弹窗
driver.switchTo().alert().accept();
//屏幕截图
getScreenShot(getClass().getName());
}
}
3.5 聊天室页面自动化测试
此处我们创建一个 ClientTest 类继承 AutoTestUtils 类得到驱动
先对页面功能以及聊天功能进行自动化测试,进行相应的弹窗处理,最后进行屏幕截截图
package UserTest;
import common.AutoTestUtils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import java.io.IOException;
import static java.lang.Thread.sleep;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ClientTest extends AutoTestUtils {
//获得驱动
public static WebDriver driver = AutoTestUtils.getDriver();
/**
* 打开会话页面
*/
@BeforeAll
public static void openWeb() {
//先打开会话页面
driver.get("http://182.92.153.14:9091/client.html");
driver.manage().window().maximize();
}
/**
* 测试会话页面正常打开
*/
@Test
@Order(1)
public void elementsAppear() throws IOException {
//主页个人账号名
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.user"));
//搜索输入框
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.search > input[type=text]"));
//搜索按钮
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.search > button"));
//会话标签图
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-session"));
//好友标签图
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-friend"));
//聊天输入框
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > textarea"));
//发送按钮
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.ctrl > button"));
//屏幕截图
getScreenShot(getClass().getName());
}
/**
* 点击具体会话
* 检验:消息页面展示当前会话用户名字
*/
@Order(2)
@Test
void SessionList() throws InterruptedException {
//点击具体会话
driver.findElement(By.xpath("//*[@id=\"session-list\"]/li[1]/h3")).click();
sleep(3000);
//获取到消息页面展示当前用户名字
String actual = driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.title")).getText();
Assertions.assertEquals("wangwu",actual);
}
/**
* 点击好友列表
*/
@Order(3)
@Test
void FriendList() throws InterruptedException {
//点击好友按钮,打开好友列表
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-friend")).click();
sleep(3000);
//点击好友
driver.findElement(By.xpath("//*[@id=\"friend-list\"]/li[1]/h4")).click();
sleep(3000);
//检验选中的好友在会话列表是否被置顶
String text = driver.findElement(By.cssSelector("#session-list > li.selected > h3")).getText();
Assertions.assertEquals("lisi",text);
}
/**
* 测试聊天发送功能
* 参数:zhangsan 给 wangwu 发送数据
*/
@ParameterizedTest
@CsvSource({"正在自动化测试中...","测试发送成功","测试结束!"})
@Order(4)
public void TalkSendTest(String msg) throws InterruptedException, IOException {
//点击好友会话开始聊天
driver.findElement(By.xpath("//*[@id=\"session-list\"]/li[2]/h3")).click();
sleep(3000);
//选择输入框开始聊天
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > textarea")).sendKeys(msg);
//点击发送
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.ctrl > button")).click();
sleep(3000);
//判断消息是否发送成功
//屏幕截图
getScreenShot(getClass().getName());
}
/**
* 测试聊天接收功能
* 参数:登录 wangwu 查看与 zhangsan 历史会话,检验是否发送成功
*/
@Test
@Order(5)
public void TalkAcceptTest() throws InterruptedException {
//打开页面
driver.get("http://182.92.153.14:9091/login.html");
sleep(3000);
//输入账号
driver.findElement(By.cssSelector("#username")).sendKeys("wangwu");
//输入密码
driver.findElement(By.cssSelector("#password")).sendKeys("123");
//点击登录
driver.findElement(By.cssSelector("#submit")).click();
sleep(3000);
//确认弹窗
driver.switchTo().alert().accept();
sleep(3000);
//点击 zhangsan 会话
driver.findElement(By.cssSelector("#session-list > li > h3")).click();
//获取好友名
String name = driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.title")).getText();
//获取最后一条消息
String text = driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.message-show > div:nth-child(3) > div > p")).getText();
//判断好友是否一致
Assertions.assertEquals("zhangsan",name);
//判断消息是否一致
Assertions.assertEquals("测试结束!",text);
}
}
3.6 自动化测试结果总结
driver.switchTo().alert().accept();
sleep(3000);
//点击 zhangsan 会话
driver.findElement(By.cssSelector("#session-list > li > h3")).click();
//获取好友名
String name = driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.title")).getText();
//获取最后一条消息
String text = driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.message-show > div:nth-child(3) > div > p")).getText();
//判断好友是否一致
Assertions.assertEquals("zhangsan",name);
//判断消息是否一致
Assertions.assertEquals("测试结束!",text);
}
}