/** * 武术比赛报名系统API自动化测试脚本 * 运行方式:node test/api-test.js * 需要先安装axios: npm install axios */ const axios = require('axios'); // 配置 const config = { baseURL: 'http://your-api-domain.com', // 修改为你的API地址 timeout: 10000, testUser: { username: 'test_user', password: 'test_password' } }; // 创建axios实例 const api = axios.create({ baseURL: config.baseURL, timeout: config.timeout, headers: { 'Content-Type': 'application/json' } }); // 测试结果统计 const testResults = { total: 0, passed: 0, failed: 0, errors: [] }; // 全局变量存储测试数据 let token = ''; let testCompetitionId = ''; let testAthleteId = ''; let testRegistrationId = ''; // 工具函数:断言 function assert(condition, testName, message) { testResults.total++; if (condition) { testResults.passed++; console.log(`✓ ${testName}`); return true; } else { testResults.failed++; console.error(`✗ ${testName}: ${message}`); testResults.errors.push({ test: testName, message }); return false; } } // 工具函数:设置Token function setToken(newToken) { token = newToken; api.defaults.headers['Blade-Auth'] = `Bearer ${token}`; } // 测试用例 const tests = { // 1. 用户登录测试 async testLogin() { console.log('\n【测试1】用户登录'); try { const res = await api.post('/martial/auth/login', config.testUser); assert(res.status === 200, '登录请求HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '登录业务状态码', `期望200,实际${res.data.code}`); assert(res.data.data && res.data.data.token, '返回Token', '未返回token'); if (res.data.data && res.data.data.token) { setToken(res.data.data.token); console.log(` Token: ${token.substring(0, 20)}...`); } return true; } catch (err) { assert(false, '登录请求', err.message); return false; } }, // 2. 获取轮播图列表 async testBannerList() { console.log('\n【测试2】获取轮播图列表'); try { const res = await api.get('/martial/banner/list'); assert(res.status === 200, '轮播图请求HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '轮播图业务状态码', `期望200,实际${res.data.code}`); assert(Array.isArray(res.data.data), '返回数据格式', '期望数组格式'); console.log(` 轮播图数量: ${res.data.data ? res.data.data.length : 0}`); } catch (err) { assert(false, '轮播图请求', err.message); } }, // 3. 获取赛事列表 async testCompetitionList() { console.log('\n【测试3】获取赛事列表'); try { const res = await api.get('/martial/competition/list', { params: { current: 1, size: 20 } }); assert(res.status === 200, '赛事列表HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '赛事列表业务状态码', `期望200,实际${res.data.code}`); const hasRecords = res.data.data && res.data.data.records && res.data.data.records.length > 0; const isArray = Array.isArray(res.data.data) && res.data.data.length > 0; assert(hasRecords || isArray, '返回赛事数据', '未返回赛事数据'); if (hasRecords) { testCompetitionId = res.data.data.records[0].id; console.log(` 赛事数量: ${res.data.data.records.length}`); console.log(` 测试赛事ID: ${testCompetitionId}`); } else if (isArray) { testCompetitionId = res.data.data[0].id; console.log(` 赛事数量: ${res.data.data.length}`); console.log(` 测试赛事ID: ${testCompetitionId}`); } } catch (err) { assert(false, '赛事列表请求', err.message); } }, // 4. 获取赛事详情 async testCompetitionDetail() { console.log('\n【测试4】获取赛事详情'); if (!testCompetitionId) { console.log(' 跳过:未获取到测试赛事ID'); return; } try { const res = await api.get('/martial/competition/detail', { params: { id: testCompetitionId } }); assert(res.status === 200, '赛事详情HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '赛事详情业务状态码', `期望200,实际${res.data.code}`); assert(res.data.data && res.data.data.id, '返回赛事详情', '未返回详情数据'); if (res.data.data) { console.log(` 赛事名称: ${res.data.data.name || res.data.data.title || '未知'}`); console.log(` 赛事地点: ${res.data.data.location || res.data.data.address || '未知'}`); } } catch (err) { assert(false, '赛事详情请求', err.message); } }, // 5. 获取选手列表 async testAthleteList() { console.log('\n【测试5】获取选手列表'); try { const res = await api.get('/martial/athlete/list', { params: { current: 1, size: 100 } }); assert(res.status === 200, '选手列表HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '选手列表业务状态码', `期望200,实际${res.data.code}`); const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0; const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0; console.log(` 选手数量: ${records || arrayLength}`); } catch (err) { assert(false, '选手列表请求', err.message); } }, // 6. 新增选手 async testCreateAthlete() { console.log('\n【测试6】新增选手'); try { const res = await api.post('/martial/athlete/submit', { name: '测试选手_' + Date.now(), idCard: '110101199001011234', team: '测试队伍', gender: '男', phone: '13800138000' }); assert(res.status === 200, '新增选手HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '新增选手业务状态码', `期望200,实际${res.data.code}`); if (res.data.data && res.data.data.id) { testAthleteId = res.data.data.id; console.log(` 新增选手ID: ${testAthleteId}`); } else if (res.data.data) { testAthleteId = res.data.data; console.log(` 新增选手ID: ${testAthleteId}`); } } catch (err) { assert(false, '��增选手请求', err.message); } }, // 7. 获取选手详情 async testAthleteDetail() { console.log('\n【测试7】获取选手详情'); if (!testAthleteId) { console.log(' 跳过:未获取到测试选手ID'); return; } try { const res = await api.get('/martial/athlete/detail', { params: { id: testAthleteId } }); assert(res.status === 200, '选手详情HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '选手详情业务状态码', `期望200,实际${res.data.code}`); assert(res.data.data && res.data.data.name, '返回选手详情', '未返回详情数据'); if (res.data.data) { console.log(` 选手姓名: ${res.data.data.name}`); } } catch (err) { assert(false, '选手详情请求', err.message); } }, // 8. 获取报名项目列表 async testProjectList() { console.log('\n【测试8】获取报名项目列表'); if (!testCompetitionId) { console.log(' 跳过:未获取到测试赛事ID'); return; } try { const res = await api.get('/martial/project/list', { params: { competitionId: testCompetitionId } }); assert(res.status === 200, '项目列表HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '项目列表业务状态码', `期望200,实际${res.data.code}`); const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0; const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0; console.log(` 项目数量: ${records || arrayLength}`); } catch (err) { assert(false, '项目列表请求', err.message); } }, // 9. 获取我的报名列表 async testRegistrationList() { console.log('\n【测试9】获取我的报名列表'); try { const res = await api.get('/martial/registration/list', { params: { current: 1, size: 20 } }); assert(res.status === 200, '报名列表HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '报名列表业务状态码', `期望200,实际${res.data.code}`); const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0; const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0; console.log(` 报名记录数量: ${records || arrayLength}`); } catch (err) { assert(false, '报名列表请求', err.message); } }, // 10. 获取用户信息 async testUserInfo() { console.log('\n【测试10】获取用户信息'); try { const res = await api.get('/martial/user/info'); assert(res.status === 200, '用户信息HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '用户信息业务状态码', `期望200,实际${res.data.code}`); assert(res.data.data, '返回用户信息', '未返回用户数据'); if (res.data.data) { console.log(` 用户名: ${res.data.data.name || res.data.data.username || '未知'}`); } } catch (err) { assert(false, '用户信息请求', err.message); } }, // 11. 获取赛事信息公告 async testInfoList() { console.log('\n【测试11】获取赛事信息公告'); if (!testCompetitionId) { console.log(' 跳过:未获取到测试赛事ID'); return; } try { const res = await api.get('/martial/info/list', { params: { competitionId: testCompetitionId } }); assert(res.status === 200, '信息公告HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '信息公告业务状态码', `期望200,实际${res.data.code}`); const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0; const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0; console.log(` 公告数量: ${records || arrayLength}`); } catch (err) { assert(false, '信息公告请求', err.message); } }, // 12. 获取成绩列表 async testResultList() { console.log('\n【测试12】获取成绩列表'); if (!testCompetitionId) { console.log(' 跳过:未获取到测试赛事ID'); return; } try { const res = await api.get('/martial/result/list', { params: { competitionId: testCompetitionId, current: 1, size: 100 } }); assert(res.status === 200, '成绩列表HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '成绩列表业务状态码', `期望200,实际${res.data.code}`); const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0; const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0; console.log(` 成绩记录数量: ${records || arrayLength}`); } catch (err) { assert(false, '成绩列表请求', err.message); } }, // 13. 获取奖牌榜 async testMedalsList() { console.log('\n【测试13】获取奖牌榜'); if (!testCompetitionId) { console.log(' 跳过:未获取到测试赛事ID'); return; } try { const res = await api.get('/martial/medal/list', { params: { competitionId: testCompetitionId } }); assert(res.status === 200, '奖牌榜HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '奖牌榜业务状态码', `期望200,实际${res.data.code}`); const records = res.data.data && res.data.data.records ? res.data.data.records.length : 0; const arrayLength = Array.isArray(res.data.data) ? res.data.data.length : 0; console.log(` 奖牌榜队伍数: ${records || arrayLength}`); } catch (err) { assert(false, '奖牌榜请求', err.message); } }, // 14. 删除测试选手(清理数据) async testDeleteAthlete() { console.log('\n【测试14】删除测试选手(清理数据)'); if (!testAthleteId) { console.log(' 跳过:未创建测试选手'); return; } try { const res = await api.delete('/martial/athlete/remove', { params: { ids: testAthleteId } }); assert(res.status === 200, '删除选手HTTP状态码', `期望200,实际${res.status}`); assert(res.data.code === 200, '删除选手业务状态码', `期望200,实际${res.data.code}`); console.log(` 成功删除测试选手: ${testAthleteId}`); } catch (err) { assert(false, '删除选手请求', err.message); } } }; // 运行所有测试 async function runAllTests() { console.log('='.repeat(60)); console.log('武术比赛报名系统 - API自动化测试'); console.log('='.repeat(60)); console.log(`测试开始时间: ${new Date().toLocaleString()}`); console.log(`API地址: ${config.baseURL}`); const startTime = Date.now(); // 按顺序执行所有测试 for (const [name, testFn] of Object.entries(tests)) { try { await testFn(); } catch (err) { console.error(`\n测试执行异常 [${name}]:`, err.message); } } const duration = ((Date.now() - startTime) / 1000).toFixed(2); // 输出测试结果 console.log('\n' + '='.repeat(60)); console.log('测试结果汇总'); console.log('='.repeat(60)); console.log(`总测试数: ${testResults.total}`); console.log(`通过: ${testResults.passed} ✓`); console.log(`失败: ${testResults.failed} ✗`); console.log(`成功率: ${testResults.total > 0 ? ((testResults.passed / testResults.total) * 100).toFixed(2) : 0}%`); console.log(`耗时: ${duration}秒`); console.log(`测试结束时间: ${new Date().toLocaleString()}`); if (testResults.failed > 0) { console.log('\n失败的测试:'); testResults.errors.forEach((err, index) => { console.log(`${index + 1}. ${err.test}: ${err.message}`); }); } console.log('='.repeat(60)); // 退出进程,返回状态码 process.exit(testResults.failed > 0 ? 1 : 0); } // 执行测试 runAllTests().catch(err => { console.error('测试执行失败:', err); process.exit(1); });