前言
逆水行舟,不进则退!!!
目录
项目背景
接口测试
性能测试
压力测试
UI测试
项目背景
项目名称: 论坛系统
项目概述: 论坛系统是一个基于Spring Boot和MySQL的Web应用程序,旨在为用户提供一个交流和分享信息的平台。该系统允许用户注册账户,创建和管理个人资料,发布和管理帖子,并进行帖子的评论和回复。此外,用户还可以私信其他用户,查看最新的帖子和热门话题。系统设计为响应快速、界面友好,并具备一定的安全性措施,如用户身份验证和数据加密存储。
技术栈:
- 前端技术: HTML, CSS, JavaScript
- 后端技术: Spring Boot 3.X, Spring MVC, MyBatis
- 数据库: MySQL 5.7
- 开发工具: IntelliJ IDEA 2022.1.4
- 部署平台: Alibaba Cloud (阿里云)
功能特性:
- 用户管理: 用户注册、登录、修改个人信息。
- 帖子管理: 发布帖子、查看帖子列表、编辑和删除帖子。
- 评论与回复: 对帖子进行评论和回复,支持多级回复。
- 消息通知: 用户收到新消息时的实时通知和私信功能。
- 安全性: 用户密码采用加盐哈希存储,使用JWT进行用户认证和授权。
测试目的:
- 确保系统的稳定性和可靠性,以应对高并发和异常情况。
- 验证系统功能的完整性和正确性,确保用户能够顺利执行各项操作。
- 检测并优化系统的性能,确保在各种负载情况下保持良好的响应速度和用户体验。
接口测试
测试报告: 注册接口测试
1. 概述
- 本报告涵盖了注册接口的测试结果和分析。
- 测试目的是验证注册功能是否按预期工作,包括成功和失败的情况。
2. 测试环境
- 测试工具: Postman(参数化测试)
- 环境变量: 使用环境变量管理测试环境和参数化测试数据
- 后端技术栈: Spring Boot 3.2.6, SpringMVC, MyBatis 3.0.3
- 数据库: MySQL 5.7
- 部署: 阿里云服务器,Ubuntu操作系统
3. 测试用例
编号 | 测试用例 | 描述 | 预期结果 | 实际结果 | 状态 |
1 | 注册成功 | 使用有效的用户名和密码注册 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 通过 |
2 | 用户名重复 | 使用已经存在的用户名注册 | 返回状态码:200, 自定义状态码:1101 message: 用户已存在 | 返回状态码:200, 自定义状态码:1101 message: 用户已存在 | 通过 |
3 | 密码不一致 | 密码和确认密码不一致 | 返回状态码:200, 自定义状态码:1105 message: 两次输入的密码不一致 | 返回状态码:200, 自定义状态码:1105 message: 两次输入的密码不一致 | 通过 |
4 | 缺少username参数 | 发送的参数中username参数为空 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 通过 |
5 | 缺少nickname参数 | 发送的参数中nickname参数为空 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 通过 |
6 | 缺少password参数 | 发送的参数中password参数为空 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 返回状态码:200, 自定义状态码:1105 message: 两次输入的密码不一致 | 不通过 |
7 | 缺少passwordRepeat参数 | 发送的参数中passwordRepeat参数为空 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 返回状态码:200, 自定义状态码:1105 message: 两次输入的密码不一致 | 不通过 |
8 | 无效用户名格式 | username字段为空字符串 | 返回状态码:200, 自定义状态码:1108 message: 无效的用户名格式 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 不通过 |
9 | 无效的昵称格式 | nickname字段为空字符串 | 返回状态码:200, 自定义状态码:1109 message: 无效的昵称格式 | 返回状态码:200, 自定义状态码:1002 message: 参数校验失败 | 不通过 |
10 | 无效的密码格式 | password 和 passwordRepeat字段为空字符串 | 返回状态码:200, 自定义状态码:1110 message: 无效的密码格式 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 不通过 |
11 | username最大长度 | username字段的字符长度超过24位 | 返回状态码:200, 自定义状态码:1108 message: 无效的用户名格式 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 不通过 |
12 | nickname最大长度 | nickname字段的字符长度超过24位 | 返回状态码:200, 自定义状态码:1109 message: 无效的昵称格式 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 不通过 |
13 | 密码的最大长度 | passwordRepeat 与 password的长度超过32位 | 返回状态码:200, 自定义状态码:1110 message: 无效的密码格式 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 不通过 |
14 | 密码的最小长度 | passwordRepeat 与 password的长度小于6位 | 返回状态码:200, 自定义状态码:1110 message: 无效的密码格式 | 返回状态码:200, 自定义状态码:0 message: 成功注册 | 不通过 |
4. 测试结果
- 总共执行测试用例数 : 14
- 通过测试用例数: 5
- 失败测试用例数: 9
5. 总结
- 本次注册接口测试共执行了14条测试用例, 其中5条测试用例通过, 9条测试用例失败, 主要的问题集中在参数校验和返回信息的具体性上, 建议后端根据具体的失败情况优化接口参数校验逻辑和返回信息, 以提高接口的健壮性和用户体验.
7, 备注
- 测试日期: 2024-06-20
- 测试人员: 章鱼哥
性能测试
性能测试报告
1. 测试概述
- 测试目标:验证用户注册接口在不同并发用户数量下的性能表现
- 测试工具:JMeter
- 测试环境:8核CPU,16GB内存,百兆网络
- 测试日期:2024年7月1日 - 2024年7月5日
- 测试接口:/user/register
2. 测试方法
- 测试步骤:从1000个并发用户开始,每次增加1000个用户,直到达到10000个用户
- 测试指标:平均响应时间、最大响应时间、最小响应时间、吞吐量、成功率、错误率
3. 测试结果
并发用户数量:1000
- 平均响应时间:9 ms
- 最大响应时间:69 ms
- 最小响应时间:1 ms
- 吞吐量:856.2 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 1000 个并发用户下,系统性能表现良好,响应时间极短,吞吐量高,所有请求成功完成,无错误。
并发用户数量:2000
- 平均响应时间:26 ms
- 最大响应时间:255 ms
- 最小响应时间:1 ms
- 吞吐量:949.2 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 2000 个并发用户下,系统性能依然较好,响应时间略有增加,但仍然保持在可接受范围内。吞吐量有所提升,成功率和错误率保持良好。
并发用户数量:3000
- 平均响应时间:540 ms
- 最大响应时间:1027 ms
- 最小响应时间:2 ms
- 吞吐量:1303.2 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 3000 个并发用户下,平均响应时间显著增加,最大响应时间突破 1 秒。吞吐量继续增加,但需要注意响应时间的增长。
并发用户数量:4000
- 平均响应时间:757 ms
- 最大响应时间:1602 ms
- 最小响应时间:2 ms
- 吞吐量:1346.3 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 4000 个并发用户下,响应时间进一步增加,最大响应时间接近 2 秒。吞吐量达到最高值,需要重点关注系统在高并发下的响应时间表现。
并发用户数量:5000
- 平均响应时间:1041 ms
- 最大响应时间:2022 ms
- 最小响应时间:5 ms
- 吞吐量:1222.2 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 5000 个并发用户下,响应时间继续增加,最大响应时间超过 2 秒。吞吐量有所下降,表明系统在高并发下的处理能力开始受到影响。
并发用户数量:6000
- 平均响应时间:968 ms
- 最大响应时间:2277 ms
- 最小响应时间:5 ms
- 吞吐量:1349.2 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 6000 个并发用户下,平均响应时间有所减少,但最大响应时间仍然较长。吞吐量回升,需要进一步分析响应时间的波动原因。
并发用户数量:7000
- 平均响应时间:1166 ms
- 最大响应时间:2902 ms
- 最小响应时间:7 ms
- 吞吐量:1292.5 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 7000 个并发用户下,响应时间和最大响应时间均增加。吞吐量保持较高水平,但系统开始显现出高并发下的性能瓶颈。
并发用户数量:8000
- 平均响应时间:1466 ms
- 最大响应时间:3252 ms
- 最小响应时间:2 ms
- 吞吐量:1253.1Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 8000 个并发用户下,平均和最大响应时间均显著增加。吞吐量略有下降,系统在高并发下的响应能力需要优化。
并发用户数量:9000
- 平均响应时间:1757 ms
- 最大响应时间:3049 ms
- 最小响应时间:3 ms
- 吞吐量:1264.6 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 9000 个并发用户下,响应时间增加幅度较大。虽然吞吐量和成功率保持良好,但系统需要进一步优化以提升高并发下的响应速度。
并发用户数量:10000
- 平均响应时间:1956 ms
- 最大响应时间:3366 ms
- 最小响应时间:2 ms
- 吞吐量:1052 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 10000 个并发用户下,响应时间接近 2 秒,最大响应时间超过 3 秒。吞吐量下降较为明显,系统在超高并发下的性能表现需要重点关注和优化。
继续增加测试结果,直到达到系统的最大承受能力
并发用户数量:12000
- 平均响应时间:1784 ms
- 最大响应时间:3448 ms
- 最小响应时间:3 ms
- 吞吐量:1255.2 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 12000 个并发用户下,平均响应时间有所下降,但最大响应时间略有上升。吞吐量有所提高,系统依然保持稳定。
并发用户数量:14000
- 平均响应时间:2608 ms
- 最大响应时间:7309 ms
- 最小响应时间:3 ms
- 吞吐量:983.8 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 14000 个并发用户下,平均响应时间和最大响应时间显著上升,吞吐量有所下降,系统开始表现出压力迹象。
并发用户数量:16000
- 平均响应时间:2742 ms
- 最大响应时间:7127 ms
- 最小响应时间:3 ms
- 吞吐量:1261.7 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 16000 个并发用户下,系统表现依然稳定,但响应时间较高,需进一步优化。
并发用户数量:18000
- 平均响应时间:2742 ms
- 最大响应时间:7127 ms
- 最小响应时间:3 ms
- 吞吐量:1261.7 Throughput
- 成功率:100%
- 错误率:0%
- 备注:与 16000 并发用户下的结果相似,表明系统在此并发量下已经达到某种瓶颈。
并发用户数量:20000
- 平均响应时间:3043 ms
- 最大响应时间:8107 ms
- 最小响应时间:18 ms
- 吞吐量:1200.6 Throughput
- 成功率:100%
- 错误率:0%
- 备注:在 20000 个并发用户下,响应时间继续上升,最大响应时间显著增加,系统在此并发量下的性能需要进一步优化。
并发用户数量:30000
- 平均响应时间:3080 ms
- 最大响应时间:9165 ms
- 最小响应时间:3 ms
- 吞吐量:983.8 Throughput
- 成功率:98.15%
- 错误率:1.85%
- 备注:在 30000 个并发用户下,响应时间明显增加,最大响应时间接近 10 秒,出现一定比例的错误,表明系统已经超出其最大承受能力。
4. 分析与讨论
- 系统稳定性:系统在 10000 到 20000 个并发用户下表现稳定,成功率保持 100%,但响应时间较高,需要优化。
- 性能瓶颈: 从 30000 个并发用户开始,系统响应时间显著增加,出现错误,表明系统达到了其最大承受能力。
- 错误分析:并发用户数量超过30000时,出现“数据库连接超时”错误
- 优化建议:需要优化系统的并发处理能力,减少响应时间,特别是针对高并发下的性能表现。
压力测试
压力测试报告
1. 测试概述
- 测试目标:验证用户注册接口在高负载下的稳定性
- 测试工具:JMeter
- 测试环境:8核CPU,16GB内存,百兆网络
- 测试日期:2024年7月1日 - 2024年7月5日
- 测试接口:/user/register
2. 测试方法
- 测试步骤:从22000个并发用户开始,每次增加2000个用户,直到系统出现明显的性能退化或崩溃.
- 测试指标:平均响应时间、最大响应时间、最小响应时间、吞吐量、成功率、错误率
3. 测试结果
并发用户数量 | 平均响应时间(ms) | 最大响应时间(ms) | 最小响应时间(ms) | 吞吐量(Throughput) | 成功率 | 错误率 | 备注 |
22000 | 2873 | 5545 | 12 | 1235.7 | 100% | 0% | |
24000 | 3343 | 6214 | 14 | 1084.5 | 100% | 0% | |
26000 | 2248 | 5445 | 11 | 1165.7 | 100% | 0% | |
28000 | 2255 | 4842 | 16 | 1064.5 | 100% | 0% | |
30000 | 3846 | 7953 | 23 | 1031 | 99.41% | 0.59% | |
32000 | 4914 | 12180 | 8 | 949.0 | 95.52% | 4.48% |
4. 性能趋势分析:
随着并发用户数量的增加,平均响应时间和最大响应时间逐步增加,吞吐量逐步下降。
成功率总体上保持在100%,但在32000并发用户时,成功率下降至95.52%,错误率升高至4.48%。
系统负载能力 :
系统在22000至28000并发用户之间表现稳定,虽然响应时间和吞吐量有所波动,但错误率保持在较低水平。
超过28000并发用户后,系统开始出现明显的性能下降,特别是在32000并发用户时,响应时间急剧增加,成功率下降。
优化建议
硬件和资源优化: 考虑增加服务器硬件资源,如CPU、内存等,以提升系统的并发处理能力。
代码和性能优化: 优化代码逻辑和数据库查询,减少响应时间和提高吞吐量。
负载均衡和缓存策略: 考虑使用负载均衡技术和缓存策略,分担服务器压力和优化数据访问效率。
- 分析和建议
- 测试步骤:从22000个并发用户开始,每次增加2000个用户,直到系统出现明显的性能退化或崩溃.
- 测试指标:平均响应时间、最大响应时间、最小响应时间、吞吐量、成功率、错误率
- 测试目标:验证用户注册接口在高负载下的稳定性
- 测试工具:JMeter
- 测试环境:8核CPU,16GB内存,百兆网络
- 测试日期:2024年7月1日 - 2024年7月5日
- 测试接口:/user/register
UI测试
注册界面UI测试报告
1. 测试概述
项目名称: 论坛系统
测试日期: 2024年7月5日
测试人员: 章鱼哥
测试目标: 验证用户注册页面的功能,包括有效注册, 无效注册, 空字段处理等。
2. 测试环境
操作系统: Windows 10
浏览器: Google Chrome 版本 126.0.6478.127
WebDriver: ChromeDriver 版本 126.0.6478.127
开发框架: Spring Boot 3.2.6
Selenium 版本: 4.1.0
3. 测试用例
测试用例1:有效的用户名和密码注册
- 步骤:
- 打开注册页面
- 输入有效的用户名, 昵称, 密码和确认密码
- 点击注册按钮
- 预期结果:
- 注册成功并跳转到登录页
- 当前URL应为:http://localhost:8080/home
- 实际结果:
- 成功注册,页面跳转正确
- 结果:符合预期, 通过
- 代码如下:
-
@Test/** 成功注册用例* */public void test1() {// 找到用户名, 昵称, 密码, 确认密码的输入框, 并输入文本WebElement usernameField = driver.findElement(By.id("username"));WebElement nicknameField = driver.findElement(By.id("nickname"));WebElement passwordField = driver.findElement(By.id("password"));WebElement passwordRepeatField = driver.findElement(By.id("passwordRepeat"));usernameField.sendKeys("UI测试用例1");nicknameField.sendKeys("成功注册");passwordField.sendKeys("111111");passwordRepeatField.sendKeys("111111");// 找到同意条款框, 并点击WebElement checkbox = driver.findElement(By.id("policy"));checkbox.click();// 找到注册按钮, 并点击WebElement loginButton = driver.findElement(By.id("submit"));loginButton.click();// 等待一段时间try {Thread.sleep(5000); // 暂停 5 秒钟} catch (InterruptedException e) {e.printStackTrace();}}
测试用例2:已存在的用户名注册
- 步骤:
- 打开注册页面
- 输入已存在的用户名
- 点击注册按钮
- 预期结果:
- 注册失败,显示错误信息 "用户名已存在"
- 实际结果:
- 注册失败,只显示错误警告
- 结果:不符合预期, 不通过
- 代码如下:
-
@Test/** 无效注册用例* 使用已经注册的用户名进行注册* */public void test2() {// 找到用户名, 昵称, 密码, 确认密码的输入框, 并输入文本WebElement usernameField = driver.findElement(By.id("username"));WebElement nicknameField = driver.findElement(By.id("nickname"));WebElement passwordField = driver.findElement(By.id("password"));WebElement passwordRepeatField = driver.findElement(By.id("passwordRepeat"));usernameField.sendKeys("UI测试用例1");nicknameField.sendKeys("无效注册");passwordField.sendKeys("111111");passwordRepeatField.sendKeys("111111");// 找到同意条款框, 并点击WebElement checkbox = driver.findElement(By.id("policy"));checkbox.click();// 找到注册按钮, 并点击WebElement loginButton = driver.findElement(By.id("submit"));loginButton.click();// 等待一段时间try {Thread.sleep(5000); // 暂停 5 秒钟} catch (InterruptedException e) {e.printStackTrace();}}
测试用例3:空用户名或密码注册
- 步骤:
- 打开注册页面
- 不输入用户名, 昵称, 密码和确认密码
- 点击注册按钮
- 预期结果:
- 注册未执行,标红所有输入框, 并提示不能为空
- 实际结果:
- 注册未执行,标红所有输入框, 并提示不能为空
- 结果:符合预期, 通过
- 代码如下:
-
@Test/** 空白用户名注册用例* 对各个字段都不进行填写, 检验是否有错误提示* */public void test3() {// 找到用户名, 昵称, 密码, 确认密码的输入框, 并输入文本WebElement usernameField = driver.findElement(By.id("username"));WebElement nicknameField = driver.findElement(By.id("nickname"));WebElement passwordField = driver.findElement(By.id("password"));WebElement passwordRepeatField = driver.findElement(By.id("passwordRepeat"));usernameField.sendKeys("");nicknameField.sendKeys("");passwordField.sendKeys("");passwordRepeatField.sendKeys("");// 找到同意条款框, 并点击WebElement checkbox = driver.findElement(By.id("policy"));checkbox.click();// 找到注册按钮, 并点击WebElement loginButton = driver.findElement(By.id("submit"));loginButton.click();// 等待一段时间try {Thread.sleep(5000); // 暂停 5 秒钟} catch (InterruptedException e) {e.printStackTrace();}}
测试用例4:不选择同意条款
- 步骤:
- 打开注册页面
- 输入用户名, 昵称, 密码和确认密码
- 不勾选同意条款
- 点击注册按钮
- 预期结果:
- 注册未执行, 标红条款勾选框
- 实际结果:
- 测试未执行, 标红条款勾选框,
- 结果: 符合预期, 通过
- 代码如下:
-
@Test/** 失败注册用例* 不勾选同意条款* */public void test4() {// 找到用户名, 昵称, 密码, 确认密码的输入框, 并输入文本WebElement usernameField = driver.findElement(By.id("username"));WebElement nicknameField = driver.findElement(By.id("nickname"));WebElement passwordField = driver.findElement(By.id("password"));WebElement passwordRepeatField = driver.findElement(By.id("passwordRepeat"));usernameField.sendKeys("UI测试用例4");nicknameField.sendKeys("成功注册");passwordField.sendKeys("111111");passwordRepeatField.sendKeys("111111");// 找到同意条款框, 不点击WebElement checkbox = driver.findElement(By.id("policy"));//checkbox.click();// 找到注册按钮, 并点击WebElement loginButton = driver.findElement(By.id("submit"));loginButton.click();// 等待一段时间try {Thread.sleep(5000); // 暂停 5 秒钟} catch (InterruptedException e) {e.printStackTrace();}}
测试用例5:注册用户名的最大边界(20个字符)
- 步骤:
- 打开注册页面
- 输入用户名(21个字符), 昵称, 密码和确认密码
- 点击注册按钮
- 预期结果:
- 注册未执行, 提示用户名长度超出限制
- 实际结果:
- 测试未执行, 只提供了错误, 并未显示具体的错误信息
- 结果: 不符合预期, 不通过
- 代码如下:
-
@Test/** 测试注册名称边界与密码边界用例* 检测时候有限制用户名和密码的最大长度* 用户名的最大长度为20个字符* 密码无上限* */public void test5() {// 找到用户名, 昵称, 密码, 确认密码的输入框, 并输入文本WebElement usernameField = driver.findElement(By.id("username"));WebElement nicknameField = driver.findElement(By.id("nickname"));WebElement passwordField = driver.findElement(By.id("password"));WebElement passwordRepeatField = driver.findElement(By.id("passwordRepeat"));usernameField.sendKeys("12345678910111213141");nicknameField.sendKeys("成功注册");passwordField.sendKeys("111111111111111111111111111111111111111111111111111111111111111111111111111111111111");passwordRepeatField.sendKeys("111111111111111111111111111111111111111111111111111111111111111111111111111111111111");// 找到同意条款框, 并点击WebElement checkbox = driver.findElement(By.id("policy"));checkbox.click();// 找到注册按钮, 并点击WebElement loginButton = driver.findElement(By.id("submit"));loginButton.click();// 等待一段时间try {Thread.sleep(5000); // 暂停 5 秒钟} catch (InterruptedException e) {e.printStackTrace();}}
测试用例6:注册密码的最小边界(6个字符)
- 步骤:
- 打开注册页面
- 输入用户名, 昵称, 密码(5个字符) 和确认密码
- 点击注册按钮
- 预期结果:
- 注册未执行, 显示密码长度超出限制
- 实际结果:
- 测试执行成功, 并未显示任何错误信息 , 并且跳转到了登录页面
- 结果: 不符合预期, 不通过
- 代码如下:
-
@Test/** 测试注册密码最小边界用例** */public void test6() {// 找到用户名, 昵称, 密码, 确认密码的输入框, 并输入文本WebElement usernameField = driver.findElement(By.id("username"));WebElement nicknameField = driver.findElement(By.id("nickname"));WebElement passwordField = driver.findElement(By.id("password"));WebElement passwordRepeatField = driver.findElement(By.id("passwordRepeat"));usernameField.sendKeys("UI测试用例6");nicknameField.sendKeys("成功注册");passwordField.sendKeys("1");passwordRepeatField.sendKeys("1");// 找到同意条款框, 并点击WebElement checkbox = driver.findElement(By.id("policy"));checkbox.click();// 找到注册按钮, 并点击WebElement loginButton = driver.findElement(By.id("submit"));loginButton.click();// 等待一段时间try {Thread.sleep(5000); // 暂停 5 秒钟} catch (InterruptedException e) {e.printStackTrace();}}
4. 测试结果总结
测试用例编号 | 预期结果 | 实际结果 | 测试结果 | 备注 |
测试用例1 | 预期 | 符合 | 通过 | |
测试用例2 | 预期 | 不符合 | 不通过 | |
测试用例3 | 预期 | 符合 | 通过 | |
测试用例4 | 预期 | 符合 | 通过 | |
测试用例5 | 预期 | 不符合 | 不通过 | |
测试用例6 | 预期 | 不符合 | 不通过 |
5. 结论
通过以上测试分析, 发现了几个问题需要改进:
1, 在注册失败时, 需要显示更具体的错误信息, 如用户名已存在, 密码长度不足, 或者密码长度超出范围, 以及 用户名长度超出范围等.
2, 对于边界情况, 如密码的最小长度需要添加验证逻辑, 并提供明确的用户提示信息.
3, 确保注册页面的输入框和按钮状态正确反馈用户的操作和状态.
我是专注学习的章鱼哥~