Showing Posts From

자동화

자동화 커버리지 80% vs 100%: 그 사이 어디가 현실일까

자동화 커버리지 80% vs 100%: 그 사이 어디가 현실일까

자동화 커버리지 80% vs 100%: 그 사이 어디가 현실일까 경영진의 질문 "자동화 커버리지 몇 퍼센트예요?" CTO가 물었다. 월요일 아침 10시, 스탠드업 미팅. "현재 73%입니다." "100% 언제쯤 가능할까요?" 순간 멈칫했다. 이 질문, 매번 나온다. "현실적으로 어렵습니다." "왜요? 다른 회사는 90% 넘는다는데." 설명해야 한다. 또.자동화 커버리지. 숫자 하나로 모든 걸 판단한다. 80%면 좋은 거다. 90%면 훌륭하다. 100%면 완벽하다. 정말 그럴까. 4년 동안 자동화 했다. 처음엔 나도 100%를 꿈꿨다. 지금은 안다. 불가능하다는 걸. 80%의 벽 우리 서비스, 테스트 케이스 2,400개. 자동화된 케이스 1,752개. 정확히 73%. 남은 648개. 왜 자동화 안 했을까. 이유는 명확하다. 첫째, UI 테스트의 함정. 로그인 페이지 자동화. 쉽다. driver.find_element(By.ID, "username").send_keys("test") driver.find_element(By.ID, "password").send_keys("1234") driver.find_element(By.ID, "login-btn").click()3줄이면 끝. 그런데 메인 페이지는 다르다. 애니메이션 들어간 대시보드. 차트가 동적으로 그려진다. 무한 스크롤. 레이지 로딩. 실시간 업데이트. 어떻게 자동화하나. # 차트 로딩 대기 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS, "chart-loaded")) )# 아니다, 10초론 부족하다 # 15초? 20초? # 네트워크 느리면 30초도 모자라다대기 시간을 늘리면 테스트가 느려진다. 줄이면 Flaky Test가 된다. 실패했다가 다시 돌리면 성공한다. 이게 버그인가 타이밍 문제인가.둘째, 써드파티 API. 결제 시스템. PG사 API 쓴다. 테스트 서버 있다. 좋다. 그런데 불안정하다. def test_payment(): response = requests.post( "https://testpay.pg.com/api/v1/payment", json={"amount": 10000} ) assert response.status_code == 200오전엔 성공한다. 오후엔 타임아웃. 저녁엔 502 Bad Gateway. 우리 코드 문제가 아니다. PG사 테스트 서버가 그렇다. 이걸 자동화에 넣으면 CI가 계속 깨진다. 개발자들이 묻는다. "이거 우리 버그예요?" "아니요, PG사 서버 문제예요." "그럼 테스트를 왜 돌려요?" 할 말이 없다. 결국 Mocking한다. @mock.patch('requests.post') def test_payment(mock_post): mock_post.return_value.status_code = 200 # 테스트 진행이게 진짜 테스트일까. 실제 PG사 API는 안 건드린다. 우리가 만든 가짜 응답만 테스트한다. 커버리지는 올라간다. 100개 케이스 추가. 실제 품질은? 모른다. 73%의 의미 우리 자동화 커버리지 73%. 이게 낮은 걸까. 계산해봤다. E2E 테스트: 120개 (자동화 48개, 40%) 풀 사용자 플로우. 회원가입부터 결제까지. 시나리오가 길다. 15분짜리도 있다. 중간에 하나만 깨져도 전체가 실패. 네트워크, 써드파티, 브라우저 버전, OS 차이. 변수가 너무 많다. 40% 자동화도 선방한 거다. 통합 테스트: 680개 (자동화 612개, 90%) API 테스트. 이건 쉽다. def test_user_api(): response = client.get("/api/users/1") assert response.status_code == 200 assert response.json()["name"] == "테스트"서버만 있으면 된다. UI 없다. 브라우저 없다. 빠르다. 안정적이다. 90% 자동화. 만족스럽다. 단위 테스트: 1,600개 (자동화 1,092개, 68%) 함수 단위 테스트. 개발자가 짜야 하는데 안 짠다. "QA가 테스트하잖아요." 이런 케이스는 우리가 자동화해도 의미 없다. 코드 레벨 테스트는 개발자 몫이다.전체 73%. E2E 40%, 통합 90%, 단위 68%. 피라미드 구조다. 정상이다. 그런데 경영진은 하나의 숫자만 본다. "73%요. 낮네요." 100%의 환상 전 직장 동료 H. 대기업 QA였다. 자동화 커버리지 95% 달성했다고 자랑했다. "어떻게 했어?" "UI 테스트 다 넣었지." "Flaky Test는?" "많아. 그냥 3번 돌려서 1번 성공하면 pass 처리." 이게 95%의 실체다. 불안정한 테스트를 숫자에 포함시킨다. 의미 없는 테스트도 넣는다. def test_homepage_loads(): driver.get("https://example.com") assert "Example" in driver.title이런 테스트. 10초 걸린다. 확인하는 건 타이틀뿐. 이게 1개 케이스로 카운트된다. 커버리지는 올라간다. 실효성은 낮다. 또 다른 회사 K. 자동화 커버리지 100% 달성. 비결이 뭘까. 테스트 케이스를 줄였다. 2,000개 → 800개. 자동화 어려운 케이스는 아예 삭제. "이건 매뉴얼로 하면 돼요." 남은 800개만 자동화. 800/800, 100%. 숫자는 예쁘다. 실제 커버리지는? 40%. 현실적인 목표 그래서 내 결론. 80%가 현실이다. 100%는 환상이다. 자동화 가능한 것: 80% 불가능한 것: 20% 20%는 이렇다.복잡한 UI 인터랙션드래그 앤 드롭 멀티터치 제스처 캔버스 기반 에디터 실시간 화상 채팅불안정한 외부 의존성써드파티 API 테스트 서버 결제 시스템 샌드박스 SNS 로그인 연동 이메일/SMS 발송 확인시각적 검증디자인 QA 애니메이션 자연스러움 반응형 레이아웃 미세 조정 다국어 텍스트 overflow탐색적 테스트예상 못 한 버그 찾기 사용자 관점 UX 검증 경계값 실험 직관적 이상함 감지이 20%는 사람이 한다. 비효율적이지 않다. 필수다. 80%를 지키는 법 그럼 80%는 어떻게 달성할까. 내 원칙 5가지. 1. 테스트 피라미드 따르기 E2E: 최소한만 (10%) 통합: 핵심 기능 (40%) 단위: 최대한 많이 (50%) E2E 많이 만들면 커버리지 빨리 오른다. 하지만 느리고 불안정하다. 단위 테스트가 기반이어야 한다. 2. Flaky Test 절대 용납 안 함 테스트가 불안정하면 즉시 수정하거나 삭제. "가끔 실패해요"는 없다. 실패하는 테스트는 신뢰를 깎는다. CI가 빨간색이면 모두가 무시한다. 3. Mocking의 한계 인정 Mocking은 도구다. 만능이 아니다. 외부 API는 Mock한다. 하지만 통합 테스트는 따로 둔다. 주 1회, 실제 테스트 서버 대상으로 돌린다. 느려도 괜찮다. 정확도가 중요하다. 4. ROI 계산하기 이 테스트 자동화하는 시간: 3시간 매뉴얼로 하는 시간: 5분 실행 빈도: 월 1회 3시간 투자해서 월 5분 절약. 의미 없다. 자주 실행하는 것만 자동화한다. CI에 들어갈 테스트, 회귀 테스트, 스모크 테스트. 5. 유지보수 고려 자동화 코드도 코드다. 관리해야 한다. UI 바뀌면 스크립트도 바뀐다. Page Object Pattern 쓴다. class LoginPage: def __init__(self, driver): self.driver = driver def enter_username(self, username): self.driver.find_element(By.ID, "username").send_keys(username) def enter_password(self, password): self.driver.find_element(By.ID, "password").send_keys(password)UI 변경되면 이 클래스만 수정. 테스트 코드 100개 건드릴 필요 없다. 경영진 설득하기 다시 CTO에게 설명했다. "100% 불가능한 이유 3가지 말씀드리겠습니다." 회의실 화이트보드. 피라미드 그렸다. "첫째, 테스트 피라미드 구조상 E2E는 소수여야 합니다. 우리는 40% 자동화했고, 이는 업계 평균 이상입니다." "둘째, 써드파티 의존성. 결제, 인증, 알림 시스템. 이들의 테스트 환경은 불안정합니다. Mock으로 대체 가능하지만, 실제 커버리지는 낮아집니다." "셋째, 시각적 요소와 탐색적 테스트. 이는 자동화로 대체 불가능합니다. 사람의 눈과 직관이 필요합니다." CTO가 고개를 끄덕였다. "그럼 현재 73%는?" "안정적으로 유지 가능한 최대치입니다. 80%까지는 올릴 수 있지만, 3개월 소요됩니다. 우선순위 조정 필요합니다." "신규 기능 개발이 우선인가요, 자동화 커버리지 증가가 우선인가요?" 침묵. "신규 기능이 우선입니다." "그렇다면 73% 유지하면서, 신규 기능에 대한 자동화는 즉시 추가하겠습니다. 분기마다 5%씩 증가 목표로 하겠습니다." 현실적인 제안. 승인됐다. 숫자의 함정 자동화 커버리지는 숫자다. 숫자는 거짓말을 한다. 95%인데 Flaky Test 투성이인 팀. 70%인데 모든 테스트가 안정적인 팀. 어느 쪽이 나을까. 당연히 후자다. 커버리지 높이기는 쉽다. 의미 없는 테스트 추가하면 된다. 케이스 줄이면 된다. Mock 남발하면 된다. 하지만 품질은 안 올라간다. 진짜 중요한 건 이거다. "이 자동화가 버그를 잡아낼 수 있나?" 73%의 테스트가 버그 100개 찾는다. 95%의 테스트가 버그 50개 찾는다. 나는 73%를 선택한다. 3개월 후 현재 커버리지: 77%. 4% 올렸다. 추가한 테스트: 96개. 모두 통합 테스트. API 위주. 안정적이다. CI에서 한 번도 안 깨졌다. E2E는 2개만 추가. 핵심 시나리오만. 회원가입-구매-환불. UI 변경 적은 부분만 골랐다. CTO가 물었다. "80% 언제 되나요?" "다음 분기요." "100%는?" "현실적으로 어렵습니다. 대신 77% 테스트가 모두 의미 있습니다. 한 번도 False Positive 없었습니다." 고개를 끄덕인다. "좋습니다. 품질이 더 중요하죠." 드디어 이해했다. 자동화의 본질 자동화는 수단이다. 목적이 아니다. 목적은 품질이다. 100% 자동화해도 버그 못 잡으면 무용지물. 50% 자동화해도 치명적 버그 잡으면 성공. 숫자에 집착하지 않는다. 대신 이것만 지킨다.모든 자동화 테스트는 안정적이어야 한다. 실패는 항상 실제 버그여야 한다. 빠르게 실행되어야 한다. 유지보수가 쉬워야 한다. 비용 대비 효과가 있어야 한다.이 5가지를 지키는 게 80%다. 100%는 욕심이다.오늘도 CI 빌드 통과. 77% 자동화, 0% Flaky. 이게 진짜 성공이다.