一、项目背景
1.1项目概述
本项目基于SSM框架搭建,并引入WebSocket技术实现实时通信,旨在提供稳定、高效的在线交流体验。SpringBoot管理项目组件,SpringMVC处理页面交互,MyBatis完成数据库操作。网页五子棋对战具备丰富的功能,如登录页面登录个人信息,游戏大厅页面开始匹配,双方匹配完成之后进入游戏房间页面开始对战,给用户便捷,快速,尽享游戏对战的愉悦。
1.2项目名称
云端五子对决
1.3开发语言
Java
1.4开发环境
IntelliJ IDEA 2024.1.4 (Ultimate Edition)
JDK1.8.0
1.5自动化测试代码附上
个人gitee链接: gobang: 网页五子棋对战(云端五子对决)项目,实现了三个页面,用户登陆页面,游戏大厅页面和游戏房间页面,实现了登录功能,匹配功能,落子功能等。
二、项目主要页面及功能
2.1用户登录页面
http://127.0.0.1:8080/login.html
2.2游戏大厅页面
http://127.0.0.1:8080/game_hall.html
2.3游戏房间页面
http://127.0.0.1:8080/game_room.html
你的页面~
匹配到对方的页面~
三、对项目进行测试
3.1编写测试用例
3.1.1用户登录页面测试用例
3.1.2游戏大厅页面测试用例
3.1.3游戏房间页面测试用例
3.2编写自动化测试用例
3.3执行测试
首先要创建一个maven项目,引入selenium以及Junit5的依赖以及浏览器驱动依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.8.0</version>
</dependency>
创建驱动类,分别是谷歌驱动对象和edge浏览器驱动对象
由于创建驱动对象和屏幕截图是频繁使用的,所以都放入一个包下
Utils可以被继承,提高代码复用
public class Utils {
//driver是谷歌驱动对象
// driver2是edge浏览器驱动对象
public static ChromeDriver driver;
public static EdgeDriver driver2;
public static ChromeDriver createDriver() {
if (driver == null) {
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
driver = new ChromeDriver(options);
//隐式等待2s
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
//隐式等待是为了查找元素,作用域贯穿整个driver的生命周期
}
return driver;
}
public static EdgeDriver createDriver2() {
if (driver2 == null) {
WebDriverManager.edgedriver().setup();
EdgeOptions options2 = new EdgeOptions();
options2.addArguments("--remote-allow-origins=*");
driver2 = new EdgeDriver(options2);
//隐式等待2s
driver2.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
//隐式等待是为了查找元素,作用域贯穿整个driver的生命周期
}
return driver2;
}
//截图
public List<String> getTime() {
SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");
String dirTime = sim1.format(System.currentTimeMillis());
String fileTime = sim2.format(System.currentTimeMillis());
List<String> list = new ArrayList<String>();
list.add(dirTime);
list.add(fileTime);
return list;
}
public void getScreenshot(String str) throws IOException {
List<String> list = getTime();
String fileName = "./src/test/images/" + list.get(0) + "/" + str + "-" + list.get(1) + ".png";
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcFile,new File(fileName));
}
public void getScreenshot2(String str) throws IOException {
List<String> list = getTime();
String fileName = "./src/test/images/" + list.get(0) + "/" + str + "-" + list.get(1) + ".png";
File srcFile = ((TakesScreenshot)driver2).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcFile,new File(fileName));
}
}
创建一个测试套件,以此顺序来执行自动化测试用例
@Suite
@SelectClasses({
LoginFail.class,
LandingPage.class,
GameLobbyPage.class
})
public class RunCase {
}
首先是异常登录状态下的测试用例,和在未登录状态下,直接用URL打开游戏大厅页面和游戏房间页
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LoginFail extends Utils {
public static String url1 = "http://127.0.0.1:8080/login.html";
public static String url2 = "http://127.0.0.1:8080/game_hall.html";
public static String url3 = "http://127.0.0.1:8080/game_room.html";
public static ChromeDriver driver;
@BeforeAll
public static void setUp() {
driver = createDriver();
driver.get(url1);
driver2 = createDriver2();
driver2.get(url1);
}
/*
异常登录 账号为空
密码为空
账号密码都不为空 账号错误
密码错误
正确账号密码为:zhangsan 123
*/
@ParameterizedTest
@Order(1)
@CsvSource({"'',123","zhangsan,''","wyb,123","zhangsan,456"})
public void loginFail(String username, String password) throws InterruptedException {
driver.navigate().refresh();
//清空输入框
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
//输入账号和密码
driver.findElement(By.cssSelector("#username")).sendKeys(username);
driver.findElement(By.cssSelector("#password")).sendKeys(password);
driver.findElement(By.cssSelector("#submit")).click();
//查看是否出现警告弹窗
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
Alert alert = null;
try {
alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
getScreenshot(getClass().getName());
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("没有出现弹窗!");
}
}
/*
检查其他页面,在用户未登录的前提下,是否会跳转到登陆页面
*/
@Test
@Order(2)
public void loginFail2() throws InterruptedException {
driver.get(url2);
String actual = driver.findElement(By.cssSelector("#submit")).getText();
String expect = "提交";
Assertions.assertEquals(expect, actual);
driver.get(url3);
actual = driver.findElement(By.cssSelector("#submit")).getText();
expect = "提交";
Assertions.assertEquals(expect, actual);
}
}
loginFail2()这个测试用例不通过,说明是有bug的,经过检查发现 由于直接用网址打开游戏大厅页面,是不能跳转到登陆页面,而是打开了页面,用户信息都是空 若点击两次匹配按钮,才会出现弹窗,确认弹窗之后才会跳转到登陆页面 在直接打开游戏房间页面时,会直接出现弹窗,确认弹窗之后会跳转到游戏大厅页面,同上述情况
用户登录页面动化测试
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LandingPage extends Utils {
public static String url = "http://127.0.0.1:8080/login.html";
//public static ChromeDriver driver;
//public static EdgeDriver driver2;
@BeforeAll
public static void setUp() {
driver = createDriver();
driver.get(url);
driver2 = createDriver2();
driver2.get(url);
}
/*
检查登录页面是否加载成功(页面是否可以正常打开)
检查点:用户名输入框 提交按钮 元素是否存在
*/
@Test
@Order(1)
public void landingPageRight() throws IOException, InterruptedException {
//可以通过检查页面元素是否存在来检查页面是否加载成功
//1.检查用户名输入框
driver.findElement(By.cssSelector("#username"));
//2.检查“提交按钮”
String expect = "提交";
String actual = driver.findElement(By.cssSelector("#submit")).getText();
getScreenshot(getClass().getName());
Assertions.assertEquals(expect, actual);
driver2.findElement(By.cssSelector("#username"));
//2.检查“提交按钮”
String expect2 = "提交";
String actual2 = driver2.findElement(By.cssSelector("#submit")).getText();
getScreenshot2(getClass().getName());
Assertions.assertEquals(expect2, actual2);
}
/*
正常登录 ----> 在正常登录确认弹窗之后是否能跳转成功
*/
@Test
@Order(2)
public void ChromeLoginRight() throws IOException, InterruptedException {
//清空输入框
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
//输入账号和密码
driver.findElement(By.cssSelector("#username")).sendKeys("zhangsan");
driver.findElement(By.cssSelector("#password")).sendKeys("123");
Thread.sleep(2000);
driver.findElement(By.cssSelector("#submit")).click();
//查看是否出现警告弹窗
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
Alert alert = null;
try {
alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
getScreenshot(getClass().getName());
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("没有出现弹窗!");
}
//检测是否出现游戏大厅页面的元素
new WebDriverWait(driver, Duration.ofSeconds(3)).until(driver ->
driver.findElement(By.cssSelector("#match-button")).getText().equals("开始匹配"));
}
@Test
@Order(3)
public void EdgeLoginRight() throws IOException, InterruptedException {
//清空输入框
driver2.findElement(By.cssSelector("#username")).clear();
driver2.findElement(By.cssSelector("#password")).clear();
//输入账号和密码
driver2.findElement(By.cssSelector("#username")).sendKeys("lisi");
driver2.findElement(By.cssSelector("#password")).sendKeys("123");
Thread.sleep(2000);
driver2.findElement(By.cssSelector("#submit")).click();
//查看是否出现警告弹窗
WebDriverWait wait = new WebDriverWait(driver2, Duration.ofSeconds(3));
Alert alert = null;
try {
alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
getScreenshot2(getClass().getName());
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("没有出现弹窗!");
}
//检测是否出现游戏大厅页面的元素
new WebDriverWait(driver2, Duration.ofSeconds(3)).until(driver2 ->
driver2.findElement(By.cssSelector("#match-button")).getText().equals("开始匹配"));
}
游戏大厅页自动化测试
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class GameLobbyPage extends Utils {
public static String url = "http://127.0.0.1:8080/game_hall.html";
//提前让两个浏览器的账号都登录好,在登陆页面自动化测试的时候已经把zhangsan和lisi的账号都登录好了
/*
检查页面元素是否正确加载
检测点:用户信息模块 匹配按钮
*/
@Test
@Order(1)
public void gameHallLoadRight() throws IOException {
//用户信息模块
driver.findElement(By.cssSelector("#screen"));
//匹配按钮
String actual = driver.findElement(By.cssSelector("#match-button")).getText();
String expect = "开始匹配";
getScreenshot(getClass().getName());
Assertions.assertEquals(expect,actual);
//用户信息模块
driver2.findElement(By.cssSelector("#screen"));
//匹配按钮
String actual2 = driver2.findElement(By.cssSelector("#match-button")).getText();
String expect2 = "开始匹配";
getScreenshot2(getClass().getName());
Assertions.assertEquals(expect2,actual2);
}
/*
点击”开始匹配“按钮,测试当前状态是否会发生改变
*/
@Test
@Order(2)
public void startMatch() throws IOException, InterruptedException {
driver.findElement(By.cssSelector("#match-button")).click();
String actual = driver.findElement(By.cssSelector("#match-button")).getText();
String expect = "匹配中...(点击停止)";
getScreenshot(getClass().getName());
Thread.sleep(3000);
Assertions.assertEquals(expect,actual);
driver2.findElement(By.cssSelector("#match-button")).click();
getScreenshot2(getClass().getName());
//查看是否出现了游戏房间页面的元素---->显式等待
new WebDriverWait(driver, Duration.ofSeconds(20)).until(driver ->
driver.findElement(By.cssSelector("#chess")));
Thread.sleep(3000);
}
游戏房间页自动化测试
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class GameRoomPage extends Utils {
public static String url = "http://127.0.0.1:8080/game_room.html";
//在游戏大厅页面中,两位用户分别已经登录,并且匹配成功,所以,直接测页面就好
/*
直接测试当前页面是否加载成功
*/
@Test
@Order(1)
public void gameRoomPageLoadRight() throws IOException {
driver.findElement(By.cssSelector("#chess"));
String actual = driver.findElement(By.cssSelector("#screen")).getText();
String expect = "轮到你落子了!";
getScreenshot(getClass().getName());
Assertions.assertEquals(expect,actual);
driver2.findElement(By.cssSelector("#chess"));
String actual2 = driver2.findElement(By.cssSelector("#screen")).getText();
String expect2 = "轮到对方落子了!";
getScreenshot2(getClass().getName());
Assertions.assertEquals(expect2,actual2);
}
/*
是否有用户掉线提示
*/
@Test
@Order(2)
public void userDisconnected() throws IOException {
//当刷新页面时会发现,用户连接会突然断开,出现弹窗
driver2.navigate().refresh();
//查看是否出现警告弹窗
WebDriverWait wait = new WebDriverWait(driver2, Duration.ofSeconds(3));
Alert alert = null;
try {
alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
getScreenshot2(getClass().getName());
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("没有出现弹窗!");
}
//确认弹窗会发现跳转到游戏大厅页面
String actual = driver2.findElement(By.cssSelector("#match-button")).getText();
String expect = "开始匹配";
getScreenshot2(getClass().getName());
Assertions.assertEquals(expect,actual);
}
/*
在游戏房间页面一方玩家掉线了,那另一方玩家直接判定为赢,并结束游戏
点击回到大厅按钮,可以回到游戏大厅页面
*/
@Test
@Order(3)
public void afterDisconnected() throws IOException {
String actual = driver.findElement(By.cssSelector("#screen")).getText();
String expect = "你赢了!";
getScreenshot(getClass().getName());
Assertions.assertEquals(expect,actual);
//点击回到大厅按钮后,查看是否回到游戏大厅页面
driver.findElement(By.cssSelector("body > div.container > div > button")).click();
String actual2 = driver.findElement(By.cssSelector("#match-button")).getText();
String expect2 = "开始匹配";
getScreenshot(getClass().getName());
Assertions.assertEquals(expect2,actual2);
}
}
四、测试总结
4.1测试分类
4.1.1功能测试
测试用例
功能测试结果:测试用例100%通过
4.1.2自动化测试
自动化测试模块覆盖:用户登录页面,游戏大厅页面,游戏房间页面
自动化测试用例数量:
自动化测试结果:
4.2遗留风险
测试时间紧张,先保证了论坛主体功能没有问题,可能存在细节测试不到位风险。
4.3测试结果评估
1)没有用户注册页面
2)密码输入时可以隐藏但不能明文显示
3)从测试结果可以看出,网页五子棋系统还有待完善,loginFail2()这个测试用例不通过,说明是有bug的,经过人工检查发现由于直接用网址打开游戏大厅页面,是不能跳转到登陆页面,而是打开了页面,用户信息都是空 若点击两次匹配按钮,才会出现弹窗,确认弹窗之后才会跳转到登陆页面 在直接打开游戏房间页面时,会直接出现弹窗,确认弹窗之后会跳转到游戏大厅页面,同上述情况