You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PAIR/src/test/java/TestMain.java

774 lines
30 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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("========================================");
}
}