테스트 실패 분석: 버그인가, 스크립트 문제인가 판단하는 법
- 10 Dec, 2025
테스트 실패 분석: 버그인가, 스크립트 문제인가 판단하는 법
10시 출근, 빨간 불
출근했다. 슬랙에 알림 12개. Jenkins에서 온 거다.
“Build #247 Failed - 18 test cases”
커피 먼저 탔다. 보고 나면 점심까지 못 마신다. 경험으로 안다.
모니터 3개 켰다. 왼쪽에 Jenkins, 가운데 로그, 오른쪽에 코드. 이게 내 전투 준비다.
18개 실패. 많은 편이다. 어제 배포 있었나 확인했다. Dev팀이 프론트엔드 UI 수정했다. 아.
첫 느낌으로 70%는 스크립트 문제다. 나머지 30%가 진짜 버그일 확률.

로그부터 읽는다
로그 읽기가 제일 중요하다. 근데 로그 해석은 경력이다.
첫 번째 실패 케이스 열었다.
ElementNotInteractableException:
Element <button id="submit-btn"> is not clickable at point (450, 320).
Other element would receive the click: <div class="modal-overlay">
이건 명백하다. 모달이 버튼을 가린 거다. 개발자가 모달 로직 바꿨나 보다.
두 번째 케이스.
TimeoutException:
Message: Expected condition failed:
waiting for visibility_of_element_located((By.ID, "user-profile"))
타임아웃. 이것도 익숙하다. 두 가지 가능성.
- 페이지 로딩이 느려졌다 (서버 문제)
- Element ID가 바뀌었다 (UI 변경)
세 번째부터는 패턴이 보인다. 전부 같은 에러.
NoSuchElementException:
Unable to locate element: {"method":"css selector","selector":".btn-primary"}
클래스명이 바뀐 거다. .btn-primary를 .primary-button로 바꿨나.
개발자한테 슬랙 날렸다.
“어제 버튼 클래스명 바꿨어?” “아 맞다. 디자인 시스템 통일한다고” ”…”
이래서 QA가 스트레스받는다. 알려주지도 않는다.

스크린샷 체크
로그만으로 부족할 때 스크린샷 본다.
Selenium은 실패 시 자동 캡처하게 설정해뒀다.
/screenshots/test_login_flow_20240115_0342.png 열었다.
화면에 로딩 스피너가 있다. 아직 페이지가 다 안 떴는데 테스트가 실행된 거다.
이건 스크립트 문제다. Wait 조건이 부족해.
현재 코드 확인했다.
driver.find_element(By.ID, "username").send_keys("test@test.com")
driver.find_element(By.ID, "password").send_keys("password123")
driver.find_element(By.ID, "login-btn").click()
바로 찾아서 클릭한다. Wait 없다.
고쳐야 한다.
wait = WebDriverWait(driver, 10)
username_field = wait.until(
EC.element_to_be_clickable((By.ID, "username"))
)
username_field.send_keys("test@test.com")
이렇게 바꿔야 안정적이다.
다른 스크린샷도 봤다. 결제 페이지 테스트 실패 건.
화면에 에러 메시지가 떠 있다. “Invalid payment method”
이건 진짜 버그다. 로그가 아니라 화면으로 확인됐다.
JIRA 티켓 생성했다.
“[BUG] Payment fails with valid test credit card” 재현 스텝 써서 Dev팀에 할당.
스크린샷 3장 첨부했다. 개발자가 바로 이해하게.
재현 테스트의 기술
의심스러운 케이스는 직접 돌려본다.
자동화 테스트 결과를 100% 믿으면 안 된다. Flaky test가 있다.
터미널 열고 단일 테스트 실행했다.
pytest tests/test_checkout.py::test_guest_checkout -v
1차: PASSED
2차: PASSED
3차: FAILED
3번 중 1번 실패. 전형적인 Flaky test다.
로그 다시 봤다. 네트워크 타임아웃이 원인이다.
API 응답이 가끔 느리다. 서버 문제일 수도 있다.
재현율 체크를 위해 10번 돌렸다.
for i in {1..10}; do pytest tests/test_checkout.py::test_guest_checkout; done
10번 중 3번 실패. 30% 재현율.
이 정도면 스크립트 문제가 아니다. 서버나 네트워크 이슈다.
백엔드 개발자한테 알렸다.
“Checkout API 응답 시간 체크해줄 수 있어? 간헐적으로 타임아웃 나.”
답장 왔다. “어제 DB 인덱스 작업했는데 그것 때문일 수도”
역시. 버그 맞다.

판단 기준표
4년 하면서 만든 내 기준이다.
스크립트 문제일 확률 높음:
- NoSuchElementException (90%)
- ElementNotInteractableException (85%)
- 같은 에러가 여러 테스트에서 발생 (95%)
- 최근 UI 배포 후 발생 (90%)
- 재현율 100% (80%)
버그일 확률 높음:
- AssertionError (70%)
- 화면에 에러 메시지 표시 (95%)
- 예전엔 통과했던 테스트 (60%)
- 재현율 낮음, 간헐적 (40%)
- 특정 환경에서만 발생 (75%)
애매한 경우:
- TimeoutException (50/50)
- StaleElementReferenceException (60% 스크립트)
- Network error (70% 버그)
- Screenshot이 공백 (디버깅 필요)
물론 절대적이지 않다. 맥락을 봐야 한다.
어제 배포 있었나, 환경 설정 바뀌었나, 외부 API 문제인가.
실전 프로세스
내가 실제로 하는 순서다.
1. 슬랙 알림 확인 (30초)
- Jenkins 빌드 번호 체크
- 몇 개 실패했나 파악
- 급한 건지 판단
2. Jenkins 대시보드 훑기 (2분)
- 실패 케이스 이름 쭉 본다
- 패턴 찾는다 (같은 모듈? 같은 에러?)
- 어느 브랜치인지 확인
3. 첫 번째 실패 로그 정독 (5분)
- 에러 타입 확인
- 스택 트레이스 읽기
- 실패한 코드 라인 찾기
4. 스크린샷 체크 (3분)
- 화면 상태 확인
- 의도한 화면인지 판단
- UI 변경 여부 파악
5. 코드 리뷰 (5분)
- 해당 테스트 스크립트 열기
- Wait 조건 있나 확인
- Selector가 정확한가 체크
6. 재현 테스트 (10분)
- 로컬에서 직접 실행
- 3회 이상 돌려보기
- 재현율 계산
7. 판단 및 액션 (5분)
- 스크립트 문제면 바로 수정
- 버그면 JIRA 생성
- 애매하면 개발자와 논의
총 30분 정도 걸린다. 18개 실패면 오전 내내 이거다.
자주 속는 케이스들
경험으로 배운 함정들이다.
1. 타임아웃인 줄 알았는데 버그
로딩이 느린 게 아니라, API가 아예 안 돌아오는 거였다. 백엔드 500 에러.
Wait을 늘려봤자 소용없다. 에러 로그 끝까지 읽어야 한다.
2. Flaky test인 줄 알았는데 스크립트 문제
가끔 실패하니까 Flaky라고 생각했다. 근데 아니었다.
페이지에 애니메이션이 있었다. 클릭 타이밍을 못 잡은 거다.
time.sleep(1) 넣으니까 통과. 근데 이건 나쁜 코드다.
EC.element_to_be_clickable로 바꿔야 한다.
3. 로컬에선 되는데 CI에서 실패
환경 차이다. CI 서버가 느리거나, 해상도가 다르거나, 브라우저 버전이 다르거나.
Headless 모드 문제일 수도 있다.
Docker 컨테이너에서 직접 돌려봐야 안다.
4. 에러 메시지를 믿었다가 낭패
“Element not found” 에러인데, 사실 iframe 안에 있었다.
에러 메시지만 보고 셀렉터 바꿨다가 시간 낭비.
HTML 구조 직접 확인해야 한다.
개발자와 소통법
이게 제일 중요하다. 판단 끝나면 전달이다.
스크립트 문제일 때:
슬랙에 조용히 쓴다.
“어제 UI 변경 건 때문에 테스트 18개 깨짐. 오늘 중으로 고칠게.”
개발자 멘션 안 한다. 내가 처리할 거니까.
버그일 때:
JIRA 티켓 먼저 만든다. 슬랙에 링크 공유.
“[BUG-1234] 결제 실패 이슈 확인됨. 우선순위 체크 부탁드려.”
재현 스텝을 명확히 쓴다.
- 게스트로 장바구니 담기
- 체크아웃 페이지 이동
- 테스트 카드 입력 (4242 4242 4242 4242)
- 결제 버튼 클릭
- 결과: “Invalid payment method” 에러
스크린샷 3장 첨부. 로그도 같이.
개발자가 “재현 안 되는데요?” 하면 환경 정보 준다.
- Browser: Chrome 120.0.6099
- OS: Ubuntu 20.04 (CI server)
- Test account: test+guest@company.com
- API endpoint: staging.api.company.com
애매할 때:
개발자 불러서 같이 본다.
“이거 좀 봐줄 수 있어? 버그인지 스크립트 문제인지 모르겠어.”
화면 공유하면서 재현한다. 같이 디버깅.
이게 제일 빠르다. 혼자 고민하지 말기.
오늘의 결과
18개 실패 분석 끝났다. 결과는 이렇다.
- 스크립트 문제: 14개 (UI 변경으로 셀렉터 깨짐)
- 진짜 버그: 3개 (결제 API, 장바구니 버그 2건)
- Flaky test: 1개 (네트워크 타임아웃, 무시)
14개는 내가 고친다. 클래스명 업데이트하면 된다.
# Before
driver.find_element(By.CLASS_NAME, "btn-primary")
# After
driver.find_element(By.CLASS_NAME, "primary-button")
30분이면 끝난다. 정규표현식으로 일괄 치환.
버그 3건은 JIRA 티켓 만들었다. Critical 2개, Medium 1개.
개발팀 스탠드업에서 공유 예정.
Flaky test는 일단 Ignore 처리. 나중에 네트워크 Retry 로직 추가할 거다.
점심 먹고 스크립트 수정 시작한다.
오후에는 신규 기능 테스트 작성해야 한다. 결제 모듈 v2가 나온다.
끝나지 않는다. QA는 계속된다.
분석하는 30분이 하루를 결정한다. 빨간 불을 초록으로 바꾸는 게 내 일이다.
