- gen-*.js: 시나리오 자동 생성기 12종 (CRUD, edge, a11y, perf 등) - search-*.js: 검색/버튼 감사 수집기 3종 - revert-hard-actions.js: 하드 액션 복원 유틸 - _gen_writer.py: 생성기 보조 스크립트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
154 lines
6.4 KiB
JavaScript
154 lines
6.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* 성능 측정 베이스라인 시나리오 생성기
|
|
*
|
|
* 주요 17개 페이지에 대해 성능 측정 시나리오를 자동 생성한다.
|
|
* 각 시나리오는:
|
|
* 1. 페이지 로드 대기
|
|
* 2. 테이블 로드 대기
|
|
* 3. measure_performance - Navigation Timing, Resource Timing, DOM 노드, 메모리 수집
|
|
* 4. measure_api_performance - ApiMonitor 로그 기반 API 성능 분석
|
|
* 5. assert_performance - 임계값 기준 통과/실패 판정
|
|
*
|
|
* Usage: node e2e/runner/gen-performance-baseline.js
|
|
*
|
|
* Output:
|
|
* e2e/scenarios/perf-{page-id}.json (17개 파일)
|
|
*
|
|
* Run generated scenarios:
|
|
* node e2e/runner/run-all.js --filter perf
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const SCENARIOS_DIR = path.resolve(__dirname, '..', 'scenarios');
|
|
|
|
// ════════════════════════════════════════════════════════════════
|
|
// 페이지 매니페스트 (17개)
|
|
// ════════════════════════════════════════════════════════════════
|
|
const PAGES = [
|
|
// 판매관리
|
|
{ id: 'perf-sales-client', name: '판매관리 > 거래처관리', level1: '판매관리', level2: '거래처관리' },
|
|
{ id: 'perf-sales-price', name: '판매관리 > 단가관리', level1: '판매관리', level2: '단가관리' },
|
|
{ id: 'perf-sales-estimate', name: '판매관리 > 견적관리', level1: '판매관리', level2: '견적관리' },
|
|
{ id: 'perf-sales-order', name: '판매관리 > 수주관리', level1: '판매관리', level2: '수주관리' },
|
|
|
|
// 회계관리
|
|
{ id: 'perf-acc-client', name: '회계관리 > 거래처관리', level1: '회계관리', level2: '거래처관리' },
|
|
{ id: 'perf-acc-sales', name: '회계관리 > 매출관리', level1: '회계관리', level2: '매출관리', tableTimeout: 20000 },
|
|
{ id: 'perf-acc-purchase', name: '회계관리 > 매입관리', level1: '회계관리', level2: '매입관리' },
|
|
{ id: 'perf-acc-deposit', name: '회계관리 > 입금관리', level1: '회계관리', level2: '입금관리' },
|
|
|
|
// 인사관리
|
|
{ id: 'perf-hr-employee', name: '인사관리 > 사원관리', level1: '인사관리', level2: '사원관리' },
|
|
{ id: 'perf-hr-attendance', name: '인사관리 > 근태관리', level1: '인사관리', level2: '근태관리' },
|
|
{ id: 'perf-hr-salary', name: '인사관리 > 급여관리', level1: '인사관리', level2: '급여관리' },
|
|
{ id: 'perf-hr-department', name: '인사관리 > 부서관리', level1: '인사관리', level2: '부서관리', tableTimeout: 20000 },
|
|
|
|
// 생산관리
|
|
{ id: 'perf-prod-work-order', name: '생산관리 > 작업지시', level1: '생산관리', level2: '작업지시' },
|
|
{ id: 'perf-prod-work-result', name: '생산관리 > 작업실적', level1: '생산관리', level2: '작업실적' },
|
|
{ id: 'perf-prod-item', name: '생산관리 > 품목관리', level1: '생산관리', level2: '품목관리', tableTimeout: 20000 },
|
|
|
|
// 자재관리
|
|
{ id: 'perf-material-stock', name: '자재관리 > 재고현황', level1: '자재관리', level2: '재고현황' },
|
|
{ id: 'perf-material-receiving', name: '자재관리 > 입고관리', level1: '자재관리', level2: '입고관리' },
|
|
];
|
|
|
|
// ════════════════════════════════════════════════════════════════
|
|
// 시나리오 생성 함수
|
|
// ════════════════════════════════════════════════════════════════
|
|
function generateScenario(page) {
|
|
const steps = [];
|
|
let stepId = 1;
|
|
|
|
// Step 1: 페이지 로드 대기
|
|
steps.push({
|
|
id: stepId++,
|
|
name: '페이지 로드 대기',
|
|
action: 'wait',
|
|
timeout: 3000,
|
|
});
|
|
|
|
// Step 2: 테이블 로드 대기
|
|
steps.push({
|
|
id: stepId++,
|
|
name: '테이블 로드 대기',
|
|
action: 'wait_for_table',
|
|
timeout: page.tableTimeout || 5000,
|
|
});
|
|
|
|
// Step 3: 페이지 성능 측정 (Navigation Timing, Resource Timing, DOM, Memory)
|
|
steps.push({
|
|
id: stepId++,
|
|
name: '페이지 성능 측정',
|
|
action: 'measure_performance',
|
|
timeout: 10000,
|
|
phase: 'PERF_MEASURE',
|
|
});
|
|
|
|
// Step 4: API 성능 측정 (ApiMonitor 로그 분석)
|
|
steps.push({
|
|
id: stepId++,
|
|
name: 'API 성능 측정',
|
|
action: 'measure_api_performance',
|
|
timeout: 10000,
|
|
phase: 'API_PERF',
|
|
});
|
|
|
|
// Step 5: 성능 기준 검증 (임계값 비교)
|
|
steps.push({
|
|
id: stepId++,
|
|
name: '성능 기준 검증',
|
|
action: 'assert_performance',
|
|
thresholds: {
|
|
pageLoad: 3000,
|
|
apiAvg: 2000,
|
|
domNodes: 5000,
|
|
},
|
|
timeout: 5000,
|
|
phase: 'PERF_ASSERT',
|
|
});
|
|
|
|
return {
|
|
id: page.id,
|
|
name: `성능 측정: ${page.name}`,
|
|
version: '1.0.0',
|
|
auth: { role: 'admin' },
|
|
menuNavigation: {
|
|
level1: page.level1,
|
|
level2: page.level2,
|
|
},
|
|
screenshotPolicy: {
|
|
captureOnFail: true,
|
|
captureOnPass: false,
|
|
},
|
|
steps,
|
|
};
|
|
}
|
|
|
|
// ════════════════════════════════════════════════════════════════
|
|
// 메인 실행
|
|
// ════════════════════════════════════════════════════════════════
|
|
function main() {
|
|
if (!fs.existsSync(SCENARIOS_DIR)) {
|
|
fs.mkdirSync(SCENARIOS_DIR, { recursive: true });
|
|
}
|
|
|
|
console.log('\n === Performance Baseline Scenario Generator ===\n');
|
|
|
|
let count = 0;
|
|
for (const page of PAGES) {
|
|
const scenario = generateScenario(page);
|
|
const fp = path.join(SCENARIOS_DIR, `${scenario.id}.json`);
|
|
fs.writeFileSync(fp, JSON.stringify(scenario, null, 2), 'utf-8');
|
|
console.log(` ${scenario.id}.json (${scenario.steps.length} steps)`);
|
|
count++;
|
|
}
|
|
|
|
console.log(`\n Generated ${count} performance scenarios`);
|
|
console.log(` Run: node e2e/runner/run-all.js --filter perf\n`);
|
|
}
|
|
|
|
main();
|