| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057 |
- /**
- * 心知益家小程序 - 自动化测试用例脚本
- *
- * 测试策略:
- * 1. Web端(管理后台):浏览器自动化测试,管理员和指导师登录,测试过程截图
- * 2. 小程序端:API接口测试,构造请求数据,验证响应,不进行UI点击测试
- *
- * 最后更新时间:2026-04-14
- */
- const TEST_CONFIG = {
- // 测试环境配置
- baseUrl: 'http://192.168.16.18:8080', // 后端API地址
- webAdminUrl: 'http://192.168.16.18:8081', // Web管理端地址
-
- // 测试账号
- adminAccount: { phone: '13800138000', password: 'admin123' },
- teacherAccount: { phone: '13800138003', password: 'teacher123' },
-
- // API测试账号(小程序端)
- apiTestAccounts: {
- parent: { id: 1, phone: '13800138001', token: '' },
- child: { id: 2, phone: '13800138002', token: '' }
- },
- // 测试超时时间(毫秒)
- timeout: 30000,
- // 截图保存路径
- screenshotPath: './screenshots'
- };
- // ============================================================================
- // 模块1: API接口测试基类(小程序端)
- // ============================================================================
- /**
- * API测试基类 - 用于小程序端接口测试
- * 只测试API接口,记录构造的请求数据和响应结果
- */
- class ApiTestCase {
- constructor(id, description, priority, endpoint, method = 'GET') {
- this.id = id;
- this.description = description;
- this.priority = priority; // P0, P1, P2
- this.endpoint = endpoint;
- this.method = method;
- this.status = 'pending'; // pending, running, passed, failed
- this.error = null;
- this.requestData = null;
- this.responseData = null;
- this.screenshots = [];
- }
- /**
- * 发送API请求
- */
- async sendRequest(data = {}, headers = {}) {
- const url = `${TEST_CONFIG.baseUrl}${this.endpoint}`;
- const startTime = Date.now();
-
- this.requestData = {
- url: url,
- method: this.method,
- headers: {
- 'Content-Type': 'application/json',
- ...headers
- },
- body: data,
- timestamp: new Date().toISOString()
- };
- console.log(`[${this.id}] 发送请求: ${this.method} ${url}`);
- console.log(`[${this.id}] 请求数据:`, JSON.stringify(data, null, 2));
- try {
- // 这里需要实际的HTTP客户端,模拟请求
- // 在实际运行时,可以使用 fetch 或 axios
- const response = await this.mockFetch(url, {
- method: this.method,
- headers: this.requestData.headers,
- body: this.method !== 'GET' ? JSON.stringify(data) : undefined
- });
- this.responseData = {
- status: response.status,
- statusText: response.statusText,
- data: response.data,
- duration: Date.now() - startTime,
- timestamp: new Date().toISOString()
- };
- console.log(`[${this.id}] 响应状态: ${response.status}`);
- console.log(`[${this.id}] 响应数据:`, JSON.stringify(response.data, null, 2));
- return response;
- } catch (error) {
- this.responseData = {
- error: error.message,
- timestamp: new Date().toISOString()
- };
- throw error;
- }
- }
- /**
- * 模拟fetch请求(实际运行时替换为真实HTTP客户端)
- */
- async mockFetch(url, options) {
- // 模拟响应,实际测试时需要连接真实后端
- return {
- status: 200,
- statusText: 'OK',
- data: { code: 200, message: 'success', data: {} }
- };
- }
- /**
- * 记录测试结果
- */
- logResult(passed, error = null) {
- this.status = passed ? 'passed' : 'failed';
- this.error = error;
- console.log(`[${this.id}] 测试${passed ? '通过 ✅' : '失败 ❌'}: ${this.description}`);
- if (error) {
- console.error(`[${this.id}] 错误信息:`, error);
- }
- }
- /**
- * 执行测试(子类实现)
- */
- async run() {
- throw new Error('子类必须实现 run 方法');
- }
- }
- // ============================================================================
- // 模块2: Web浏览器测试基类(管理后台)
- // ============================================================================
- /**
- * Web浏览器测试基类 - 用于管理后台UI测试
- * 使用Chrome DevTools进行浏览器自动化,测试过程截图
- */
- class WebTestCase {
- constructor(id, description, priority) {
- this.id = id;
- this.description = description;
- this.priority = priority;
- this.status = 'pending';
- this.error = null;
- this.screenshots = [];
- this.pageId = null;
- }
- /**
- * 初始化测试环境 - 打开浏览器
- */
- async setup() {
- console.log(`[${this.id}] 测试启动: ${this.description}`);
- this.status = 'running';
- }
- /**
- * 标准化快照数据
- */
- normalizeSnapshot(snapshot) {
- if (!snapshot) return [];
- if (Array.isArray(snapshot)) return snapshot;
- if (Array.isArray(snapshot.elements)) return snapshot.elements;
- if (Array.isArray(snapshot.nodes)) return snapshot.nodes;
- if (Array.isArray(snapshot.items)) return snapshot.items;
- return [];
- }
- /**
- * 通过文本查找元素
- */
- findByText(snapshot, text) {
- const items = this.normalizeSnapshot(snapshot);
- return items.find(item => typeof item.text === 'string' && item.text.includes(text));
- }
- /**
- * 截图
- */
- async screenshot(name) {
- const filename = `${TEST_CONFIG.screenshotPath}/${this.id}_${name}.png`;
- // 实际运行时调用 chrome-devtools_take_screenshot
- console.log(`[${this.id}] 截图保存: ${filename}`);
- this.screenshots.push(filename);
- return filename;
- }
- /**
- * 等待元素出现
- */
- async waitForElement(text, timeout = TEST_CONFIG.timeout) {
- // 实际运行时调用 chrome-devtools_wait_for
- console.log(`[${this.id}] 等待元素: ${text}`);
- return { uid: `mock-${text}` };
- }
- /**
- * 点击元素
- */
- async click(uid) {
- // 实际运行时调用 chrome-devtools_click
- console.log(`[${this.id}] 点击元素: ${uid}`);
- }
- /**
- * 填充输入框
- */
- async fill(uid, value) {
- // 实际运行时调用 chrome-devtools_fill
- console.log(`[${this.id}] 填充输入: ${uid} = ${value}`);
- }
- /**
- * 获取页面快照
- */
- async getSnapshot() {
- // 实际运行时调用 chrome-devtools_take_snapshot
- return [];
- }
- /**
- * 登录管理员账号
- */
- async loginAdmin() {
- console.log(`[${this.id}] 登录管理员账号: ${TEST_CONFIG.adminAccount.phone}`);
- await this.screenshot('01_login_page');
-
- // 填写登录表单
- const phoneInput = await this.waitForElement('手机号');
- await this.fill(phoneInput.uid, TEST_CONFIG.adminAccount.phone);
-
- const pwdInput = await this.waitForElement('密码');
- await this.fill(pwdInput.uid, TEST_CONFIG.adminAccount.password);
-
- const loginBtn = await this.waitForElement('登录');
- await this.click(loginBtn.uid);
- await this.screenshot('02_after_login');
- }
- /**
- * 登录指导师账号
- */
- async loginTeacher() {
- console.log(`[${this.id}] 登录指导师账号: ${TEST_CONFIG.teacherAccount.phone}`);
- await this.screenshot('01_teacher_login_page');
-
- const phoneInput = await this.waitForElement('手机号');
- await this.fill(phoneInput.uid, TEST_CONFIG.teacherAccount.phone);
-
- const pwdInput = await this.waitForElement('密码');
- await this.fill(pwdInput.uid, TEST_CONFIG.teacherAccount.password);
-
- const loginBtn = await this.waitForElement('登录');
- await this.click(loginBtn.uid);
- await this.screenshot('02_teacher_after_login');
- }
- /**
- * 记录测试结果
- */
- logResult(passed, error = null) {
- this.status = passed ? 'passed' : 'failed';
- this.error = error;
- console.log(`[${this.id}] 测试${passed ? '通过 ✅' : '失败 ❌'}: ${this.description}`);
- if (error) {
- console.error(`[${this.id}] 错误信息:`, error);
- }
- }
- /**
- * 执行测试(子类实现)
- */
- async run() {
- throw new Error('子类必须实现 run 方法');
- }
- }
- // ============================================================================
- // 小程序端 API 测试用例
- // ============================================================================
- /**
- * API-001: 家长登录接口
- */
- class API_001_TestCase extends ApiTestCase {
- constructor() {
- super('API-001', '家长登录接口', 'P0', '/api/auth/login', 'POST');
- }
- async run() {
- try {
- this.requestData = {
- phone: '13800138001',
- code: '123456',
- role: 'parent'
- };
- const response = await this.sendRequest(this.requestData);
-
- // 验证响应
- const passed = response.status === 200 && response.data.code === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-002: 创建任务接口
- */
- class API_002_TestCase extends ApiTestCase {
- constructor() {
- super('API-002', '家长创建任务接口', 'P0', '/api/tasks', 'POST');
- }
- async run() {
- try {
- this.requestData = {
- childId: 2,
- name: '完成语文作业',
- points: 5,
- category: 'study',
- deadline: '2026-04-15T18:00:00',
- description: '完成课本第10页到第15页的练习题'
- };
- const response = await this.sendRequest(this.requestData);
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-003: 获取今日任务列表
- */
- class API_003_TestCase extends ApiTestCase {
- constructor() {
- super('API-003', '获取孩子今日任务列表', 'P0', '/api/tasks/today/2', 'GET');
- }
- async run() {
- try {
- this.requestData = {
- childId: 2,
- date: new Date().toISOString().split('T')[0]
- };
- const response = await this.sendRequest(this.requestData);
-
- // 记录响应数据结构
- console.log(`[${this.id}] 任务列表数据结构:`, JSON.stringify(response.data, null, 2));
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-004: 孩子完成任务
- */
- class API_004_TestCase extends ApiTestCase {
- constructor() {
- super('API-004', '孩子完成任务接口', 'P0', '/api/tasks/1/complete', 'POST');
- }
- async run() {
- try {
- this.requestData = {
- taskId: 1,
- completedAt: new Date().toISOString(),
- proof: {
- type: 'photo',
- url: 'https://example.com/photo.jpg',
- description: '已完成作业拍照'
- }
- };
- const response = await this.sendRequest(this.requestData);
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-005: 获取积分记录
- */
- class API_005_TestCase extends ApiTestCase {
- constructor() {
- super('API-005', '获取积分记录接口', 'P0', '/api/points/records', 'GET');
- }
- async run() {
- try {
- this.requestData = {
- childId: 2,
- startDate: '2026-04-01',
- endDate: '2026-04-30'
- };
- const response = await this.sendRequest(this.requestData);
-
- console.log(`[${this.id}] 积分记录数据:`, JSON.stringify(response.data, null, 2));
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-006: 添加心愿到心愿单
- */
- class API_006_TestCase extends ApiTestCase {
- constructor() {
- super('API-006', '孩子添加心愿接口', 'P0', '/api/rewards/wishlist', 'POST');
- }
- async run() {
- try {
- this.requestData = {
- childId: 2,
- name: '去游乐园玩',
- category: 'experience',
- description: '周末全家一起去游乐园'
- };
- const response = await this.sendRequest(this.requestData);
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-007: 兑换奖励
- */
- class API_007_TestCase extends ApiTestCase {
- constructor() {
- super('API-007', '孩子兑换奖励接口', 'P0', '/api/rewards/1/exchange', 'POST');
- }
- async run() {
- try {
- this.requestData = {
- rewardId: 1,
- childId: 2,
- pointsUsed: 50
- };
- const response = await this.sendRequest(this.requestData);
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-008: 家长审批奖励兑换
- */
- class API_008_TestCase extends ApiTestCase {
- constructor() {
- super('API-008', '家长审批奖励兑换接口', 'P0', '/api/rewards/1/approve', 'POST');
- }
- async run() {
- try {
- this.requestData = {
- exchangeId: 1,
- approved: true,
- comment: '同意兑换,表现很好!'
- };
- const response = await this.sendRequest(this.requestData);
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-009: 获取连续打卡天数
- */
- class API_009_TestCase extends ApiTestCase {
- constructor() {
- super('API-009', '获取连续打卡天数接口', 'P0', '/api/streak/2', 'GET');
- }
- async run() {
- try {
- this.requestData = {
- childId: 2
- };
- const response = await this.sendRequest(this.requestData);
-
- console.log(`[${this.id}] 连续打卡数据:`, JSON.stringify(response.data, null, 2));
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * API-010: 获取家庭信息
- */
- class API_010_TestCase extends ApiTestCase {
- constructor() {
- super('API-010', '获取家庭信息接口', 'P0', '/api/family/info', 'GET');
- }
- async run() {
- try {
- this.requestData = {
- familyId: 1
- };
- const response = await this.sendRequest(this.requestData);
-
- console.log(`[${this.id}] 家庭信息数据:`, JSON.stringify(response.data, null, 2));
-
- const passed = response.status === 200;
- this.logResult(passed);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- // ============================================================================
- // Web管理端 浏览器测试用例
- // ============================================================================
- /**
- * WEB-001: 管理员登录测试
- */
- class WEB_001_TestCase extends WebTestCase {
- constructor() {
- super('WEB-001', '管理员登录Web后台', 'P0');
- }
- async run() {
- try {
- await this.setup();
-
- // 1. 打开登录页面
- console.log(`[${this.id}] 访问: ${TEST_CONFIG.webAdminUrl}`);
- await this.screenshot('01_login_page');
-
- // 2. 输入账号密码
- const phoneInput = await this.waitForElement('手机号');
- await this.fill(phoneInput.uid, TEST_CONFIG.adminAccount.phone);
-
- const pwdInput = await this.waitForElement('密码');
- await this.fill(pwdInput.uid, TEST_CONFIG.adminAccount.password);
- await this.screenshot('02_form_filled');
-
- // 3. 点击登录
- const loginBtn = await this.waitForElement('登录');
- await this.click(loginBtn.uid);
- await this.screenshot('03_after_login');
-
- // 4. 验证登录成功
- const result = await this.getSnapshot();
- const hasDashboard = result.some(item =>
- item.text.includes('仪表板') ||
- item.text.includes('管理') ||
- item.text.includes('统计')
- );
-
- this.logResult(hasDashboard);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * WEB-002: 管理员查看用户列表
- */
- class WEB_002_TestCase extends WebTestCase {
- constructor() {
- super('WEB-002', '管理员查看用户列表', 'P0');
- }
- async run() {
- try {
- await this.setup();
- await this.loginAdmin();
-
- // 1. 点击用户管理
- const userMenu = await this.waitForElement('用户管理');
- await this.click(userMenu.uid);
- await this.screenshot('01_user_menu');
-
- // 2. 查看用户列表
- const userList = await this.waitForElement('用户列表');
- await this.click(userList.uid);
- await this.screenshot('02_user_list');
-
- // 3. 验证列表显示
- const result = await this.getSnapshot();
- const hasUsers = result.some(item =>
- item.text.includes('家长') ||
- item.text.includes('孩子') ||
- item.text.includes('手机号')
- );
-
- this.logResult(hasUsers);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * WEB-003: 管理员查看任务统计
- */
- class WEB_003_TestCase extends WebTestCase {
- constructor() {
- super('WEB-003', '管理员查看任务统计', 'P0');
- }
- async run() {
- try {
- await this.setup();
- await this.loginAdmin();
-
- // 1. 进入任务管理
- const taskMenu = await this.waitForElement('任务管理');
- await this.click(taskMenu.uid);
- await this.screenshot('01_task_menu');
-
- // 2. 查看统计
- const stats = await this.waitForElement('统计');
- await this.click(stats.uid);
- await this.screenshot('02_task_stats');
-
- // 3. 验证统计图表
- const result = await this.getSnapshot();
- const hasStats = result.some(item =>
- item.text.includes('完成率') ||
- item.text.includes('任务数') ||
- item.text.includes('统计')
- );
-
- this.logResult(hasStats);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * WEB-004: 指导师登录测试
- */
- class WEB_004_TestCase extends WebTestCase {
- constructor() {
- super('WEB-004', '指导师登录Web后台', 'P0');
- }
- async run() {
- try {
- await this.setup();
-
- // 1. 打开登录页面
- console.log(`[${this.id}] 访问: ${TEST_CONFIG.webAdminUrl}`);
- await this.screenshot('01_teacher_login_page');
-
- // 2. 输入指导师账号
- const phoneInput = await this.waitForElement('手机号');
- await this.fill(phoneInput.uid, TEST_CONFIG.teacherAccount.phone);
-
- const pwdInput = await this.waitForElement('密码');
- await this.fill(pwdInput.uid, TEST_CONFIG.teacherAccount.password);
- await this.screenshot('02_teacher_form_filled');
-
- // 3. 登录
- const loginBtn = await this.waitForElement('登录');
- await this.click(loginBtn.uid);
- await this.screenshot('03_teacher_after_login');
-
- // 4. 验证指导师界面
- const result = await this.getSnapshot();
- const hasGuideFeatures = result.some(item =>
- item.text.includes('指导') ||
- item.text.includes('家庭') ||
- item.text.includes('任务')
- );
-
- this.logResult(hasGuideFeatures);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * WEB-005: 指导师查看分配的家庭
- */
- class WEB_005_TestCase extends WebTestCase {
- constructor() {
- super('WEB-005', '指导师查看分配的家庭', 'P0');
- }
- async run() {
- try {
- await this.setup();
- await this.loginTeacher();
-
- // 1. 查看我的家庭
- const myFamilies = await this.waitForElement('我的家庭');
- await this.click(myFamilies.uid);
- await this.screenshot('01_my_families');
-
- // 2. 验证家庭列表
- const result = await this.getSnapshot();
- const hasFamilies = result.some(item =>
- item.text.includes('家庭') ||
- item.text.includes('孩子')
- );
-
- this.logResult(hasFamilies);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * WEB-006: 管理员审核指导师注册
- */
- class WEB_006_TestCase extends WebTestCase {
- constructor() {
- super('WEB-006', '管理员审核指导师注册', 'P1');
- }
- async run() {
- try {
- await this.setup();
- await this.loginAdmin();
-
- // 1. 进入指导师管理
- const guideMenu = await this.waitForElement('指导师管理');
- await this.click(guideMenu.uid);
- await this.screenshot('01_guide_menu');
-
- // 2. 查看待审核
- const pendingBtn = await this.waitForElement('待审核');
- await this.click(pendingBtn.uid);
- await this.screenshot('02_pending_guides');
-
- // 3. 审核操作
- const approveBtn = await this.waitForElement('通过');
- await this.click(approveBtn.uid);
- await this.screenshot('03_approved');
-
- this.logResult(true);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- /**
- * WEB-007: 管理员查看街道统计
- */
- class WEB_007_TestCase extends WebTestCase {
- constructor() {
- super('WEB-007', '管理员查看街道统计', 'P1');
- }
- async run() {
- try {
- await this.setup();
- await this.loginAdmin();
-
- // 1. 进入统计分析
- const statsMenu = await this.waitForElement('统计分析');
- await this.click(statsMenu.uid);
- await this.screenshot('01_stats_menu');
-
- // 2. 街道分布
- const streetBtn = await this.waitForElement('街道分布');
- await this.click(streetBtn.uid);
- await this.screenshot('02_street_stats');
-
- this.logResult(true);
- } catch (error) {
- this.logResult(false, error);
- }
- }
- }
- // ============================================================================
- // 测试套件管理
- // ============================================================================
- class TestSuite {
- constructor() {
- this.testCases = [];
- this.results = {
- total: 0,
- passed: 0,
- failed: 0,
- skipped: 0,
- coverage: {
- P0: { total: 0, passed: 0 },
- P1: { total: 0, passed: 0 },
- P2: { total: 0, passed: 0 }
- }
- };
- this.apiTestData = []; // 记录所有API测试数据
- this.webTestScreenshots = []; // 记录所有Web测试截图
- }
- /**
- * 注册测试用例
- */
- register(testCase) {
- this.testCases.push(testCase);
- this.results.total++;
- this.results.coverage[testCase.priority].total++;
- }
- /**
- * 运行所有测试
- */
- async runAll() {
- console.log('========================================');
- console.log('心知益家 - 自动化测试开始');
- console.log(`测试用例总数: ${this.testCases.length}`);
- console.log('========================================\n');
- for (const testCase of this.testCases) {
- console.log(`\n>>> 执行测试: ${testCase.id} - ${testCase.description}`);
- try {
- await testCase.run();
- if (testCase.status === 'passed') {
- this.results.passed++;
- this.results.coverage[testCase.priority].passed++;
- } else {
- this.results.failed++;
- }
- // 收集测试数据
- if (testCase instanceof ApiTestCase) {
- this.apiTestData.push({
- id: testCase.id,
- description: testCase.description,
- request: testCase.requestData,
- response: testCase.responseData,
- status: testCase.status
- });
- } else if (testCase instanceof WebTestCase) {
- this.webTestScreenshots.push({
- id: testCase.id,
- description: testCase.description,
- screenshots: testCase.screenshots,
- status: testCase.status
- });
- }
- } catch (error) {
- console.error(`[${testCase.id}] 测试执行异常:`, error);
- this.results.failed++;
- testCase.status = 'failed';
- testCase.error = error;
- }
- }
- this.generateReport();
- }
- /**
- * 按优先级运行测试
- */
- async runByPriority(priority) {
- const filteredTests = this.testCases.filter(tc => tc.priority === priority);
- console.log(`\n运行 ${priority} 级测试用例: ${filteredTests.length} 个\n`);
- for (const testCase of filteredTests) {
- await testCase.run();
- if (testCase.status === 'passed') {
- this.results.passed++;
- this.results.coverage[testCase.priority].passed++;
- } else {
- this.results.failed++;
- }
- }
- this.generateReport();
- }
- /**
- * 生成测试报告
- */
- generateReport() {
- console.log('\n========================================');
- console.log('测试执行完成 - 测试报告');
- console.log('========================================');
- console.log(`总测试数: ${this.results.total}`);
- console.log(`通过: ${this.results.passed} ✅`);
- console.log(`失败: ${this.results.failed} ❌`);
- console.log(`跳过: ${this.results.skipped} ⏭️`);
- console.log(`通过率: ${((this.results.passed / this.results.total) * 100).toFixed(2)}%`);
- console.log('\n需求覆盖度:');
- console.log(` P0: ${this.results.coverage.P0.passed}/${this.results.coverage.P0.total}`);
- console.log(` P1: ${this.results.coverage.P1.passed}/${this.results.coverage.P1.total}`);
- console.log(` P2: ${this.results.coverage.P2.passed}/${this.results.coverage.P2.total}`);
- console.log('========================================\n');
- // 输出API测试数据汇总
- if (this.apiTestData.length > 0) {
- console.log('\n========================================');
- console.log('API接口测试数据汇总');
- console.log('========================================');
- this.apiTestData.forEach(test => {
- console.log(`\n[${test.id}] ${test.description}`);
- console.log('请求:', JSON.stringify(test.request, null, 2));
- console.log('响应:', JSON.stringify(test.response, null, 2));
- });
- }
- // 输出Web测试截图汇总
- if (this.webTestScreenshots.length > 0) {
- console.log('\n========================================');
- console.log('Web浏览器测试截图汇总');
- console.log('========================================');
- this.webTestScreenshots.forEach(test => {
- console.log(`\n[${test.id}] ${test.description}`);
- console.log('截图:', test.screenshots.join(', '));
- });
- }
- // 生成JSON报告
- const report = {
- timestamp: new Date().toISOString(),
- summary: this.results,
- apiTests: this.apiTestData,
- webTests: this.webTestScreenshots,
- details: this.testCases.map(tc => ({
- id: tc.id,
- description: tc.description,
- priority: tc.priority,
- status: tc.status,
- error: tc.error?.message || null,
- screenshots: tc.screenshots || [],
- requestData: tc.requestData || null,
- responseData: tc.responseData || null
- }))
- };
- return report;
- }
- }
- // ============================================================================
- // 导出测试用例和运行器
- // ============================================================================
- module.exports = {
- TestSuite,
- TEST_CONFIG,
-
- // API测试用例(小程序端)
- apiTestCases: {
- API_001_TestCase,
- API_002_TestCase,
- API_003_TestCase,
- API_004_TestCase,
- API_005_TestCase,
- API_006_TestCase,
- API_007_TestCase,
- API_008_TestCase,
- API_009_TestCase,
- API_010_TestCase
- },
-
- // Web浏览器测试用例(管理后台)
- webTestCases: {
- WEB_001_TestCase,
- WEB_002_TestCase,
- WEB_003_TestCase,
- WEB_004_TestCase,
- WEB_005_TestCase,
- WEB_006_TestCase,
- WEB_007_TestCase
- }
- };
- // ============================================================================
- // 主程序入口
- // ============================================================================
- async function main() {
- const suite = new TestSuite();
- // 注册API测试用例(小程序端)
- Object.values(module.exports.apiTestCases).forEach(TestCase => {
- const testCase = new TestCase();
- if (testCase.priority === 'P0') {
- suite.register(testCase);
- }
- });
- // 注册Web测试用例(管理后台)
- Object.values(module.exports.webTestCases).forEach(TestCase => {
- const testCase = new TestCase();
- if (testCase.priority === 'P0') {
- suite.register(testCase);
- }
- });
- // 运行测试
- await suite.runAll();
- }
- // 如果直接运行此脚本
- if (require.main === module) {
- main().catch(console.error);
- }
|