QA 담당이 없을 때: 혼자 돌리는 시험, E2E, 그리고 믿으면 안 되는 초록불
QA 팀 없이 게임 네 개를 검증한 방법을 정리했다. 봇 시뮬레이션, 실제 서버에 붙는 E2E, 모바일 브라우저 자동 플레이, 그리고 필터를 건 '전부 통과'가 23건의 실패를 숨긴 사고까지 적었다.

혼자 게임을 만들면 QA 담당도 나다. 그런데 게임 네 개를 매일 손으로 끝까지 해 볼 수는 없다. 그래서 “사람 대신 뭔가가 끝까지 해 보게” 만드는 데 시간을 많이 썼다. 이 글은 게임별로 무엇을 자동으로 돌렸는지, 그리고 그 자동화가 어디서 나를 속였는지에 대한 기록이다.
네 게임의 검증 층
| 층 | AvoidNow | 랜선포차 | PallMark | Salmonholic |
|---|---|---|---|---|
| 규칙 단위 시험 | 판정 시험 (Godot, TS 양쪽 같은 값) | vitest, 미니게임마다 시험 | 시뮬 시험 5천여 건 | 골든 비교 |
| 자동 시뮬레이션 | 봇 20판 | 서버 시뮬레이션 200판 | 자동 플레이 녹화 | 100시드 스윕 |
| 실제 서버 E2E | Node와 DO 서버 둘 다 | 재접속·드레인 점검 | 해당 없음 | 재접속 점검 |
| 브라우저 E2E | 헤드리스 Chrome 클릭 | Playwright 모바일 | 해당 없음 | 3개 브라우저 매트릭스 |
| 화면 확인 | 녹화 프레임 | 게임별 스크린샷 모음 | 32컷 캡처 | 첫 60초 캡처 |
Salmonholic의 골든, 스윕, 소크 테스트는 다른 글에 자세히 있어서 여기서는 나머지 셋을 중심으로 적는다.
단위 시험이 못 보는 곳: 전송 계층
AvoidNow에서 9월 26일 밤에 버그 두 개가 CI를 통과해 버렸다.
하나는 화면 코드의 문법 오류였다. 규칙 시험(sim_test)은 게임 규칙만 불러오고 화면·UI 코드는 불러오지 않는다. 그러니 UI 파일이 깨져도 시험은 초록이었다.
다른 하나는 더 아팠다. 해외용 DO 서버가 플레이어 입력을 전부 무시했다. DO 런타임은 바이너리 웹소켓 프레임을 Blob으로 넘겨주는데, 입력 해석 코드는 바이트 배열만 기대했다. 그래서 서버에서 캐릭터가 한 발짝도 안 움직였다(커밋 7860504). 단위 시험은 방 로직만 봤고, Node와 DO 어댑터는 시험 대상이 아니었다.
다음 날 0시 33분 커밋 73c05a1에서 두 가지를 CI에 넣었다.
- 모든
.gd파일을 실제로 컴파일해 보는check_scripts.gd - 떠 있는 서버에 바이너리 입력을 보내 응답(ack)이 오르고 캐릭터가 움직이는지 보는
live.ts. CI가 Node 서버와wrangler dev로 띄운 DO 서버 양쪽에 대해 돌린다.
커밋 메시지 마지막 줄은 “둘 다 예전의 고장 난 코드에서는 실패하는 것을 확인했다”다. 새 검사를 넣을 때 고장 난 코드에서 빨간불이 뜨는지 먼저 본다. 안 뜨면 그 검사는 아무것도 지키지 않는다.
개발 서버에서 수백 판 돌리기
랜선포차는 미니게임이 24종이다. 최대 여섯 명이 한 방에서 하는 게임이라 손으로 시험하기가 제일 어렵다. 그래서 개발용 서버에서 판을 처음부터 끝까지 자동으로 돌리는 시뮬레이션 명령(sim 200)을 만들었다. 한 판 길이, 라운드 수, 탈락자 분포가 나온다. 9월 27일 새벽 기록은 “24종 모두 100% 종료, 한 판 7.5분”이다. “끝나지 않는 판”이 하나도 없다는 게 제일 중요한 숫자다.
화면은 Playwright로 따로 본다. e2e.mjs는 휴대폰 화면 크기로 홈 → 빠른 매칭 → 한 판 → 결과까지 따라가며 스크린샷과 콘솔 오류를 모은다. e2e-games.mjs는 게임마다 그 게임만 나오는 방 서버를 띄워 두 라운드씩 찍는다. 부하가 높을 때 서버 기동이 느려서 기다리는 시간을 15초에서 60초로 늘린 커밋(f3555ea)도 있다. 시험 도구도 고쳐 가며 쓴다.
Salmonholic 0.16.2의 첫 60초 점검 캡처. 왼쪽부터 수정 전 모바일, 수정 후 모바일, 수정 후 웹킷 화면이다
믿으면 안 되는 초록불
가장 크게 배운 건 PallMark에서다. PallMark의 게이트는 컴파일 → 시뮬 → 씬 생성 → 에디터 시험 → 플레이 시험 → 화면 캡처 순서로 돈다. 저장소 문서에는 “앞이 빨간불이면 뒤는 볼 값어치가 없다”고 적어 두었다.
9월 21일에 그 약속이 깨져 있었다는 걸 알았다. 여러 작업을 병합할 때마다 “시험 N/N 통과”라는 보고를 받았는데, 그건 --filter로 고른 일부만 돌린 결과였다. 필터를 떼니 5,262건 중 23건이 실패하고 있었다. 날짜를 거슬러 이분 탐색해 보니 실패는 9월 19일 밤 8건에서 21일 밤 22건까지 며칠에 걸쳐 쌓였다.
그 뒤로 규칙을 바꿨다.
- “게이트 초록”은 필터 없는 전체 시험으로만 주장한다.
- 이미 알고 있는 실패는 목록 파일로 관리한다. 목록 밖의 실패도 빨간불, 목록에 있는데 통과해도 빨간불이다. 톱니처럼 한 방향으로만 갈 수 있게 해서, 필터로 만든 초록이 통과하지 못하게 했다.
- 시험이 읽는 자료는 반드시 커밋한다. 보고서 폴더에 있던 기준값 파일이 커밋에서 빠져 다른 기계에서만 깨진 일이 있었다.
Salmonholic 캐릭터 떨림을 고친 뒤 온라인 경기에서 원 운동을 녹화한 점검 화면. 숫자 대신 화면으로 확인했다
결국 눈으로 본다
자동 검사를 아무리 쌓아도 마지막은 화면이다. PallMark 문서의 검증 원칙은 이렇다. 새 검사는 되돌리면 빨간불이 떠야 하고, 화면은 캡처나 영상으로 눈으로 보고, “고쳤다”는 실제 실행 결과로만 말한다. PallMark에서 “계단이 연결됐다”는 보고를 받고도 실제 빌드에서는 2층에 못 올라간 적이 있다. 도달과 상승은 다른 일이었다.
커밋 전에 거는 검사는 PallMark 커밋 훅 글에, 검증에 쓰는 도구 목록은 공용 도구 글에 정리했다. 이렇게 검증한 게임은 AvoidNow, 랜선포차, PallMark 페이지에서 볼 수 있다.


