ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 단위 테스트 초록인데 왜 push하면 안 되냐면요
    AI Agent 2026. 6. 22. 08:56
    728x90
    반응형

    그날 저녁, 저는 이미 push 버튼을 누른 뒤였습니다.

    새로 짠 단위 테스트는 초록이었고, 정적 분석기도 경고 한 줄 없이 깨끗했거든요. "생성 화면에 필수 입력값 하나를 더 붙여라"는 작은 변경이었습니다. 값이 없으면 생성 버튼이 안 눌리게 막는, 딱 그것만요. 그래서 올렸습니다.

    이 글은 그 push가 왜 틀렸는지, 그리고 동작을 바꾸는 변경 앞에서 뭘 먼저 돌려야 하는지에 대한 기록입니다. 단위 PASS는 통합 PASS가 아니더라고요.

    백그라운드에서 빨간 줄이 올라왔습니다

    push하고 다른 일을 보고 있는데, 한쪽 터미널에서 아까 무심코 켜둔 통합 테스트가 그제서야 결과를 뱉었습니다. 기존 e2e 7개가 전부 빨갰습니다.

    손이 잠깐 멈췄습니다.

    원인은 허무할 만큼 단순했습니다. 그 기존 테스트들은 예전 규칙대로, 새 필수 값을 채우지 않은 채로 생성 버튼을 누르도록 짜여 있었거든요. 제가 방금 "이 값 없으면 버튼 막아라"를 추가했으니, 그 7개는 전부 버튼이 안 눌려서 죽은 겁니다. 코드는 멀쩡합니다. 새 규칙도 맞습니다. 기존 흐름이 새 전제를 만족 못 할 뿐이었습니다.

    무서운 건 이겁니다. 그 백그라운드 실행을 우연히 안 켜뒀으면, 저는 끝까지 몰랐을 겁니다. 이미 올라가 있는 채로요.

    종료코드가 저한테 거짓말을 하고 있었습니다

    여기서 한 겹이 더 있었습니다.

    저는 테스트를 돌릴 때 출력이 길어서, 끝부분만 보려고 ... | tail 식으로 파이프를 걸어두는 습관이 있었습니다. 그런데 파이프로 명령을 이으면, 셸이 돌려주는 종료코드는 맨 마지막 명령(tail)의 것입니다. tail은 거의 항상 0, 즉 "성공"을 돌려줍니다. 앞에서 테스트가 7개 깨져 0이 아닌 코드로 죽어도, 파이프 끝의 0이 그걸 덮어버립니다.

    그러니까 echo $?는 계속 0을 보여줬습니다. "다 괜찮다"고요. 실제 출력 안에는 실패 라인이 멀쩡히 찍혀 있었는데, 저는 요약된 끝줄과 0이라는 숫자만 믿고 있었던 겁니다.

    쇼핑몰에서 환불 신청하고 "정상 접수되었습니다" 화면만 보고 닫은 거랑 비슷합니다. 정작 환불 내역에는 아무것도 안 잡혀 있는데, 접수 화면은 끝까지 초록불이죠.

    그래서 순서를 이렇게 바꿨습니다

    망가진 테스트는 새 규칙에 맞게 값을 채우도록 고쳐서 7개 다시 초록으로 돌려놨습니다. 그건 30분이면 끝나는 일이었습니다. 진짜 문제는 제 순서였습니다.

    동작을 바꾸는 변경 — 게이트·검증·새 필수 필드·상태 전이·화면 이동처럼 "되던 게 안 되게" 만드는 종류 — 앞에서는 이렇게 합니다.

    • 새 단위 테스트랑 분석기 통과는 출발선이지 결승선이 아닙니다. 그것만으로는 push하지 않습니다.
    • push 전에, 그 영역에 원래 있던 통합/e2e 테스트를 직접 돌립니다. 내가 새로 짠 거 말고, 남들이(또는 과거의 내가) 옛 전제로 짜둔 그 기존 묶음이요. 깨지는 건 거기서 깨집니다.
    • 결과는 종료코드 말고 출력의 실제 pass/fail 라인을 눈으로 봅니다. | tail이나 | grep을 걸 거면 종료코드를 그대로 믿지 말고, 통과/실패 문구를 직접 찾습니다.

    마지막 줄이 제일 비쌌습니다.

    단위 테스트가 무죄를 증명하지 못하는 이유

    단위 테스트는 "이 함수 하나가 시키는 대로 한다"를 봅니다. 정적 분석기는 "문법과 타입이 맞다"를 봅니다. 둘 다 이번 변경에 대해선 정직하게 통과를 줬습니다 — 그 범위 안에선 정말 아무 문제가 없었으니까요.

    근데 제가 건드린 건 함수 하나가 아니라 흐름이었습니다. 입력 화면 전체가 따르던 전제를 하나 바꾼 거죠. 그건 함수 단위로는 안 보이고, 흐름을 처음부터 끝까지 밟아보는 통합/e2e에서만 보입니다.

    깨끗한 단위 테스트와 빈 통합 커버리지를 합치면, 제가 본 그 초록불이 나옵니다. 가장 안심되는 색이, 가장 안 본 구간을 가리고 있었습니다.

    지금 남은 것

    push 전에 기존 e2e부터 돌리는 건 이제 습관으로 굳히는 중입니다. 종료코드 0을 보면 반사적으로 "이거 파이프 뒤에 가려진 거 아냐?"부터 의심하고요.

    아직 안 푼 게 하나 있습니다. 그 백그라운드 실행은 제가 의도해서 켠 게 아니라 그냥 어쩌다 돌고 있던 거였습니다. 운이 좋아서 잡힌 거지, 시스템이 잡아준 게 아니라는 뜻입니다. 다음엔 "동작 바꾸는 변경이면 그 영역 기존 e2e를 push 전에 강제로 돌린다"를 손이 아니라 파이프라인이 막게 만들어 둘 생각입니다. 오늘은 일단 echo $? 0이 떠도, 위로 스크롤해서 실패 라인부터 찾아 읽고 있습니다.

    728x90
    반응형
Designed by Tistory.