test:添加认证系统测试套件

- 添加UI测试场景,支持模拟各种认证场景
- 实现API测试脚本,覆盖登录、注册、验证码等接口
- 添加测试文档,说明测试用例和预期结果
- 支持自动化测试和手动测试验证
This commit is contained in:
2025-12-24 20:37:33 +08:00
parent c6bcca4e7f
commit 47cfc14f68
7 changed files with 1511 additions and 0 deletions

165
tests/auth/README.md Normal file
View File

@@ -0,0 +1,165 @@
# 认证UI测试
这个文件夹包含了登录和注册界面的UI响应测试具有美观优雅的反馈系统。
## 文件说明
- `auth_ui_test.tscn` - 测试场景文件
- `auth_ui_test.gd` - 测试脚本
- `README.md` - 本说明文件
## 如何运行测试
### 方法1在Godot编辑器中运行
1. 在Godot编辑器中打开 `tests/auth/auth_ui_test.tscn` 文件
2. 点击编辑器右上角的"播放场景"按钮或按F6键
3. 如果仍然跳转到主场景,请尝试以下步骤:
- 确保当前打开的是测试场景文件
- 在场景面板中右键点击根节点,选择"Change Scene"
- 或者在项目设置中临时更改主场景为测试场景
### 方法2通过代码运行
在任何脚本中添加以下代码来切换到测试场景:
```gdscript
get_tree().change_scene_to_file("res://tests/auth/auth_ui_test.tscn")
```
## 界面布局
### 左侧:认证界面
- 完整的登录和注册界面
- 实时表单验证
- Toast消息显示
- 字段错误提示
### 右侧:测试控制面板
#### 🧪 UI响应测试标题
#### 📋 测试反馈面板
- **智能反馈系统**:实时显示测试执行状态
- **颜色编码**
- 🔵 蓝色:信息提示
- 🟢 绿色:成功响应
- 🔴 红色:错误响应
- **详细信息**
- 测试名称和类型
- HTTP状态码
- 响应消息和错误代码
- 预期的UI反馈效果
- **自动滚动**:新消息自动滚动到可见区域
#### 🎯 测试用例按钮
16个精美设计的测试按钮按功能分组
## 测试功能
### 登录测试4个
-**登录成功**状态码200
- 预期绿色Toast "登录成功!正在进入鲸鱼镇...",跳转到主场景
-**用户名或密码错误**状态码401
- 预期红色Toast "用户名或密码错误,请检查后重试"
-**用户不存在**状态码404
- 预期红色Toast "用户不存在,请先注册"
-**参数错误**状态码400
- 预期红色Toast根据具体错误显示
### 发送验证码测试5个
-**发送成功**状态码200
- 预期绿色Toast "验证码已发送到您的邮箱"
-**邮箱格式错误**状态码400
- 预期红色Toast "请输入有效的邮箱地址"
-**请求过频**状态码429
- 预期红色Toast "请求过于频繁,请稍后再试"
-**服务器错误**状态码500
- 预期红色Toast "服务器繁忙,请稍后再试"
-**网络错误**状态码0
- 预期红色Toast "网络连接失败,请检查网络连接"
### 邮箱验证测试3个
-**验证成功**状态码200
- 预期绿色Toast "邮箱验证成功,正在注册..."
-**验证码错误**状态码400
- 预期红色Toast "验证码错误或已过期"
-**验证码不存在**状态码404
- 预期红色Toast "请先获取验证码"
### 注册测试6个
-**注册成功**状态码201
- 预期绿色Toast "注册成功!欢迎加入鲸鱼镇",切换到登录界面
-**参数错误**状态码400
- 预期红色Toast根据具体错误显示
-**缺少验证码**状态码400
- 预期红色Toast "请先获取并输入邮箱验证码"
-**用户已存在**状态码409
- 预期红色Toast "用户名或邮箱已被使用,请换一个"
-**请求过频**状态码429
- 预期红色Toast "注册请求过于频繁,请稍后再试"
-**服务器错误**状态码500
- 预期红色Toast "注册失败,请稍后再试"
## 测试步骤
1. **启动测试场景**
- 运行测试场景后,右侧反馈面板会显示欢迎信息和使用说明
2. **准备测试数据**
- 在左侧认证界面切换到注册界面
- 填写测试数据:
- 用户名testuser
- 邮箱test@example.com
- 密码password123
- 确认密码password123
- 验证码123456
3. **执行测试**
- 点击右侧对应的测试按钮
- 观察反馈面板中的详细信息:
- 🚀 测试开始提示
- 📡 请求类型和状态码
- ⚡ HTTP响应模拟
- 🎯 预期UI反馈说明
- ✅/❌ 测试完成状态
4. **观察UI反馈**
- 左侧界面的实际反馈效果
- Toast消息的颜色和内容
- 字段错误提示的显示
- 按钮状态的变化
## 反馈系统特色
### 🎨 美观设计
- 使用Emoji图标增强视觉效果
- 颜色编码区分不同状态
- 圆角边框和阴影效果
- 按钮分组和分隔符
### 📊 详细分析
- 实时显示测试执行过程
- 预期vs实际效果对比
- HTTP响应详细解析
- 错误代码和消息说明
### 🔄 交互体验
- 自动滚动到最新消息
- 按钮悬停效果
- 平滑的颜色过渡
- 响应式布局
## 注意事项
- 测试场景会自动断开`login_success`信号,避免跳转到主场景
- 按ESC键可以优雅退出测试显示退出提示
- 所有测试都是模拟的,不会发送真实的网络请求
- 反馈面板会保留测试历史,便于对比分析
- 测试按钮按功能分组,每组之间有分隔符
## 预期行为验证
这个测试系统不仅模拟后端响应还会告诉你每种情况下应该看到什么UI反馈帮助你验证
1. **Toast消息系统**是否正常工作
2. **字段验证错误**是否正确显示
3. **按钮状态管理**是否符合预期
4. **用户体验流程**是否顺畅
通过对比预期效果和实际效果可以快速发现UI反馈系统中的问题并进行修复。

464
tests/auth/auth_ui_test.gd Normal file
View File

@@ -0,0 +1,464 @@
extends Control
# 认证UI测试场景
# 用于测试登录和注册界面的各种响应情况
@onready var auth_scene: Control = $AuthScene
@onready var test_panel: Panel = $TestPanel
@onready var test_buttons: VBoxContainer = $TestPanel/VBoxContainer/ScrollContainer/TestButtons
@onready var feedback_panel: Panel = $TestPanel/VBoxContainer/FeedbackPanel
@onready var feedback_text: RichTextLabel = $TestPanel/VBoxContainer/FeedbackPanel/FeedbackContainer/FeedbackScroll/FeedbackText
# 反馈样式 - 动态创建
var feedback_styles = {}
var test_scenarios = [
{
"name": "✅ 登录成功",
"type": "login",
"response_code": 200,
"response_data": {
"success": true,
"data": {
"user": {
"id": "123",
"username": "testuser",
"email": "test@example.com"
},
"token": "jwt_token_here"
},
"message": "登录成功"
}
},
{
"name": "❌ 登录失败-用户名或密码错误",
"type": "login",
"response_code": 401,
"response_data": {
"success": false,
"message": "用户名或密码错误",
"error_code": "INVALID_CREDENTIALS"
}
},
{
"name": "❌ 登录失败-用户不存在",
"type": "login",
"response_code": 404,
"response_data": {
"success": false,
"message": "用户不存在",
"error_code": "USER_NOT_FOUND"
}
},
{
"name": "❌ 登录失败-参数错误",
"type": "login",
"response_code": 400,
"response_data": {
"success": false,
"message": "用户名格式错误",
"error_code": "INVALID_PARAMETERS"
}
},
{
"name": "✅ 发送验证码成功",
"type": "send_code",
"response_code": 200,
"response_data": {
"success": true,
"data": {"verification_code": "123456"},
"message": "验证码已发送"
}
},
{
"name": "❌ 发送验证码-邮箱格式错误",
"type": "send_code",
"response_code": 400,
"response_data": {
"success": false,
"message": "邮箱格式错误",
"error_code": "INVALID_EMAIL"
}
},
{
"name": "❌ 发送验证码-请求过频",
"type": "send_code",
"response_code": 429,
"response_data": {
"success": false,
"message": "请求过于频繁",
"error_code": "TOO_MANY_REQUESTS"
}
},
{
"name": "❌ 发送验证码-服务器错误",
"type": "send_code",
"response_code": 500,
"response_data": {
"success": false,
"message": "服务器内部错误",
"error_code": "INTERNAL_ERROR"
}
},
{
"name": "❌ 发送验证码-网络错误",
"type": "send_code",
"response_code": 0,
"response_data": {}
},
{
"name": "✅ 邮箱验证成功",
"type": "verify_email",
"response_code": 200,
"response_data": {
"success": true,
"message": "邮箱验证成功"
}
},
{
"name": "❌ 邮箱验证-验证码错误",
"type": "verify_email",
"response_code": 400,
"response_data": {
"success": false,
"message": "验证码错误或已过期",
"error_code": "INVALID_CODE"
}
},
{
"name": "❌ 邮箱验证-验证码不存在",
"type": "verify_email",
"response_code": 404,
"response_data": {
"success": false,
"message": "验证码不存在",
"error_code": "CODE_NOT_FOUND"
}
},
{
"name": "✅ 注册成功",
"type": "register",
"response_code": 201,
"response_data": {
"success": true,
"data": {
"user": {
"id": "123",
"username": "testuser",
"email": "test@example.com"
}
},
"message": "注册成功"
}
},
{
"name": "❌ 注册失败-参数错误",
"type": "register",
"response_code": 400,
"response_data": {
"success": false,
"message": "用户名格式错误",
"error_code": "INVALID_USERNAME"
}
},
{
"name": "❌ 注册失败-缺少验证码",
"type": "register",
"response_code": 400,
"response_data": {
"success": false,
"message": "提供邮箱时必须提供邮箱验证码",
"error_code": "REGISTER_FAILED"
}
},
{
"name": "❌ 注册失败-用户已存在",
"type": "register",
"response_code": 409,
"response_data": {
"success": false,
"message": "用户名已存在",
"error_code": "USER_EXISTS"
}
},
{
"name": "❌ 注册失败-请求过频",
"type": "register",
"response_code": 429,
"response_data": {
"success": false,
"message": "注册请求过于频繁请5分钟后再试",
"error_code": "TOO_MANY_REQUESTS",
"throttle_info": {
"limit": 3,
"window_seconds": 300,
"current_requests": 3,
"reset_time": "2025-12-24T11:26:41.136Z"
}
}
},
{
"name": "❌ 注册失败-服务器错误",
"type": "register",
"response_code": 500,
"response_data": {
"success": false,
"message": "服务器内部错误",
"error_code": "INTERNAL_ERROR"
}
}
]
func _ready():
print("🧪 认证UI测试场景已加载")
# 初始化反馈样式
create_feedback_styles()
# 初始化反馈面板
show_feedback("🎯 测试场景已准备就绪", "info")
add_feedback_line("💡 使用说明:")
add_feedback_line("1⃣ 点击下方测试按钮模拟后端响应")
add_feedback_line("2⃣ 观察左侧认证界面的UI反馈")
add_feedback_line("3⃣ 按ESC键退出测试")
add_feedback_line("")
# 确保auth_scene已准备好
if auth_scene == null:
show_feedback("❌ 错误无法找到AuthScene节点", "error")
return
# 等待一帧确保所有节点都已初始化
await get_tree().process_frame
setup_test_buttons()
# 断开auth_scene的login_success信号避免跳转到主场景
if auth_scene.has_signal("login_success"):
var connections = auth_scene.get_signal_connection_list("login_success")
for connection in connections:
auth_scene.disconnect("login_success", connection.callable)
add_feedback_line("🔗 已断开login_success信号连接")
# 创建反馈样式
func create_feedback_styles():
# 成功样式 - 绿色
var success_style = StyleBoxFlat.new()
success_style.bg_color = Color(0.2, 0.8, 0.3, 0.9)
success_style.border_color = Color(0.1, 0.6, 0.2, 1)
success_style.border_width_left = 2
success_style.border_width_top = 2
success_style.border_width_right = 2
success_style.border_width_bottom = 2
success_style.corner_radius_top_left = 8
success_style.corner_radius_top_right = 8
success_style.corner_radius_bottom_left = 8
success_style.corner_radius_bottom_right = 8
# 错误样式 - 红色
var error_style = StyleBoxFlat.new()
error_style.bg_color = Color(0.8, 0.2, 0.2, 0.9)
error_style.border_color = Color(0.6, 0.1, 0.1, 1)
error_style.border_width_left = 2
error_style.border_width_top = 2
error_style.border_width_right = 2
error_style.border_width_bottom = 2
error_style.corner_radius_top_left = 8
error_style.corner_radius_top_right = 8
error_style.corner_radius_bottom_left = 8
error_style.corner_radius_bottom_right = 8
# 信息样式 - 蓝色
var info_style = StyleBoxFlat.new()
info_style.bg_color = Color(0.2, 0.5, 0.8, 0.9)
info_style.border_color = Color(0.1, 0.4, 0.6, 1)
info_style.border_width_left = 2
info_style.border_width_top = 2
info_style.border_width_right = 2
info_style.border_width_bottom = 2
info_style.corner_radius_top_left = 8
info_style.corner_radius_top_right = 8
info_style.corner_radius_bottom_left = 8
info_style.corner_radius_bottom_right = 8
feedback_styles = {
"success": success_style,
"error": error_style,
"info": info_style
}
func setup_test_buttons():
# 创建测试按钮
for i in range(test_scenarios.size()):
var scenario = test_scenarios[i]
var button = Button.new()
button.text = scenario.name
button.custom_minimum_size.y = 35
button.pressed.connect(_on_test_button_pressed.bind(scenario))
# 为按钮添加样式
var style_normal = StyleBoxFlat.new()
style_normal.bg_color = Color(0.9, 0.9, 0.9, 1)
style_normal.border_color = Color(0.7, 0.7, 0.7, 1)
style_normal.border_width_left = 1
style_normal.border_width_top = 1
style_normal.border_width_right = 1
style_normal.border_width_bottom = 1
style_normal.corner_radius_top_left = 4
style_normal.corner_radius_top_right = 4
style_normal.corner_radius_bottom_left = 4
style_normal.corner_radius_bottom_right = 4
var style_hover = style_normal.duplicate()
style_hover.bg_color = Color(0.8, 0.8, 0.8, 1)
button.add_theme_stylebox_override("normal", style_normal)
button.add_theme_stylebox_override("hover", style_hover)
button.add_theme_color_override("font_color", Color(0.2, 0.2, 0.2, 1))
test_buttons.add_child(button)
# 添加分隔符每4个按钮一组
if (i + 1) % 4 == 0 and i < test_scenarios.size() - 1:
var separator = HSeparator.new()
separator.custom_minimum_size.y = 10
test_buttons.add_child(separator)
add_feedback_line("✨ 已创建 %d 个测试按钮" % test_scenarios.size())
func _on_test_button_pressed(scenario: Dictionary):
# 显示测试开始信息
show_feedback("🚀 执行测试: %s" % scenario.name, "info")
add_feedback_line("📡 请求类型: %s" % scenario.type)
add_feedback_line("📊 状态码: %d" % scenario.response_code)
# 确保auth_scene存在
if auth_scene == null:
show_feedback("❌ 错误AuthScene节点不存在", "error")
return
# 模拟HTTP响应
simulate_http_response(scenario)
func simulate_http_response(scenario: Dictionary):
# 设置当前请求类型
auth_scene.current_request_type = scenario.type
# 准备模拟数据
var response_code = scenario.response_code
var response_data = scenario.response_data
var response_text = JSON.stringify(response_data)
var response_body = response_text.to_utf8_buffer()
var headers = PackedStringArray()
add_feedback_line("⚡ 模拟HTTP响应...")
# 模拟HTTP请求完成
auth_scene._on_http_request_completed(0, response_code, headers, response_body)
# 分析响应结果
analyze_response(scenario, response_data)
func analyze_response(scenario: Dictionary, response_data: Dictionary):
var response_code = scenario.response_code
var is_success = response_code >= 200 and response_code < 300
# 显示响应分析
if is_success:
show_feedback("✅ 测试完成 - 成功响应", "success")
else:
show_feedback("❌ 测试完成 - 错误响应", "error")
# 显示详细信息
if response_data.has("message"):
add_feedback_line("💬 响应消息: %s" % response_data.message)
if response_data.has("error_code"):
add_feedback_line("🏷️ 错误代码: %s" % response_data.error_code)
if response_data.has("data"):
add_feedback_line("📦 响应数据: %s" % str(response_data.data))
# 预期的UI反馈
var expected_feedback = get_expected_ui_feedback(scenario)
add_feedback_line("🎯 预期UI反馈: %s" % expected_feedback)
add_feedback_line("─────────────────────")
func get_expected_ui_feedback(scenario: Dictionary) -> String:
var response_code = scenario.response_code
var type = scenario.type
match type:
"login":
match response_code:
200:
return "绿色Toast: 登录成功,跳转到主场景"
400:
return "红色Toast: 登录信息格式错误"
401:
return "红色Toast: 用户名或密码错误"
404:
return "红色Toast: 用户不存在"
429:
return "红色Toast: 登录请求过于频繁"
500:
return "红色Toast: 服务器繁忙"
"send_code":
match response_code:
200, 206:
return "绿色Toast: 验证码已发送"
400:
return "红色Toast: 邮箱格式错误"
429:
return "红色Toast: 请求过于频繁"
500:
return "红色Toast: 服务器繁忙"
0:
return "红色Toast: 网络连接失败"
"verify_email":
match response_code:
200:
return "绿色Toast: 邮箱验证成功"
400:
return "红色Toast: 验证码错误"
404:
return "红色Toast: 请先获取验证码"
500:
return "红色Toast: 验证失败"
"register":
match response_code:
201:
return "绿色Toast: 注册成功,切换到登录界面"
400:
return "红色Toast: 根据具体错误显示(验证码缺失、格式错误等)"
409:
return "红色Toast: 用户名或邮箱已存在"
429:
return "红色Toast: 注册请求过于频繁,请稍后再试"
500:
return "红色Toast: 注册失败"
return "未知响应"
# 反馈面板功能
func show_feedback(message: String, type: String = "info"):
# 更改面板样式
if feedback_styles.has(type):
feedback_panel.add_theme_stylebox_override("panel", feedback_styles[type])
# 清空并显示新消息
feedback_text.text = "[b]%s[/b]" % message
func add_feedback_line(message: String):
feedback_text.text += "\n" + message
# 自动滚动到底部
await get_tree().process_frame
var scroll = feedback_text.get_parent()
if scroll is ScrollContainer:
scroll.scroll_vertical = scroll.get_v_scroll_bar().max_value
func _input(event):
if event.is_action_pressed("ui_cancel"):
show_feedback("👋 退出测试场景", "info")
await get_tree().create_timer(0.5).timeout
get_tree().quit()

View File

@@ -0,0 +1 @@
uid://ddb8v5c6aeqe7

View File

@@ -0,0 +1,117 @@
[gd_scene load_steps=4 format=3 uid="uid://bvn8y7x2qkqxe"]
[ext_resource type="Script" uid="uid://ddb8v5c6aeqe7" path="res://tests/auth/auth_ui_test.gd" id="1_test_script"]
[ext_resource type="PackedScene" uid="uid://by7m8snb4xllf" path="res://scenes/auth_scene.tscn" id="2_auth_scene"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_feedback_info"]
bg_color = Color(0.2, 0.5, 0.8, 0.9)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.1, 0.4, 0.6, 1)
corner_radius_top_left = 8
corner_radius_top_right = 8
corner_radius_bottom_right = 8
corner_radius_bottom_left = 8
[node name="AuthUITest" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_test_script")
[node name="AuthScene" parent="." instance=ExtResource("2_auth_scene")]
layout_mode = 1
[node name="TestPanel" type="Panel" parent="."]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -350.0
offset_top = 20.0
offset_right = -20.0
offset_bottom = 620.0
grow_horizontal = 0
[node name="VBoxContainer" type="VBoxContainer" parent="TestPanel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = 10.0
offset_right = -10.0
offset_bottom = -10.0
grow_horizontal = 2
grow_vertical = 2
[node name="TitleLabel" type="Label" parent="TestPanel/VBoxContainer"]
layout_mode = 2
theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1)
theme_override_font_sizes/font_size = 18
text = "🧪 UI响应测试"
horizontal_alignment = 1
[node name="HSeparator" type="HSeparator" parent="TestPanel/VBoxContainer"]
layout_mode = 2
[node name="FeedbackPanel" type="Panel" parent="TestPanel/VBoxContainer"]
custom_minimum_size = Vector2(0, 120)
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_feedback_info")
[node name="FeedbackContainer" type="VBoxContainer" parent="TestPanel/VBoxContainer/FeedbackPanel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = 8.0
offset_right = -10.0
offset_bottom = -8.0
grow_horizontal = 2
grow_vertical = 2
[node name="FeedbackTitle" type="Label" parent="TestPanel/VBoxContainer/FeedbackPanel/FeedbackContainer"]
layout_mode = 2
theme_override_colors/font_color = Color(1, 1, 1, 1)
theme_override_font_sizes/font_size = 14
text = "📋 测试反馈"
[node name="FeedbackScroll" type="ScrollContainer" parent="TestPanel/VBoxContainer/FeedbackPanel/FeedbackContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="FeedbackText" type="RichTextLabel" parent="TestPanel/VBoxContainer/FeedbackPanel/FeedbackContainer/FeedbackScroll"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_colors/default_color = Color(1, 1, 1, 1)
theme_override_font_sizes/normal_font_size = 12
bbcode_enabled = true
text = "点击下方测试按钮开始测试..."
fit_content = true
scroll_following = true
[node name="HSeparator2" type="HSeparator" parent="TestPanel/VBoxContainer"]
layout_mode = 2
[node name="ButtonsLabel" type="Label" parent="TestPanel/VBoxContainer"]
layout_mode = 2
theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1)
theme_override_font_sizes/font_size = 14
text = "🎯 测试用例"
horizontal_alignment = 1
[node name="ScrollContainer" type="ScrollContainer" parent="TestPanel/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="TestButtons" type="VBoxContainer" parent="TestPanel/VBoxContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3