419 lines
14 KiB
JavaScript
419 lines
14 KiB
JavaScript
/**
|
||
* 武术比赛报名系统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, '<27><>增选手请求', 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);
|
||
});
|