文章目录
- 多用户网页在线聊天室
- 一,项目概括
- 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);//创建隐式等待,设置最长等待时间10sdriver.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();/*** 打开网页* 注册网页一般是从登录页面进入*/@BeforeAllpublic 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();@Testpublic 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();/*** 打开页面* 注册页面一般是从登录页面进入*/@BeforeAllpublic 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();/*** 打开会话页面*/@BeforeAllpublic 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)@Testvoid 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)@Testvoid 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);}
}