Artillery 부하 테스트 하기
갑작스레 부하 테스트 및 원인 수정 알바가 들어와서 부하 처리를 하게 되었다. 이전에도 잠깐이나마 Artillery로 테스트 코드를 작성한 적이 있었는데, 기억도 안나고 테스트 파일도 찾을 수가 없어서, 이번에 나온 GPT-4o 성능도 체험할겸 GPT-4o 에게 도움을 받아서 작성하고 테스트 하기로 하였다.
1. GPT-4o 에게 기본 YML 작성 요청 하기
요청 질문:
답변 :
Artillery를 사용하여 100명의 동시 접속자 테스트를 실행하기 위한 yml 파일을 작성하려면, 다음과 같은 설정이 필요합니다. 이 파일은 60초 동안 1명에서 100명까지 점차적으로 증가하며, 특정 Web Element에 ID 및 비밀번호를 입력하고 로그인 버튼을 클릭한 후, 결과를 HTML 보고서로 출력하도록 구성합니다.
config: target: 'https://localhost' phases: - duration: 60 arrivalRate: 1 rampTo: 100 payload: path: 'users.csv' fields: - "username" - "password" environments: production: target: 'https://localhost' plugins: html: { "output": "test-report.html" } scenarios: - flow: - get: url: "/login" - think: 1 - post: url: "/login" form: username: "{{ username }}" password: "{{ password }}" - think: 1 - log: "Logged in with {{ username }}" plugins: html: enabled: true
이 설정 파일을 사용하기 전에 다음과 같은 사항을 준비해야 합니다:
users.csv 파일: 사용자의 ID와 비밀번호를 포함한 CSV 파일을 준비해야 합니다. 예를 들어:
username,password user1,pass1 user2,pass2 user3,pass3 ...
Artillery 설치: 아직 설치하지 않았다면, Artillery를 설치해야 합니다.
npm install -g artillery
테스트 실행: 준비가 완료되면, 다음 명령어를 사용하여 테스트를 실행할 수 있습니다.
artillery run test.yml
이 설정 파일은 Artillery가 1명에서 시작하여 60초 동안 100명까지 점차 증가하는 부하 테스트를 수행하고, 로그인 페이지에 접근하여 ID와 비밀번호를 입력한 후 로그인하는 시나리오를 실행합니다. 결과는 HTML 보고서로 출력됩니다.
완벽하지는 않지만 얼추 Yml의 기본 설정 정도는 짜여있다.
2. 수정 요청 및 다듬기 (feeat. 삽질)
제법 그럴 듯 하게 작성은 해주었지만... ID 패스워드 입력하는 부분이 HTTP 요청으로 작성되어서 원하는 결과 값은 아니기 때문에 수정 요청을 진행 하였다.
- CSV는 동적으로 처리 하고 싶다.
- CSS Selector 를 이용해 클릭 등의 요청을 하고 싶다.
위의 내용으로 작성 하였더니 Puppeteer 를 설치하게 유도 하고 소스코드를 짜주었는데, 짜준 소스가 실행이 되지 않았고, 몇번이고 물어 보았지만, 처리가 되지 않았다. 뭔가 이상하다고 느낀 나는 Artillery docs를 읽어 보게 되었다.
조금 조사해 보니 원하는 요청을 처리하려면 playwright 엔진을 사용하면 될 것 같아. playwright 엔진으로 작성해 달라고 요청 하였다.
재 수정된 요청 내용
- Artillery Engine 은 Playwright 로 작성해 줘
- CSV는 동적으로 처리 하고 싶다.
- 동적으로 만든 데이터를 이용해서 로그인 처리
- CSS Selector 를 이용해 클릭 등의 요청을 하고 싶다.
대충 삽질한 흔적들... 잘못 알려준 소스코드 방식, 덕분에 Pupeteer를 알게됨
- 존재 하지 않는 패키지 설치를 알려준... GPT
- 내가 못 찾았을 수도 있지만.. Docs 어디를 뒤져 봐도 나오지 않던 actions / script 문구
- 그 외에도 많은 오류가 있었지만... 생략 한다.
3. 수정된 GPT 답변
Artillery와 Playwright를 함께 사용하여 웹사이트 부하 테스트를 수행할 수 있습니다. Playwright는 Puppeteer와 유사하지만, 브라우저 자동화와 테스트를 더 효율적으로 지원하는 도구입니다. 다음은 Artillery와 Playwright를 사용하여 동적으로 생성된 사용자 자격 증명을 활용한 테스트를 구성하는 방법입니다.
필요한 패키지 설치:
npm install -g artillery npm install playwright
payload-generator.js
파일 작성:module.exports = { generateLoginPayload: function(context, events, done) { const users = [ { username: 'user1@example.com', password: 'password1' }, { username: 'user2@example.com', password: 'password2' }, // 추가 사용자 자격 증명 ]; const user = users[Math.floor(Math.random() * users.length)]; context.vars.username = user.username; context.vars.password = user.password; return done(); } };
Playwright 스크립트 작성: Playwright 스크립트를 별도의 파일로 작성합니다. 예를 들어
playwright-script.js
파일을 작성합니다.const { chromium } = require('playwright'); module.exports = async function(context, events, done) { const browser = await chromium.launch(); const page = await browser.newPage(); const username = context.vars.username; const password = context.vars.password; try { // 로그인 페이지로 이동 await page.goto('http://localhost/login'); // ID와 비밀번호 입력 await page.fill('#username', username); await page.fill('#password', password); // 로그인 버튼 클릭 await page.click('#login-button'); // 추가적인 사용자 액션 await page.waitForSelector('#dashboard'); await page.click('#some-button'); } catch (err) { console.error(err); } finally { await browser.close(); done(); } };
Artillery YAML 파일 작성: Playwright 스크립트를 호출하는 Artillery YAML 파일을 작성합니다.
config: target: 'http://localhost/login' phases: - duration: 60 arrivalRate: 1 # 1 user per second rampTo: 10 - duration: 60 arrivalRate: 10 # 10 users per second rampTo: 100 processor: "./payload-generator.js" engines: playwright: {} scenarios: - beforeRequest: "generateLoginPayload" - flow: - action: "playwright" script: "./playwright-script.js"
테스트 실행: Artillery 명령어를 사용하여 테스트를 실행합니다.
artillery run your-test-file.yaml
이 설정에서는 Playwright 스크립트를 Artillery의
playwright
엔진을 통해 호출하고, 동적으로 생성된 사용자 자격 증명을 이용하여 웹사이트 테스트를 수행합니다. Playwright 스크립트는 브라우저를 열고, 로그인 페이지로 이동하여 ID와 비밀번호를 입력하고 로그인 버튼을 클릭한 후 추가적인 사용자 액션을 수행합니다.
띡! 하면 뚀! 하고 처리 되었으면 좋았겠지만...
그럴 듯 하게 수정해서 주었지만 현상태로는 동작하지 않았고, 잘못된 문법은 따로 찾아서 수정 하였다.
4. 구동 성공한 테스트 소스
test.yml
config:
target: 'https//localhost'
phases:
- duration: 60 # 몇 초간 실행할 건지
arrivalRate: 10 # 10 users per second
rampTo: 100 # 초당 인원이 증가하여 최대 증가힐 안원 수
name: '10초간 10~100명 요청 테스트' # Phase 네임
engines:
playwright:
launchOptions:
headless: true # false시 브라우저 띄워서 보여줌
defaults:
headers:
userAgent: 'Artillery'
processor: './payload-generator.js'
before:
engine: playwright
flowFunction: "generateLoginPayload"
scenarios:
- engine: playwright
name: 'playwright'
flowFunction: 'testFlow'
payload-generator.js
module.exports = {
// 유저 생성 함수
generateLoginPayload: function (context, events, done) {
const users = [
{ username: 'user1@example.com', password: 'password1' },
{ username: 'user2@example.com', password: 'password2' },
];
const user = users[Math.floor(Math.random() * users.length)];
context.vars.username = user.username;
context.vars.password = user.password;
return done()
},
// 웹 페이지 flow
testFlow: async function (page, context) {
const username = context.vars.username;
const password = context.vars.password;
try {
// 로그인 페이지로 이동
await page.goto('http://loclahost/login');
// ID와 비밀번호 입력
await page.fill('#username', username);
await page.fill('#password', password);
// 로그인 버튼 클릭
await page.click('#login-button');
// 추가적인 사용자 액션
await page.waitForSelector('#dashboard');
await page.click('#some-button');
} catch (err) {
console.error(err);
} finally {
}
}
};
Node 실행문
일반 테스트 실행시
# 테스트 요청
npx artillery run test.yml
# 리포트 요청시
npx artillery run test.yml --output report.json
Debug 모드
# 전체
DEBUG=http* npx artillery run test.yml
# Request
DEBUG=http:request npx artillery run test.yml
# Response
DEBUG=http:response npx artillery run test.yml
리포트 요청
# 동시실행
npx artillery run test.yml --output report.json && artillery report report.json
# 단일 리포트
npx artillery report report.json
후기
확실히 예전 모델 보다는 훨씬 빨라지고, 정확도나 반응이 좋아 졌음을 느낀다. 질문에 대한 답변도 그렇고, 수정 요청시 대응 하는 부분들... 마치 비서를 얻은 느낌으로 편하다.
하지만 아직까지는 100% 정답까지는 나오지 않아 수정을 해야하지만, 이게 어딘가 라는 생각이다. 기존에 개발하다가 구글링해서 검색하듯이.. 편리함에 익숙해져 GPT한테 물어봐서 작성하게 될 것 같다.
성공 코드 이후로는 개인적으로 프로젝트에 맞춰 커스텀 하여 정상적으로 부하 테스트 진행 할 수 있었다. 앞으로도 쭈욱 활용해서 개발하지 않을까... 싶지만, AI 발전 속도가 무섭다.
참조
- https://www.artillery.io/docs
- https://www.artillery.io/docs/reference/engines/playwright
- https://www.artillery.io/docs/reference/engines/http
- https://medium.com/@tolandominic/front-end-load-testing-with-playwright-and-artillery-4fa1ac615fda
- https://inpa.tistory.com/entry/JEST-%F0%9F%93%9A-%EB%B6%80%ED%95%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-Stress-Test