generated from pricelees/issue-pr-template
136 lines
4.3 KiB
JavaScript
136 lines
4.3 KiB
JavaScript
import http from 'k6/http';
|
|
import {check, sleep} from 'k6';
|
|
import exec from 'k6/execution';
|
|
import {BASE_URL, getHeaders, login, parseIdToString} from "./common.js";
|
|
import {randomIntBetween} from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
|
|
|
|
|
|
const TOTAL_ITERATIONS = 85212;
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
schedule_creation: {
|
|
executor: 'shared-iterations',
|
|
vus: 263,
|
|
iterations: TOTAL_ITERATIONS,
|
|
maxDuration: '30m',
|
|
},
|
|
},
|
|
thresholds: {
|
|
'http_req_duration': ['p(95)<3000'],
|
|
'http_req_failed': ['rate<0.1'],
|
|
},
|
|
};
|
|
|
|
export function setup() {
|
|
console.log('=== Setup: 테스트 데이터 및 작업 목록 준비 중 ===');
|
|
|
|
const themesRes = http.get(`${BASE_URL}/tests/themes`);
|
|
const themes = parseIdToString(themesRes).results
|
|
|
|
const accountsRes = http.get(`${BASE_URL}/tests/admin/accounts`);
|
|
const accounts = JSON.parse(accountsRes.body).results;
|
|
|
|
const dates = generateDates(7);
|
|
|
|
console.log(`총 매장 수: ${accounts.length}`);
|
|
console.log(`총 테마 수: ${themes.length}`);
|
|
console.log(`생성 기간: ${dates.length}일`);
|
|
|
|
const tasks = [];
|
|
for (const account of accounts) {
|
|
const loginResult = login(account.account, account.password, 'ADMIN');
|
|
if (loginResult === null) {
|
|
console.error(`[Setup] 로그인 실패: ${account.account}`);
|
|
continue;
|
|
}
|
|
const {storeId, accessToken} = loginResult;
|
|
|
|
// 5 ~ ${themes.size} 인 random 숫자 생성
|
|
const selectedThemes = selectRandomThemes(themes, randomIntBetween(5, themes.length));
|
|
|
|
for (const theme of selectedThemes) {
|
|
for (const date of dates) {
|
|
for (const time of theme.times) {
|
|
tasks.push({
|
|
storeId,
|
|
accessToken,
|
|
date,
|
|
time: time.startFrom,
|
|
themeId: theme.id,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log(`총 생성할 스케줄 수(iterations): ${tasks.length}`);
|
|
|
|
return {tasks};
|
|
}
|
|
|
|
export default function (data) {
|
|
// 👈 3. 현재 반복 횟수가 준비된 작업 수를 초과하는지 확인
|
|
const taskIndex = exec.scenario.iterationInTest;
|
|
|
|
if (taskIndex >= data.tasks.length) {
|
|
// 첫 번째로 이 조건에 도달한 VU가 테스트를 종료
|
|
if (taskIndex === data.tasks.length) {
|
|
console.log('모든 스케쥴 생성 완료. 테스트 종료');
|
|
exec.test.abort();
|
|
}
|
|
return;
|
|
}
|
|
const task = data.tasks[taskIndex];
|
|
|
|
if (!task) {
|
|
console.log(`[VU ${__VU}] 알 수 없는 오류: task가 없습니다. (index: ${taskIndex})`);
|
|
return;
|
|
}
|
|
|
|
createSchedule(task.storeId, task.accessToken, task);
|
|
}
|
|
|
|
function createSchedule(storeId, accessToken, schedule) {
|
|
const payload = JSON.stringify({
|
|
date: schedule.date,
|
|
time: schedule.time,
|
|
themeId: schedule.themeId,
|
|
});
|
|
const params = getHeaders(accessToken)
|
|
const res = http.post(`${BASE_URL}/admin/stores/${storeId}/schedules`, payload, params);
|
|
|
|
const success = check(res, {'일정 생성 성공': (r) => r.status === 200 || r.status === 201});
|
|
|
|
if (!success) {
|
|
console.error(`일정 생성 실패 [${res.status}]: 매장=${storeId}, ${schedule.date} ${schedule.time} (테마: ${schedule.themeId}) | 응답: ${res.body}`);
|
|
}
|
|
sleep(5)
|
|
|
|
return success;
|
|
}
|
|
|
|
function generateDates(days) {
|
|
const dates = [];
|
|
const today = new Date();
|
|
for (let i = 1; i <= days; i++) {
|
|
const date = new Date(today);
|
|
date.setDate(today.getDate() + i);
|
|
dates.push(date.toISOString().split('T')[0]);
|
|
}
|
|
return dates;
|
|
}
|
|
|
|
function selectRandomThemes(themes, count) {
|
|
const shuffled = [...themes].sort(() => 0.5 - Math.random());
|
|
return shuffled.slice(0, Math.min(count, themes.length));
|
|
}
|
|
|
|
export function teardown(data) {
|
|
if (data.tasks) {
|
|
console.log(`\n=== 테스트 완료: 총 ${data.tasks.length}개의 스케줄 생성을 시도했습니다. ===`);
|
|
} else {
|
|
console.log('\n=== 테스트 완료: setup 단계에서 오류가 발생하여 작업을 실행하지 못했습니다. ===');
|
|
}
|
|
}
|