|
|
|
|
@ -0,0 +1,774 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.model.*;
|
|
|
|
|
import com.service.*;
|
|
|
|
|
import com.service.question_generator.QuestionFactoryManager;
|
|
|
|
|
import com.util.PasswordValidator;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 完整测试类
|
|
|
|
|
* 测试项目的各个功能模块
|
|
|
|
|
*/
|
|
|
|
|
public class TestMain {
|
|
|
|
|
|
|
|
|
|
private static int testsPassed = 0;
|
|
|
|
|
private static int testsFailed = 0;
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
System.out.println("========================================");
|
|
|
|
|
System.out.println(" 数学答题系统 - 完整测试");
|
|
|
|
|
System.out.println("========================================\n");
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 1. 测试工具类
|
|
|
|
|
testPasswordValidator();
|
|
|
|
|
|
|
|
|
|
// 2. 测试文件服务
|
|
|
|
|
testFileIOService();
|
|
|
|
|
|
|
|
|
|
// 3. 测试用户服务
|
|
|
|
|
testUserService();
|
|
|
|
|
|
|
|
|
|
// 4. 测试题目生成
|
|
|
|
|
testQuestionGeneration();
|
|
|
|
|
|
|
|
|
|
// 5. 测试答题服务
|
|
|
|
|
testQuizService();
|
|
|
|
|
|
|
|
|
|
// 6. 测试完整流程
|
|
|
|
|
testCompleteWorkflow();
|
|
|
|
|
|
|
|
|
|
// 输出测试结果
|
|
|
|
|
printTestSummary();
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("测试过程中发生错误:" + e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 1. 测试密码验证工具 ====================
|
|
|
|
|
|
|
|
|
|
private static void testPasswordValidator() {
|
|
|
|
|
System.out.println("【测试1】密码验证工具");
|
|
|
|
|
System.out.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
// 测试1.1: 有效密码
|
|
|
|
|
test("有效密码验证",
|
|
|
|
|
PasswordValidator.isValid("Abc123456"),
|
|
|
|
|
"密码 'Abc123456' 应该有效");
|
|
|
|
|
|
|
|
|
|
// 测试1.2: 密码太短
|
|
|
|
|
test("密码太短检测",
|
|
|
|
|
!PasswordValidator.isValid("Abc12"),
|
|
|
|
|
"密码 'Abc12' 应该无效(太短)");
|
|
|
|
|
|
|
|
|
|
// 测试1.3: 缺少数字
|
|
|
|
|
test("缺少数字检测",
|
|
|
|
|
!PasswordValidator.isValid("Abcdefgh"),
|
|
|
|
|
"密码 'Abcdefgh' 应该无效(缺少数字)");
|
|
|
|
|
|
|
|
|
|
// 测试1.4: 密码加密
|
|
|
|
|
String encrypted1 = PasswordValidator.encrypt("test123");
|
|
|
|
|
String encrypted2 = PasswordValidator.encrypt("test123");
|
|
|
|
|
test("密码加密一致性",
|
|
|
|
|
encrypted1.equals(encrypted2),
|
|
|
|
|
"相同密码加密结果应该一致");
|
|
|
|
|
|
|
|
|
|
// 测试1.5: 密码匹配
|
|
|
|
|
test("密码匹配验证",
|
|
|
|
|
PasswordValidator.matches("test123", encrypted1),
|
|
|
|
|
"密码匹配应该成功");
|
|
|
|
|
|
|
|
|
|
// 测试1.6: 生成注册码
|
|
|
|
|
String code = PasswordValidator.generateRegistrationCode();
|
|
|
|
|
test("注册码生成",
|
|
|
|
|
code.length() >= 6 && code.length() <= 10,
|
|
|
|
|
"注册码长度应该在6-10位之间,实际:" + code.length());
|
|
|
|
|
|
|
|
|
|
// 测试1.7: 密码强度检测
|
|
|
|
|
String strength = PasswordValidator.getPasswordStrength("Abc123!@#");
|
|
|
|
|
test("密码强度检测",
|
|
|
|
|
strength != null && !strength.isEmpty(),
|
|
|
|
|
"密码强度应该返回有效值,实际:" + strength);
|
|
|
|
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 2. 测试文件IO服务 ====================
|
|
|
|
|
|
|
|
|
|
private static void testFileIOService() throws IOException {
|
|
|
|
|
System.out.println("【测试2】文件IO服务");
|
|
|
|
|
System.out.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
FileIOService fileService = new FileIOService();
|
|
|
|
|
|
|
|
|
|
// 测试2.1: 初始化目录
|
|
|
|
|
try {
|
|
|
|
|
fileService.initDataDirectory();
|
|
|
|
|
test("初始化数据目录", true, "数据目录初始化成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("初始化数据目录", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试2.2: 保存和加载用户
|
|
|
|
|
User testUser = new User("小学-测试", "encrypted123", "test@test.com", Grade.ELEMENTARY);
|
|
|
|
|
try {
|
|
|
|
|
fileService.saveUser(testUser);
|
|
|
|
|
User loaded = fileService.findUserByUsername("小学-测试");
|
|
|
|
|
test("保存和加载用户",
|
|
|
|
|
loaded != null && loaded.getUsername().equals("小学-测试"),
|
|
|
|
|
"用户数据应该正确保存和加载");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("保存和加载用户", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试2.3: 检查用户名是否存在
|
|
|
|
|
try {
|
|
|
|
|
boolean exists = fileService.isUsernameExists("小学-测试");
|
|
|
|
|
test("检查用户名存在", exists, "用户名应该存在");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("检查用户名存在", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试2.4: 查找不存在的用户
|
|
|
|
|
try {
|
|
|
|
|
User notFound = fileService.findUserByUsername("不存在的用户");
|
|
|
|
|
test("查找不存在的用户",
|
|
|
|
|
notFound == null,
|
|
|
|
|
"不存在的用户应该返回null");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("查找不存在的用户", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 3. 测试用户服务====================
|
|
|
|
|
|
|
|
|
|
private static void testUserService() throws IOException {
|
|
|
|
|
System.out.println("【测试3】用户服务(包含验证码)");
|
|
|
|
|
System.out.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
UserService userService = new UserService();
|
|
|
|
|
|
|
|
|
|
// ========== 3.1 测试注册码生成和保存 ==========
|
|
|
|
|
|
|
|
|
|
String testEmail1 = "test001@example.com";
|
|
|
|
|
String registrationCode1 = null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
registrationCode1 = userService.generateRegistrationCode(testEmail1);
|
|
|
|
|
test("生成注册码",
|
|
|
|
|
registrationCode1 != null && registrationCode1.length() >= 6,
|
|
|
|
|
"注册码:" + registrationCode1);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("生成注册码", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.2 测试注册码文件存储 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
boolean fileExists = com.util.FileUtils.exists("data/registration_codes.txt");
|
|
|
|
|
test("注册码文件创建",
|
|
|
|
|
fileExists,
|
|
|
|
|
"注册码应该保存到文件");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("注册码文件创建", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.3 测试用户注册(带验证码)==========
|
|
|
|
|
|
|
|
|
|
String testUsername = "小学-张三测试";
|
|
|
|
|
String testPassword = "Test123456";
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
User user = userService.register(testUsername, testPassword, testEmail1, registrationCode1);
|
|
|
|
|
test("用户注册(带验证码)",
|
|
|
|
|
user != null && user.getUsername().equals(testUsername),
|
|
|
|
|
"用户注册成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("用户注册(带验证码)", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.4 测试注册码一次性使用 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 尝试用同一个注册码再次注册
|
|
|
|
|
userService.register("小学-李四", "Test123456", testEmail1, registrationCode1);
|
|
|
|
|
test("注册码一次性使用", false, "应该抛出异常");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("注册码一次性使用",
|
|
|
|
|
e.getMessage().contains("未找到"),
|
|
|
|
|
"注册码使用后应该被删除");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("注册码一次性使用", false, "异常类型错误:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.5 测试错误的注册码 ==========
|
|
|
|
|
|
|
|
|
|
String testEmail2 = "test002@example.com";
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String code = userService.generateRegistrationCode(testEmail2);
|
|
|
|
|
// 故意使用错误的注册码
|
|
|
|
|
userService.register("小学-王五", "Test123456", testEmail2, "wrongCode123");
|
|
|
|
|
test("错误注册码检测", false, "应该抛出异常");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("错误注册码检测",
|
|
|
|
|
e.getMessage().contains("注册码错误"),
|
|
|
|
|
"应该检测到错误的注册码");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("错误注册码检测", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.6 测试未获取注册码就注册 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
userService.register("小学-赵六", "Test123456", "nocode@test.com", "randomCode");
|
|
|
|
|
test("未获取注册码检测", false, "应该抛出异常");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("未获取注册码检测",
|
|
|
|
|
e.getMessage().contains("未找到"),
|
|
|
|
|
"应该检测到未获取注册码");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("未获取注册码检测", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.7 测试重复注册检测 ==========
|
|
|
|
|
|
|
|
|
|
String testEmail3 = "test003@example.com";
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String code = userService.generateRegistrationCode(testEmail3);
|
|
|
|
|
userService.register(testUsername, "Test123456", testEmail3, code);
|
|
|
|
|
test("重复注册检测", false, "应该抛出异常");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("重复注册检测",
|
|
|
|
|
e.getMessage().contains("已存在"),
|
|
|
|
|
"应该检测到用户名已存在");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("重复注册检测", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.8 测试用户登录 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
User user = userService.login(testUsername, testPassword);
|
|
|
|
|
test("用户登录",
|
|
|
|
|
user != null && userService.isLoggedIn(),
|
|
|
|
|
"用户登录成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("用户登录", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.9 测试错误密码登录 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
userService.logout(); // 先退出
|
|
|
|
|
userService.login(testUsername, "WrongPassword123");
|
|
|
|
|
test("错误密码登录", false, "应该抛出异常");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("错误密码登录",
|
|
|
|
|
e.getMessage().contains("密码错误"),
|
|
|
|
|
"应该检测到密码错误");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("错误密码登录", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.10 测试不存在的用户登录 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
userService.login("小学-不存在", "Test123456");
|
|
|
|
|
test("不存在用户登录", false, "应该抛出异常");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("不存在用户登录",
|
|
|
|
|
e.getMessage().contains("不存在"),
|
|
|
|
|
"应该检测到用户名不存在");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("不存在用户登录", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.11 测试获取当前用户 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
userService.login(testUsername, testPassword);
|
|
|
|
|
User current = userService.getCurrentUser();
|
|
|
|
|
test("获取当前用户",
|
|
|
|
|
current != null && current.getUsername().equals(testUsername),
|
|
|
|
|
"应该返回当前登录用户");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("获取当前用户", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.12 测试提取真实姓名 ==========
|
|
|
|
|
|
|
|
|
|
User user = userService.getCurrentUser();
|
|
|
|
|
String realName = userService.getRealName(user);
|
|
|
|
|
test("提取真实姓名",
|
|
|
|
|
realName.equals("张三测试"),
|
|
|
|
|
"应该正确提取真实姓名,实际:" + realName);
|
|
|
|
|
|
|
|
|
|
// ========== 3.13 测试获取学段显示名 ==========
|
|
|
|
|
|
|
|
|
|
String gradeName = userService.getGradeDisplayName(user);
|
|
|
|
|
test("获取学段显示名",
|
|
|
|
|
gradeName.equals("小学"),
|
|
|
|
|
"应该返回'小学',实际:" + gradeName);
|
|
|
|
|
|
|
|
|
|
// ========== 3.14 测试退出登录 ==========
|
|
|
|
|
|
|
|
|
|
userService.logout();
|
|
|
|
|
test("退出登录",
|
|
|
|
|
!userService.isLoggedIn(),
|
|
|
|
|
"退出后应该未登录状态");
|
|
|
|
|
|
|
|
|
|
// ========== 3.15 测试完整注册流程(不同学段)==========
|
|
|
|
|
|
|
|
|
|
// 初中学生注册
|
|
|
|
|
try {
|
|
|
|
|
String middleEmail = "middle@test.com";
|
|
|
|
|
String middleCode = userService.generateRegistrationCode(middleEmail);
|
|
|
|
|
User middleUser = userService.register("初中-李明", "Middle123", middleEmail, middleCode);
|
|
|
|
|
|
|
|
|
|
test("初中学生注册",
|
|
|
|
|
middleUser != null && middleUser.getGrade() == Grade.MIDDLE,
|
|
|
|
|
"初中学生注册成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("初中学生注册", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 高中学生注册
|
|
|
|
|
try {
|
|
|
|
|
String highEmail = "high@test.com";
|
|
|
|
|
String highCode = userService.generateRegistrationCode(highEmail);
|
|
|
|
|
User highUser = userService.register("高中-王华", "High123456", highEmail, highCode);
|
|
|
|
|
|
|
|
|
|
test("高中学生注册",
|
|
|
|
|
highUser != null && highUser.getGrade() == Grade.HIGH,
|
|
|
|
|
"高中学生注册成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("高中学生注册", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.16 测试密码强度验证 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String weakEmail = "weak@test.com";
|
|
|
|
|
String weakCode = userService.generateRegistrationCode(weakEmail);
|
|
|
|
|
userService.register("小学-弱密码", "123", weakEmail, weakCode);
|
|
|
|
|
test("密码强度验证", false, "应该拒绝弱密码");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("密码强度验证",
|
|
|
|
|
e.getMessage().contains("密码"),
|
|
|
|
|
"应该检测到密码不符合要求");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("密码强度验证", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.17 测试邮箱格式验证 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
userService.generateRegistrationCode("invalid-email");
|
|
|
|
|
test("邮箱格式验证", false, "应该拒绝无效邮箱");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("邮箱格式验证",
|
|
|
|
|
e.getMessage().contains("邮箱"),
|
|
|
|
|
"应该检测到邮箱格式错误");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("邮箱格式验证", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.18 测试用户名格式验证 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String invalidEmail = "invalid@test.com";
|
|
|
|
|
String invalidCode = userService.generateRegistrationCode(invalidEmail);
|
|
|
|
|
userService.register("错误格式", "Test123456", invalidEmail, invalidCode);
|
|
|
|
|
test("用户名格式验证", false, "应该拒绝错误格式的用户名");
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
test("用户名格式验证",
|
|
|
|
|
e.getMessage().contains("格式"),
|
|
|
|
|
"应该检测到用户名格式错误");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("用户名格式验证", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.19 测试清理过期注册码 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
userService.cleanExpiredCodes();
|
|
|
|
|
test("清理过期注册码", true, "清理操作成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("清理过期注册码", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.20 测试从文件重新加载注册码 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String reloadEmail = "reload@test.com";
|
|
|
|
|
String reloadCode = userService.generateRegistrationCode(reloadEmail);
|
|
|
|
|
|
|
|
|
|
// 创建新的 UserService 实例(模拟重启)
|
|
|
|
|
UserService newUserService = new UserService();
|
|
|
|
|
|
|
|
|
|
// 使用之前保存的注册码
|
|
|
|
|
User reloadUser = newUserService.register("小学-重载测试", "Reload123", reloadEmail, reloadCode);
|
|
|
|
|
|
|
|
|
|
test("从文件重载注册码",
|
|
|
|
|
reloadUser != null,
|
|
|
|
|
"应该能从文件读取注册码");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("从文件重载注册码", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3.21 查看注册码文件内容 ==========
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (com.util.FileUtils.exists("data/registration_codes.txt")) {
|
|
|
|
|
String fileContent = com.util.FileUtils.readFileToString(
|
|
|
|
|
"data/registration_codes.txt"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
System.out.println("\n 【注册码文件内容预览】");
|
|
|
|
|
String[] lines = fileContent.split("\n");
|
|
|
|
|
int lineCount = 0;
|
|
|
|
|
for (String line : lines) {
|
|
|
|
|
if (lineCount++ < 10) { // 显示前10行
|
|
|
|
|
System.out.println(" " + line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (lines.length > 10) {
|
|
|
|
|
System.out.println(" ... (共 " + lines.length + " 行)");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test("注册码文件格式",
|
|
|
|
|
fileContent.contains("#") && fileContent.contains("|"),
|
|
|
|
|
"文件格式正确");
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("查看文件内容", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 4. 测试题目生成 ====================
|
|
|
|
|
|
|
|
|
|
private static void testQuestionGeneration() {
|
|
|
|
|
System.out.println("【测试4】题目生成");
|
|
|
|
|
System.out.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
// 测试4.1: 生成小学题目(不去重)
|
|
|
|
|
try {
|
|
|
|
|
List<ChoiceQuestion> questions = QuestionFactoryManager.generateQuestions(
|
|
|
|
|
Grade.ELEMENTARY, 1, null
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
test("生成小学题目",
|
|
|
|
|
questions.size() == 1 && questions.get(0).getQuestionText() != null,
|
|
|
|
|
"应该生成1道有效的小学题目");
|
|
|
|
|
|
|
|
|
|
System.out.println(" 示例题目:" + questions.get(0).getQuestionText());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("生成小学题目", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试4.2: 生成初中题目
|
|
|
|
|
try {
|
|
|
|
|
List<ChoiceQuestion> questions = QuestionFactoryManager.generateQuestions(
|
|
|
|
|
Grade.MIDDLE, 1, null
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
test("生成初中题目",
|
|
|
|
|
questions.size() == 1,
|
|
|
|
|
"应该生成1道有效的初中题目");
|
|
|
|
|
|
|
|
|
|
System.out.println(" 示例题目:" + questions.get(0).getQuestionText());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("生成初中题目", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试4.3: 生成高中题目
|
|
|
|
|
try {
|
|
|
|
|
List<ChoiceQuestion> questions = QuestionFactoryManager.generateQuestions(
|
|
|
|
|
Grade.HIGH, 1, null
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
test("生成高中题目",
|
|
|
|
|
questions.size() == 1,
|
|
|
|
|
"应该生成1道有效的高中题目");
|
|
|
|
|
|
|
|
|
|
System.out.println(" 示例题目:" + questions.get(0).getQuestionText());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("生成高中题目", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试4.4: 批量生成题目
|
|
|
|
|
try {
|
|
|
|
|
List<ChoiceQuestion> questions = QuestionFactoryManager.generateQuestions(
|
|
|
|
|
Grade.ELEMENTARY, 10, null
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
test("批量生成题目",
|
|
|
|
|
questions.size() == 10,
|
|
|
|
|
"应该生成10道题目,实际:" + questions.size());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("批量生成题目", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试4.5: 题目去重功能
|
|
|
|
|
try {
|
|
|
|
|
// 第一次生成
|
|
|
|
|
List<ChoiceQuestion> firstBatch = QuestionFactoryManager.generateQuestions(
|
|
|
|
|
Grade.ELEMENTARY, 5, null
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 收集已生成的题目文本
|
|
|
|
|
Set<String> historyQuestions = new HashSet<>();
|
|
|
|
|
for (ChoiceQuestion q : firstBatch) {
|
|
|
|
|
historyQuestions.add(q.getQuestionText());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第二次生成(带去重)
|
|
|
|
|
List<ChoiceQuestion> secondBatch = QuestionFactoryManager.generateQuestions(
|
|
|
|
|
Grade.ELEMENTARY, 5, historyQuestions
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 检查第二次生成的题目是否与第一次重复
|
|
|
|
|
boolean noDuplicate = true;
|
|
|
|
|
for (ChoiceQuestion q : secondBatch) {
|
|
|
|
|
if (historyQuestions.contains(q.getQuestionText())) {
|
|
|
|
|
noDuplicate = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test("题目去重功能",
|
|
|
|
|
noDuplicate,
|
|
|
|
|
"第二次生成的题目不应与第一次重复");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("题目去重功能", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
// ==================== 5. 测试答题服务 ====================
|
|
|
|
|
|
|
|
|
|
private static void testQuizService() throws IOException {
|
|
|
|
|
System.out.println("【测试5】答题服务");
|
|
|
|
|
System.out.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
FileIOService fileService = new FileIOService();
|
|
|
|
|
UserService userService = new UserService(fileService);
|
|
|
|
|
QuizService quizService = new QuizService(fileService, userService);
|
|
|
|
|
|
|
|
|
|
// 创建测试用户
|
|
|
|
|
User testUser = new User("小学-李四", "encrypted", "lisi@test.com", Grade.ELEMENTARY);
|
|
|
|
|
fileService.saveUser(testUser);
|
|
|
|
|
|
|
|
|
|
// 测试5.1: 开始答题
|
|
|
|
|
try {
|
|
|
|
|
quizService.startNewQuiz(testUser, 5);
|
|
|
|
|
test("开始答题会话",
|
|
|
|
|
quizService.getTotalQuestions() == 5,
|
|
|
|
|
"应该生成5道题目");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("开始答题会话", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试5.2: 获取当前题目
|
|
|
|
|
ChoiceQuestion current = quizService.getCurrentQuestion();
|
|
|
|
|
test("获取当前题目",
|
|
|
|
|
current != null,
|
|
|
|
|
"应该返回当前题目");
|
|
|
|
|
|
|
|
|
|
// 测试5.3: 提交答案
|
|
|
|
|
try {
|
|
|
|
|
boolean correct = quizService.submitCurrentAnswer(0);
|
|
|
|
|
test("提交答案",
|
|
|
|
|
true, // 只要不抛异常就算通过
|
|
|
|
|
"提交答案应该成功,结果:" + (correct ? "正确" : "错误"));
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("提交答案", false, "失败:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试5.4: 题目导航
|
|
|
|
|
boolean canNext = quizService.nextQuestion();
|
|
|
|
|
test("下一题导航",
|
|
|
|
|
canNext,
|
|
|
|
|
"应该能够移动到下一题");
|
|
|
|
|
|
|
|
|
|
boolean canPrev = quizService.previousQuestion();
|
|
|
|
|
test("上一题导航",
|
|
|
|
|
canPrev,
|
|
|
|
|
"应该能够移动到上一题");
|
|
|
|
|
|
|
|
|
|
// 测试5.5: 检查答案
|
|
|
|
|
ChoiceQuestion question = quizService.getCurrentQuestion();
|
|
|
|
|
int correctIndex = quizService.getCorrectAnswerIndex(question);
|
|
|
|
|
boolean isCorrect = quizService.checkAnswer(question, correctIndex);
|
|
|
|
|
test("检查正确答案",
|
|
|
|
|
isCorrect,
|
|
|
|
|
"正确答案应该通过验证");
|
|
|
|
|
|
|
|
|
|
// 测试5.6: 答题进度
|
|
|
|
|
quizService.goToQuestion(0);
|
|
|
|
|
quizService.submitCurrentAnswer(0);
|
|
|
|
|
quizService.nextQuestion();
|
|
|
|
|
quizService.submitCurrentAnswer(1);
|
|
|
|
|
|
|
|
|
|
int answered = quizService.getAnsweredCount();
|
|
|
|
|
test("答题进度统计",
|
|
|
|
|
answered == 2,
|
|
|
|
|
"应该有2道题已作答,实际:" + answered);
|
|
|
|
|
|
|
|
|
|
// 测试5.7: 完成所有题目并计算成绩
|
|
|
|
|
for (int i = 0; i < quizService.getTotalQuestions(); i++) {
|
|
|
|
|
quizService.goToQuestion(i);
|
|
|
|
|
quizService.submitCurrentAnswer(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QuizResult result = quizService.calculateResult();
|
|
|
|
|
test("计算成绩",
|
|
|
|
|
result.getTotalQuestions() == 5,
|
|
|
|
|
"成绩统计应该正确,总题数:" + result.getTotalQuestions());
|
|
|
|
|
|
|
|
|
|
System.out.println(" 得分:" + result.getScore());
|
|
|
|
|
System.out.println(" 正确:" + result.getCorrectCount());
|
|
|
|
|
System.out.println(" 错误:" + result.getWrongCount());
|
|
|
|
|
|
|
|
|
|
// 测试5.8: 格式化输出
|
|
|
|
|
String formatted = quizService.formatResult(result);
|
|
|
|
|
test("格式化结果输出",
|
|
|
|
|
formatted != null && formatted.contains("答题结束"),
|
|
|
|
|
"应该返回格式化的结果文本");
|
|
|
|
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 6. 测试完整流程 ====================
|
|
|
|
|
|
|
|
|
|
private static void testCompleteWorkflow() throws IOException {
|
|
|
|
|
System.out.println("【测试6】完整答题流程");
|
|
|
|
|
System.out.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
FileIOService fileService = new FileIOService();
|
|
|
|
|
UserService userService = new UserService(fileService);
|
|
|
|
|
QuizService quizService = new QuizService(fileService, userService);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// ========== 步骤1: 注册新用户 ==========
|
|
|
|
|
System.out.println("步骤1: 注册新用户...");
|
|
|
|
|
|
|
|
|
|
String username = "初中-王五";
|
|
|
|
|
String password = "Test123456";
|
|
|
|
|
String email = "wangwu@test.com";
|
|
|
|
|
|
|
|
|
|
// 1.1 生成注册码
|
|
|
|
|
String registrationCode = userService.generateRegistrationCode(email);
|
|
|
|
|
System.out.println(" 获取注册码:" + registrationCode);
|
|
|
|
|
|
|
|
|
|
// 1.2 使用注册码注册
|
|
|
|
|
User user = userService.register(username, password, email, registrationCode);
|
|
|
|
|
test("完整流程-注册", user != null, "用户注册成功");
|
|
|
|
|
|
|
|
|
|
// ========== 步骤2: 用户登录 ==========
|
|
|
|
|
System.out.println("步骤2: 用户登录...");
|
|
|
|
|
userService.login(username, password);
|
|
|
|
|
test("完整流程-登录", userService.isLoggedIn(), "用户登录成功");
|
|
|
|
|
|
|
|
|
|
// ========== 步骤3: 开始答题 ==========
|
|
|
|
|
System.out.println("步骤3: 开始答题(10道题)...");
|
|
|
|
|
quizService.startNewQuiz(user, 10);
|
|
|
|
|
test("完整流程-生成题目",
|
|
|
|
|
quizService.getTotalQuestions() == 10,
|
|
|
|
|
"题目生成成功");
|
|
|
|
|
|
|
|
|
|
// ========== 步骤4: 答题(模拟全部答对)==========
|
|
|
|
|
System.out.println("步骤4: 模拟答题过程...");
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
quizService.goToQuestion(i);
|
|
|
|
|
ChoiceQuestion q = quizService.getCurrentQuestion();
|
|
|
|
|
int correctIndex = quizService.getCorrectAnswerIndex(q);
|
|
|
|
|
quizService.submitAnswer(i, correctIndex);
|
|
|
|
|
}
|
|
|
|
|
test("完整流程-答题", quizService.isAllAnswered(), "所有题目已作答");
|
|
|
|
|
|
|
|
|
|
// ========== 步骤5: 计算成绩 ==========
|
|
|
|
|
System.out.println("步骤5: 计算成绩...");
|
|
|
|
|
QuizResult result = quizService.calculateResult();
|
|
|
|
|
test("完整流程-计算成绩",
|
|
|
|
|
result.getScore() == 100,
|
|
|
|
|
"全部答对应该得100分,实际:" + result.getScore());
|
|
|
|
|
|
|
|
|
|
System.out.println(quizService.formatResult(result));
|
|
|
|
|
|
|
|
|
|
// ========== 步骤6: 保存记录 ==========
|
|
|
|
|
System.out.println("步骤6: 保存答题记录...");
|
|
|
|
|
quizService.saveQuizHistory(user);
|
|
|
|
|
|
|
|
|
|
// 验证用户统计是否更新
|
|
|
|
|
User updatedUser = fileService.findUserByUsername(username);
|
|
|
|
|
test("完整流程-保存记录",
|
|
|
|
|
updatedUser.getTotalQuizzes() == 1,
|
|
|
|
|
"用户答题次数应该增加,实际:" + updatedUser.getTotalQuizzes());
|
|
|
|
|
|
|
|
|
|
test("完整流程-平均分更新",
|
|
|
|
|
updatedUser.getAverageScore() == 100.0,
|
|
|
|
|
"平均分应该更新,实际:" + updatedUser.getAverageScore());
|
|
|
|
|
|
|
|
|
|
// ========== 步骤7: 退出登录 ==========
|
|
|
|
|
System.out.println("步骤7: 退出登录...");
|
|
|
|
|
userService.logout();
|
|
|
|
|
test("完整流程-退出", !userService.isLoggedIn(), "退出登录成功");
|
|
|
|
|
|
|
|
|
|
System.out.println("\n✓ 完整流程测试通过!");
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
test("完整流程", false, "失败:" + e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 测试工具方法 ====================
|
|
|
|
|
|
|
|
|
|
private static void test(String testName, boolean condition, String message) {
|
|
|
|
|
if (condition) {
|
|
|
|
|
System.out.println(" ✓ " + testName + ": 通过");
|
|
|
|
|
if (message != null && !message.isEmpty()) {
|
|
|
|
|
System.out.println(" " + message);
|
|
|
|
|
}
|
|
|
|
|
testsPassed++;
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println(" ✗ " + testName + ": 失败");
|
|
|
|
|
if (message != null && !message.isEmpty()) {
|
|
|
|
|
System.out.println(" " + message);
|
|
|
|
|
}
|
|
|
|
|
testsFailed++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void printTestSummary() {
|
|
|
|
|
System.out.println("========================================");
|
|
|
|
|
System.out.println(" 测试结果汇总");
|
|
|
|
|
System.out.println("========================================");
|
|
|
|
|
System.out.println("总测试数:" + (testsPassed + testsFailed));
|
|
|
|
|
System.out.println("通过:" + testsPassed + " 项");
|
|
|
|
|
System.out.println("失败:" + testsFailed + " 项");
|
|
|
|
|
|
|
|
|
|
if (testsFailed == 0) {
|
|
|
|
|
System.out.println("\n🎉 所有测试通过!项目功能正常,可以开始开发UI了!");
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("\n⚠ 有 " + testsFailed + " 项测试失败,请检查并修复问题");
|
|
|
|
|
}
|
|
|
|
|
System.out.println("========================================");
|
|
|
|
|
}
|
|
|
|
|
}
|