目录

一.项目介绍 

(一)项目简介

(二)功能介绍

(三)页面展示

1.注册页面

2.登录页面

3.游戏大厅页面

4.游戏房间页面(对战)

二.功能测试

(一)出现的bug

 (二)解决方法

三.自动化测试

(一)测试用例设计

(二)测试准备

(三)编写测试脚本

1.工具类

2.注册功能

3.登录测试

3.“游戏大厅”测试

4.“游戏房间”测试

5.驱动退出和测试套件类

(四)测试结果

四.性能测试

例子

五.总结

 

一.项目介绍 

若需要【萌笔趣棋】项目源码可后台私信

(一)项目简介

“新酱爱玩的五子棋” 是一款以《蜡笔小新》春日部角色为主题背景的五子棋游戏。该游戏基于网页端开发,通过简洁易懂的界面设计,为玩家提供经典五子棋的对战体验,融合了趣味性与竞技性,目标用户主要为喜爱五子棋和《蜡笔小新》动漫的人群。

(二)功能介绍

  1. 注册页面:玩家可在此页面输入自定义的用户名和密码进行账号注册。系统会对输入信息进行验证,确保用户名的唯一性等,成功注册后可获得在游戏中进行对战的资格。
  2. 登录页面:已注册玩家输入正确的用户名和密码登录游戏。登录成功后,可进入游戏大厅开始游戏相关操作;若输入错误,系统会提示重新输入。
  3. 游戏大厅:玩家登录后进入游戏大厅,可查看自己的游戏信息,包括用户名、当前分数、比赛场次和获胜场次等。点击 “开始匹配” 按钮,系统会自动为玩家寻找对战对手,在匹配过程中可点击取消匹配。
  4. 游戏房间:匹配成功后进入游戏房间,玩家和对手在此进行五子棋对战。游戏界面会显示棋盘,玩家按规则轮流落子。当一方率先在棋盘的横线、竖线或斜线上形成连续的五个棋子时,判定为获胜方,系统会显示胜负结果,并更新玩家在游戏大厅中的相关数据(如分数、比赛场次、获胜场次等) 。

(三)页面展示

1.注册页面

2.登录页面

3.游戏大厅页面

信息展示/开始匹配 

4.游戏房间页面(对战)

落子/回合切换

 胜负判定

二.功能测试

在此就不展示进行功能测试的截图了,具体可以跳转到(三)页面展示

(一)出现的bug

1.在进行注册功能时候,出现了用户名或者密码输入为空,但是仍然注册成功的情况

 (二)解决方法

1.在注册页面的前端代码中加入如下拦截请求代码:

   // 验证用户名和密码是否为空if (!username.trim()||!password.trim()) {alert('用户名或者密码不能为空');return; // 阻止表单提交}

三.自动化测试

源码:gobangAutoTest: 网页版五子棋对战——Web自动化测试

(一)测试用例设计

(二)测试准备

1.工具选择:

使用Selenium 并配合Junit单元测试框架

2.搭建和配置环境:

2.1 创建Maven项目——gobangAutoTest

2.2 在pom.xml中引入相关依赖

    <dependencies><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>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version></dependency><dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.9.0</version></dependency></dependencies>

2.3 包的模块化设计:

(三)编写测试脚本

1.工具类

public class AutotestUtils {public static EdgeDriver driver;/*** 创建驱动对象*/public static EdgeDriver createDriver() {if (driver == null) {WebDriverManager.edgedriver().setup();EdgeOptions options = new EdgeOptions();options.addArguments("--remote-allow-origins=*");// options.addArguments("-headless");driver = new EdgeDriver(options);//创建隐式等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));}return driver;}/*** 获取时间戳*/public List<String> getTime() {SimpleDateFormat sim1 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd");String filename = sim1.format(System.currentTimeMillis());String dirname = sim2.format(System.currentTimeMillis());List<String> list = new ArrayList();list.add(dirname);list.add(filename);return list;}/*** 获取屏幕截图*/public void getScreenShot(String str) throws IOException {List<String> list = this.getTime();String filename = "./src/test/java/com/gobangAutoTest/" + list.get(0) + "/" + str + "_" + list.get(1) + ".png";File srcfile = (File)driver.getScreenshotAs(OutputType.FILE);FileUtils.copyFile(srcfile, new File(filename));}}

2.注册功能

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class RegisterPageTest extends AutotestUtils {//1.驱动对象public static EdgeDriver driver = createDriver();/**访问注册页面的URL*/@BeforeAllstatic void baseControl() {driver.get("http://127.0.0.1:8080/register.html");}/*** 检查注册页面是否正常打开* 检查点:注册框标题 是否存在*/@Test@Order(1)void registerPageLoadRight() throws IOException {driver.findElement(By.cssSelector("body > div.login-container > div > h3"));getScreenShot(getClass().getName());}/*** 检查正常注册的情况,会出现弹窗:注册成功!*/@ParameterizedTest@CsvSource({"na_na,123"})@Order(3)void registerSuc(String name,String password) throws InterruptedException, IOException {String expected = "注册成功!";driver.findElement(By.cssSelector("#username")).clear();driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(name);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();//处理弹窗WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();String accept = alert.getText();alert.accept();getScreenShot(getClass().getName());Assertions.assertEquals(expected,accept);}/*** 检查异常注册的情况:用户名或者密码为空* 会出现弹窗提示*/@ParameterizedTest@CsvSource({"oppop"})@Order(3)void registerFail(String name) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear();driver.findElement(By.cssSelector("#password")).clear();String expected = "用户名或者密码不能为空!";driver.findElement(By.cssSelector("#username")).sendKeys(name);driver.findElement(By.cssSelector("#submit")).click();//处理弹窗WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();String accept = alert.getText();alert.accept();getScreenShot(getClass().getName());Assertions.assertEquals(expected,accept);}}

3.登录测试

//一个类注解,表明测试方法将按照@Order注解 指定执行顺序
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class LoginPageTest extends AutotestUtils {//1.驱动对象public static EdgeDriver driver = createDriver();//被BeforeAll修饰的方法必须为静态的,而静态的方法内不能存取非静态变量和非静态方法//在当前测试类中所有测试方法执行之前只执行一次@BeforeAll/**访问登录页面的URL*/static void baseControl() {driver.get("http://127.0.0.1:8080/login.html");}/**检查登录页面是否正常打开检查点:登录按钮 登录框标题 是否存在*/@Test@Order(1)void loginPageLoadRight() throws IOException {driver.findElement(By.cssSelector("#submit"));driver.findElement(By.cssSelector("body > div.login-container > div > h3"));getScreenShot(getClass().getName());}/**检查正常登录的情况*/@ParameterizedTest//为参数化测试提供Csv格式的数据@CsvSource({"wukong,123","w_o.ogason,123"})@Order(2)void loginSuc(String name, String passwd) throws InterruptedException, IOException {//这三步只是登录的步骤,能不能保证登录是成功的呢?//clear 先清空driver.findElement(By.cssSelector("#username")).clear();driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(name);driver.findElement(By.cssSelector("#password")).sendKeys(passwd);driver.findElement(By.cssSelector("#submit")).click();//处理“登录成功的弹窗”WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();alert.accept();//对登录结果进行检验——跳转到游戏大厅页面才算是登录成功//检查“个人信息框”元素是否存在//driver.findElement(By.cssSelector("#screen"));//检查“开始匹配按钮”元素是否存在driver.findElement(By.cssSelector("#match-button"));getScreenShot(getClass().getName());//页面返回——防止执行第二个测试用例时候因为页面跳转而导致元素查找失败driver.navigate().back();}/**检查异常登录的情况*/@ParameterizedTest@CsvSource({"wukong,12"})@Order(3)void loginFail(String name, String passwd) throws IOException {driver.findElement(By.cssSelector("#username")).clear();driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(name);driver.findElement(By.cssSelector("#password")).sendKeys(passwd);driver.findElement(By.cssSelector("#submit")).click();//对登录失败的结果进行检验WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();String res = alert.getText();alert.accept();getScreenShot(getClass().getName());// System.out.println(res);assert res.equals("登录失败! 用户名密码错误! 或者该账号正在游戏中!");}}

3.“游戏大厅”测试

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class GameHallTest extends AutotestUtils {//1.驱动对象public static EdgeDriver driver = createDriver();/**访问游戏大厅页面的URL*/@BeforeAllstatic void baseControl() {driver.get("http://127.0.0.1:8080/game_hall.html");}/*** 检查登录状态下的游戏大厅页面是否正常打开* */@Test@Order(1)void gameHallLoadRight() throws IOException {//检查“开始匹配按钮”元素是否存在driver.findElement(By.cssSelector("#match-button"));getScreenShot(getClass().getName());}/*** 检查正登录状态下:点击“开始匹配”按钮否会变化*/@Test@Order(2)void gameHallSuc() throws InterruptedException, IOException {String expected = "匹配中...(点击取消)";WebElement matchButton = driver.findElement(By.cssSelector("#match-button"));matchButton.click();//强制等待,等按钮文字改变Thread.sleep(3);String accept = driver.findElement(By.cssSelector("#match-button")).getText();getScreenShot(getClass().getName());Assertions.assertEquals(expected,accept);}}

4.“游戏房间”测试

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class GameRoomTest extends AutotestUtils {//1.驱动对象public static EdgeDriver driver = createDriver();/**访问游戏大厅页面的URL*/@BeforeAllstatic void baseControl() {driver.get("http://127.0.0.1:8080/game_room.html");}/*** 检查登录——未匹配用户状态下的的游戏房间是否有弹窗*/@Test@Order(1)void gameRoomFail() throws InterruptedException, IOException {String expected = "连接游戏失败! reason: 用户并未匹配成功! 不能开始游戏!";Thread.sleep(1000);Alert alert = driver.switchTo().alert();String accept = alert.getText();alert.accept();getScreenShot(getClass().getName());Assertions.assertEquals(expected,accept);}
}

5.驱动退出和测试套件类

public class driverQuitTest extends AutotestUtils {public static EdgeDriver driver = createDriver();@Testvoid driverQuit() {driver.quit();}
}
@Suite//创建测试套件
// 用于Suite的注解,指定要包含在测试套件中的测试类
@SelectClasses({RegisterPageTest.class, LoginPageTest.class,GameHallTest.class,GameRoomTest.class,driverQuitTest.class})
public class runSuite {}

(四)测试结果

运行结果

四.性能测试

总体测试框架

例子

1.设置线程组

模拟 100 个虚拟用户同时进行登录操作,在10秒内完成

用于测试五子棋游戏登录功能在高并发场景下的性能和稳定性。

 2.添加http请求

3.结果分析

 总体而言,从这两个报告看,该 HTTP 请求的响应时间短且稳定,无异常请求,系统在当前测试场景下性能表现良好,能较快速且稳定地处理请求 。

五.总结

功能测试保障软件功能正常、无缺失和错误,让用户有预期体验;性能测试确保软件在不同负载下响应及时、不卡顿崩溃,评估承载能力;自动化测试提升效率、降成本、保准确一致,在开发流程中及时发现问题,稳定软件质量。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/83305.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/83305.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/83305.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

知识图谱增强的大型语言模型编辑

https://arxiv.org/pdf/2402.13593 摘要 大型语言模型&#xff08;LLM&#xff09;是推进自然语言处理&#xff08;NLP&#xff09;任务的关键&#xff0c;但其效率受到不准确和过时知识的阻碍。模型编辑是解决这些挑战的一个有前途的解决方案。然而&#xff0c;现有的编辑方法…

数据库,Spring Boot,数据源

您是对的&#xff0c;我之前的回答解释了Spring Boot在操作MySQL时不一定需要显式配置指定的数据源类型&#xff0c;因为它有自动配置机制&#xff0c;但没有直接点明在自动配置情况下“数据源是什么”。 在Spring Boot自动配置机制下&#xff0c;这个“数据源”指的是一个连接…

数据结构测试模拟题(3)

1、两个有序链表序列的合并 #include<bits/stdc.h> using namespace std;struct node{int num;node* next; };// 创建链表 node* CreatList(){int x;node *head new node(); // 创建头节点head->next NULL;node *tail head; // 尾指针初始指向头节点while…

LabVIEW Val (Sgnl) 属性

在 LabVIEW 事件驱动架构中&#xff0c;Val (Sgnl) 属性&#xff08;Value (Signaling)&#xff09;是实现编程触发与用户交互行为一致性的关键技术。与普通 Value 属性不同&#xff0c;Val (Sgnl) 在修改控件值的同时强制生成值改变事件&#xff0c;确保程序逻辑与 UI 交互保持…

04.MySQL数据类型详解

MySQL数据类型详解 文章目录 MySQL数据类型数据类型分类数值类型 tinyint类型bit类型float类型decimal类型 字符串类型 char类型varchar类型char和varchar比较 时间日期类型enum和set类型数据类型选择的进阶技巧常见误区与解决方案性能优化与最佳实践 MySQL数据类型 数据类型…

Spring AI 之对话记忆(Chat Memory)

大型语言模型&#xff08;LLMs&#xff09;是无状态的&#xff0c;这意味着它们不会保留关于之前交互的信息。当想在多次交互中保持上下文或状态时&#xff0c;这可能会成为一个限制。为了解决这一问题&#xff0c;Spring AI 提供了对话记忆功能&#xff0c;允许你在与大型语言…

Hölder Statistical Pseudo Divergence Proper Hölder Divergence

目录 Hlder Statistical Pseudo DivergenceProper Hlder Divergence Hlder Statistical Pseudo Divergence Hlder Statistical Pseudo Divergence是一种度量两个概率分布 p p p 和 q q q差异的方法&#xff0c;它基于Hlder不等式。定义如下&#xff1a; D α H ( p : q ) 1 …

时序数据库IoTDB基于云原生的创新与实践

概述 Apache IoTDB 是一款独立自研的物联网时序数据库&#xff0c;作为 Apache 基金会的顶级项目&#xff0c;它融合了产学研的优势&#xff0c;拥有深厚的科研基底。IoTDB 采用了端边云协同的架构&#xff0c;专为物联网设计&#xff0c;致力于提供极致的性能。 数据模型 I…

git 如何解决分支合并冲突(VS code可视化解决+gitLab网页解决)

1、定义&#xff1a;两个分支修改了同一文件的同一行代码&#xff0c;无法自动决定如何合并代码&#xff0c;需要人工干预的情况。&#xff08;假设A提交了文件a,此时B在未拉取代码的情况下&#xff0c;直接提交是会报错的&#xff0c;此时需要拉取之后再提交才会成功&#xff…

系统架构设计师(一):计算机系统基础知识

系统架构设计师&#xff08;一&#xff09;&#xff1a;计算机系统基础知识 引言计算机系统概述计算机硬件处理器处理器指令集常见处理器 存储器总线总线性能指标总线分类按照总线在计算机中所处的位置划分按照连接方式分类按照功能分类 接口接口分类 计算机软件文件系统文件类…

聊一聊接口测试中缓存处理策略

目录 一、强制绕过缓存 添加时间戳参数 修改请求头 二、主动清除缓存 清除本地缓存 清除服务端缓存&#xff08;需权限&#xff09; 清除CDN缓存 三、测试缓存逻辑 首次请求获取数据 记录响应头中的缓存标识​​​​​ 验证缓存生效 测试缓存过期​​​​​​​ 四…

机器学习算法-逻辑回归

今天我们用 「预测考试是否及格」 的例子来讲解逻辑回归&#xff0c;从原理到实现一步步拆解&#xff0c;保证零基础也能懂&#xff01; &#x1f3af; 例子背景 假设你是班主任&#xff0c;要根据学生的「学习时间」预测「是否及格」&#xff0c;手上有以下数据&#xff1a;…

【论文解读】CVPR2023 PoseFormerV2:3D人体姿态估计(附论文地址)

论文链接&#xff1a;https://arxiv.org/pdf/2303.17472 源码链接&#xff1a;https://github.com/QitaoZhao/PoseFormerV2 Abstract 本文提出了 PoseFormerV2&#xff0c;通过探索频率域来提高 3D 人体姿态估计的效率和鲁棒性。PoseFormerV2 利用离散余弦变换&#xff08;DC…

DRW - 加密市场预测

1.数据集描述 在本次比赛中&#xff0c;数据集包含加密市场的分钟级历史数据。您的挑战是预测未来的加密货币市场价格走势。这是一项kaggle社区预测竞赛&#xff0c;您可以以 CSV 文件的形式或通过 Kaggle Notebooks 提交您的预测。有关使用 Kaggle Notebooks 的更多详细信息&a…

嵌入式Linux系统中的启动分区架构

在嵌入式Linux系统架构中,Linux内核、设备树(Device Tree)与引导配置文件构成了系统启动的基础核心。如何安全、高效地管理这些关键文件,直接影响到系统的稳定性与可维护性。近年来,越来越多的嵌入式Linux开发者选择将启动相关文件从传统的“混合存放”方式,转向采用独立…

用户资产化视角下开源AI智能名片链动2+1模式S2B2C商城小程序的应用研究

摘要&#xff1a;在数字化时代&#xff0c;平台流量用户尚未完全转化为企业的数字资产&#xff0c;唯有将其沉淀至私域流量池并实现可控、随时触达&#xff0c;方能成为企业重要的数字资产。本文从用户资产化视角出发&#xff0c;探讨开源AI智能名片链动21模式S2B2C商城小程序在…

Spring是如何实现属性占位符解析

Spring属性占位符解析 核心实现思路1️⃣ 定义占位符处理器类2️⃣ 处理 BeanDefinition 中的属性3️⃣ 替换具体的占位符4️⃣ 加载配置文件5️⃣ Getter / Setter 方法 源码见&#xff1a;mini-spring 在使用 Spring 框架开发过程中&#xff0c;为了实现配置的灵活性&#xf…

【大模型面试每日一题】Day 31:LoRA微调方法中低秩矩阵的秩r如何选取?

【大模型面试每日一题】Day 31&#xff1a;LoRA微调方法中低秩矩阵的秩r如何选取&#xff1f; &#x1f4cc; 题目重现 &#x1f31f;&#x1f31f; 面试官:LoRA微调方法中低秩矩阵的秩r如何选取&#xff1f;&#xff1a; #mermaid-svg-g5hxSxV8epzWyP98 {font-family:"…

字节golang后端二面

前端接口使用restful格式&#xff0c;post与get的区别是什么&#xff1f; HTTP网络返回的状态码有哪些&#xff1f; go语言切片与数组的区别是什么&#xff1f; MySQL实现并发安全避免两个事务同时对一个记录写操作的手段有哪些&#xff1f; 如何实现业务的幂等性&#xff08;在…

Spring Security安全实践指南

安全性的核心价值 用户视角的数据敏感性认知 从终端用户角度出发,每个应用程序都涉及不同级别的数据敏感度。以电子邮件服务与网上银行为例:前者内容泄露可能仅造成隐私困扰,而后者账户若被操控将直接导致财产损失。这种差异体现了安全防护需要分级实施的基本原则: // 伪…