
안녕하세요. 오픈소프트랩 개발팀입니다.
단위 테스트 400건이 전부 통과하는데 서비스는 깨져 있었다는 글을 쓴 적이 있습니다. 그 뒤로 화면을 실제로 열어보는 테스트를 늘렸습니다.
늘리고 나서 다른 문제가 생겼습니다. 가끔 실패합니다.
다시 돌리면 통과했습니다
증상은 이랬습니다.
전체 테스트를 돌리면 한 건이 실패합니다. 그 한 건만 따로 돌리면 통과합니다. 다시 전체를 돌리면 이번엔 통과하고, 그다음엔 또 실패합니다.
이런 테스트를 흔히 플레이키(flaky) 하다고 부릅니다. 결과가 일정하지 않은 테스트입니다.
처음 대응은 다들 하는 대로였습니다. 다시 돌렸습니다. 두 번째에 통과하면 넘어갔습니다.
재시도를 켜려다 멈췄습니다
몇 번 반복되니 손으로 다시 돌리기가 번거로워졌습니다. 테스트 도구에는 실패하면 자동으로 다시 시도하는 설정이 있습니다. 그걸 켜면 이 문제는 화면에서 사라집니다.
켜기 직전에 한 가지가 걸렸습니다.
재시도로 통과한 것과 처음부터 통과한 것을 구분할 수 있는가. 로그를 보면 구분되긴 합니다. 그런데 매일 보는 사람은 없습니다. 초록색으로 표시되면 넘어갑니다.
그러면 이렇게 됩니다. 이 테스트는 앞으로도 절반쯤 실패하는데, 아무도 모릅니다. 그리고 나중에 진짜 결함으로 실패해도 재시도가 한 번 더 돌려줍니다. 두 번 다 실패해야 알게 됩니다.
400건 글에서 정리한 것과 같은 모양이었습니다. 그때는 확인 대상으로 정하지 않은 영역이 비어 있었고, 이번엔 확인은 하는데 결과를 안 믿어도 되는 상태를 만들려던 참이었습니다.
그래서 켜지 않고 원인을 찾아보기로 했습니다.
시간을 더해봤습니다
먼저 언제 실패하는지 세어봤습니다. 네 번 돌려서 두 번 실패했습니다. 절반입니다. 우연이라고 보기엔 잦습니다.
그다음 조건을 갈랐습니다.
| 어떻게 돌렸나 | 결과 |
|---|---|
| 그 테스트만 단독으로 | 통과 |
| 전체를 하나씩 순서대로 | 통과 |
| 전체를 동시에 여러 개씩 | 간헐 실패 |
동시에 돌릴 때만 실패합니다. 동시에 돌리면 서버가 여러 요청을 한꺼번에 받으니 응답이 느려집니다. 여기까지는 예상했는데, 그래서 왜 실패하는지가 안 보였습니다.
그래서 이 테스트가 기다리는 시간을 전부 적어봤습니다.
화면 열기 최대 30초
등록 버튼 기다리기 최대 15초
모달 뜨기 기다리기 최대 15초
목록 갱신 기다리기 최대 10초
─────────────────────────
합계 최대 70초
테스트 전체 제한 시간 30초단계별 최대 대기 시간(타임아웃)을 다 더하면 70초인데, 테스트 전체 제한 시간은 30초였습니다.
혼자 돌릴 때는 각 단계가 1~2초에 끝나니 30초 안에 들어옵니다. 동시에 돌리면 첫 단계에서만 20초 넘게 쓰고, 그 뒤 단계들은 시작도 못 한 채 전체 시간이 끝납니다.
테스트가 잘못된 게 아니었습니다. 시간 배분이 애초에 맞지 않았습니다. 혼자 돌릴 때 통과한 게 운이 좋았던 쪽입니다.
제한 시간을 실제 소요에 맞췄습니다
고친 건 하나입니다. 이 테스트의 제한 시간을 실제로 걸리는 만큼으로 늘렸습니다.
그리고 세 번 연속으로 전체를 돌려 확인했습니다. 세 번 다 통과했습니다.
간단한 수정입니다. 다만 재시도를 켰다면 여기까지 오지 않았습니다. 증상이 사라졌을 테니까요. 그리고 같은 종류의 문제가 다른 테스트에도 있는지 볼 이유도 없었을 겁니다.
얻은 것과 포기한 것
얻은 것 — 테스트 결과를 그대로 믿을 수 있게 됐습니다. 빨간색이면 진짜 문제입니다. 이게 되어야 테스트를 늘리는 게 의미가 있습니다. 믿을 수 없는 테스트는 많을수록 방해가 됩니다.
그리고 숫자로 확인하는 습관이 하나 생겼습니다. "가끔 실패한다"가 아니라 "네 번 중 두 번 실패한다"로 적으면 우연인지 아닌지가 바로 보입니다.
포기한 것 — 시간이 들었습니다. 재시도 설정 한 줄이면 끝날 일을 며칠에 걸쳐 봤습니다. 급한 배포 앞이었다면 같은 선택을 했을지 모르겠습니다.
그리고 테스트 전체가 느려졌습니다. 제한 시간을 늘렸으니 정말 문제가 생겼을 때 그만큼 더 기다렸다가 실패합니다.
제한 시간을 늘리는 게 답이 아닐 때
지금 붙어 있는 문제입니다.
이번엔 제한 시간을 늘리는 게 맞았습니다. 애초에 배분이 틀려 있었으니까요. 그런데 이 방법을 계속 쓰면 위험합니다. 제한 시간을 늘려서 통과시키는 일이 반복되면, 앱이 실제로 느려진 것을 테스트가 못 잡습니다.
느려짐도 결함입니다. 화면이 열리는 데 20초 걸리면 사용자는 고장으로 받아들입니다.
그래서 두 가지를 나누기로 했습니다. 테스트가 통과하는 제한 시간와 사용자가 참을 수 있는 시간은 다른 숫자입니다. 지금은 앞쪽만 있습니다.
뒤쪽을 따로 재는 쪽을 만들고 있습니다. 테스트를 통과시키는 기준과 별개로 각 단계가 실제로 몇 초 걸렸는지를 기록해 두고, 그 값이 이전보다 눈에 띄게 늘면 알리는 방식입니다. 통과 여부와 분리하면 제한 시간을 넉넉히 두면서도 느려짐을 볼 수 있습니다.
먼저 자주 쓰는 화면 몇 개부터 재고 있습니다. 어느 정도 쌓여야 "눈에 띄게 늘었다"의 기준을 잡을 수 있어서, 당분간은 값만 모으는 단계입니다.
오픈소프트랩 개발팀이 작성합니다. 보안 운영 포탈과 생성형 AI 사용 통제를 만들고 있습니다.
