개발 팁
프로젝트와 상관없이 다시 쓸 수 있는 요령을 문제·원인·해법·코드 예시로 짧게 적습니다.
- 시험 더블과 운영 백엔드가 다르면, 실제 백엔드로 도는 시험을 하나는 둔다 →인메모리 레이어·SQLite·가짜 큐와 실제 구현의 차이에서만 나는 버그는 단위 시험이 못 잡는다. 핵심 경로 하나는 운영과 같은 백엔드로 돌린다.
- 시험 환경에서는 일부러 느리게 만든 것을 끈다 →비밀번호 해셔는 MD5, Postgres는 tmpfs와 fsync=off, Redis는 저장 끔, 배경 작업 주기는 짧게, YAML은 C 로더. 운영 설정에는 두지 않는다.
- E2E는 폴링·고정 대기 대신 이벤트로만 기다린다 →expect.poll·waitForTimeout·toPass 대신 MutationObserver와 스트림 메시지 리스너로 화면이 바뀔 때마다 한 번씩만 다시 본다. 전체 E2E 6분(실패 10개)이 CI 45초(110개 통과)가 됐다.
- 시험 DB는 마이그레이션해 둔 템플릿에서 복제한다 →워커마다 migrate를 돌리지 않는다. 마이그레이션 해시로 이름 지은 템플릿 DB를 한 번 만들고 CREATE DATABASE … TEMPLATE으로 복제하면 7~9초가 1초 미만이 된다.
- 처음 쓸 때 적재되는 것은 세션 픽스처에서 미리 읽는다 →URLconf나 정의 레지스트리처럼 첫 사용 때 적재되는 비용을 「처음 쓴 시험」 하나가 혼자 지면, 빌드마다 다른 시험이 떨어진다. autouse 세션 픽스처로 앞당긴다.
- 지연에 민감한 프로세스는 CPU 몫 제한 대신 코어를 못박는다 →--cpus 몫 제한은 할당량이 차면 프로세스를 0.1초씩 통째로 멈춘다. 틱 루프 같은 프로세스는 --cpuset-cpus로 코어를 고정하고 taskset으로 자리를 나눈다.
- 시험 하나마다 시간 예산을 두고, 러너가 강제한다 →순수 로직 0.5초, 백엔드 1초, E2E 3초. 넘으면 통과한 시험도 실패로 바꾸고, 예산을 늘리는 대신 로직과 준비를 고친다.
- 시간에 기대는 화면은 시험이 시간을 쥔다 →마감·만료·자동 갱신을 실제로 기다리지 않는다. 브라우저는 page.clock, 서버의 「지금」은 주입한 시계, 배경 주기 작업은 「한 번 돌기」로 부른다.
- E2E 준비는 API로 하고, 화면은 흐름마다 한 번만 지난다 →가입·만들기처럼 앞 단계에 필요한 사정은 화면을 열기 전에 API로 깔고 쿠키를 브라우저 맥락에 옮긴다.
- 백엔드 시험 시간은 벽시계가 아니라 CPU 시간으로 잰다 →CI가 붐비면 1초 근처 시험이 빌드마다 번갈아 떨어진다. 프로세스가 쓴 CPU 시간에 자식 프로세스 몫을 더해 재면 부하에 흔들리지 않는다.