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 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 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 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 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 firstBatch = QuestionFactoryManager.generateQuestions( Grade.ELEMENTARY, 5, null ); // 收集已生成的题目文本 Set historyQuestions = new HashSet<>(); for (ChoiceQuestion q : firstBatch) { historyQuestions.add(q.getQuestionText()); } // 第二次生成(带去重) List 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("========================================"); } }