자동화된 웹 프론트엔드 테스트 - 이유

자동화된 웹 프론트엔드 테스트 - 이유

Tags
Automated Test
Published
January 8, 2025
Author
Seongbin Kim
 
이 글은 웹 프론트엔드 환경에서 테스트 자동화를 할지 말지, 무엇을 테스트할 수 있는지, 어떻게 자동화할 수 있는지에 대해 설명합니다.
 
저는 테스트 자동화로 이득을 본 경험은 없지만, 자동화된 테스트가 있었으면 하는 간절함은 느껴보았기에, 테스트 자동화의 가치를 생각해보고 정리한 글입니다.
 
QA 엔지니어를 위한 글이 아닌, 웹 프론트엔드 개발자 입장에서의 개발자 테스트를 기준으로 합니다.
 

1. 테스트의 현실, 어려움, 가치

 

1-1. 수동 테스트 고찰해보기

 

개발자가 테스트를 하는가?

  • 당연히 합니다.
  • 개발자는 기능의 정상 동작을 보장해기 위해 충분히 노력해야 합니다.
  • 적어도 기본적인 테스트가 없어서 누락되는 일은 없게 합니다.
    • (ex)
      • 정상 케이스일 때의 여러 개의 (입력, 출력) Test Case
      • 엣지 케이스일 때의 Test Case (빈 배열 시 화면 출력 등)
      • 로그인 / 본인 여부
      • 단일 동작을 반복했을 때
      • 여러 가지 동작을 섞었을 때
      • (성능 문제가 있을 수 있는 경우) 데이터가 많을 때
      • (반응형인 경우) Mobile/PC 화면일 때 동일하게 진행
  • 만드는 기능의 오류 발생 비용에 따라 더 철저히 하게 됩니다.
 

현실적으로 무엇을 수동 테스트하고, 무엇을 빠트리는가?

  • 현실적으로 테스트하는 것
    • 추가된 코드 / 수정된 코드에 영향을 받는 기능의 기본적인 동작들
    • 인지하고 있는 코드 변경 내용에 기반
  • 현실적으로 빠트리는 것(어려운 것)
    • 처음 개발된 기능이 아니라면, 코드 영향 범위를 잘못 추정해 누락된 경우
      • 특히 기존 기능/코드 분량이 많을수록 그렇습니다.
    • 재현하기 어려운 입력 값(=재현 시간이 오래 걸리는 동작 경로)인 경우
      • 특히 API mock이 없고, 단독으로 테스트하기 어려운 경우 테스트하지 않게 됩니다.
        • (ex) 코인 거래소의 보유 자산 페이지의 자산 계산식
          • 코인의 종류가 많고, 보유 자산을 편집하는 일이 어렵기 때문에, API 데이터로 재현하려고 하는 일은 꽤 힘듭니다.
          • API 데이터로 재현하기보다는, 테스트할 수 있게 코드를 분리하는 것이 좋습니다.
    • 코드 수정 이후 이전에 했던 테스트를 또 해야하는 경우
      • 간단한 수정을 했을 때, 리팩토링을 했을 때 기존 TC를 모두 재실행한다면 비용이 너무 크다고 생각하게 됩니다.
      • 그래서 심리 상 수정된 코드의 영향 범위로 재실행할 TC를 최소화하게 됩니다.
      • 이 때 누락되는 경우가 많을 수 있다. 즉, 회귀가 발생할 확률이 높아집니다.
 

수동 테스트에 드는 시간

  • 테스트 소요 시간 = 전체 TC 개수 * 평균 TC 구상 시간 * 평균 TC 실행 시간 * 테스트 횟수
  • 테스트 횟수는 추가 배포, 기존 코드 수정 시 등 기존 TC가 있는 시점에 반복 테스트를 하는 것을 의미합니다.
 

걸리는 시간은 불명확

  • 세 가지 요인이 전부 불명확하기 때문입니다.
  • 전체 TC 개수 = (UI를 보고 즉흥적으로 떠올리므로 명확하지 않음)
  • TC 구상 시간 = (사전 구상 없이 UI를 따라가며 되는 대로 진행)
  • TC 실행 시간 = (필요한 데이터는 사용하던 계정의 데이터에서 이어서 재현)
    • 데이터가 단순한 경우: 일부 상태만 변경하는 작업을 UI로 하면 되므로, 거의 없음
    • 데이터가 복잡한 경우: 데이터를 UI로 만들어내는 시간이 필요해 오래 걸릴 수 있음
 

언제 오래 걸리는가?

  • 손으로 하는 게 오래 걸리는 경우입니다.
    • 폼의 필드가 3개 이상이고 모두 입력해야 하는 경우
    • 정상 Case의 데이터의 조합이 3개 이상인 경우
    • 로그인 등 인증 과정이 포함된 경우
    • 과정이 n단계의 Step으로 이루어진 경우
  • 예시
    • 프로필 수정 폼에서 여러 가지 이미지 업로드가 잘 되는지 확인 → 이미지 크기 별, 확장자 별, 불량 파일 등
    • 자산 목록에 특정 자산들의 목록을 구축 → 로그인, 2FA 인증, 일부 자산들 구매, 일부 자산들 판매
    • 즉시 구매/판매할 수 없는 경우라면..? 서브 계정에 로그인+인증한 후 매물을 사고/팔고…)
    • 자산 포트폴리오의 개수가 하나일 때, 여러 개일 때 → 포트폴리오 이동을 위해 각 자산을 모두 이동
    • (ex) 비밀번호 찾기 → 본인 인증 폼 입력, 휴대폰 인증코드 입력, 신규 비밀번호 입력
 

테스트는 몇 번 반복해야하는가?

  • 최초 개발 시, 최초 배포 후 코드 변경 시마다 해야 합니다.
  • 사실 한 번에 개발이 깔끔하게 되는 경우가 적기 때문에 동일 TC를 반복해서 실행해야 할 확률이 높습니다.
  • 그래서 조금 복잡한 기능을 개발할 때 계속해서 오류가 발생하는 경우가 있는데, 이 때는 주로 회귀가 발생하게 되며 이 쯤에서 테스트 코드를 짜놨다면 훨씬 나았을텐데라고 생각하게 됩니다.
 

테스트를 누락하면 무슨 일이 생기는가?

  • 누락하지 않았을 때보다 리뷰, 배포에 더 많은 시간을 쓰게 됩니다.
    • 실서버 hotfix를 하거나 QA 과정을 거쳐야 합니다.
    • 다시 PR 생성 / 코드 리뷰를 받아야 합니다.
      • 팀원들이 컨텍스트 스위칭을 하는 횟수가 늘어납니다.
      • PR을 만드는 시간, 리뷰를 요청드리는 시간, 리뷰를 대기하는 시간이 소요됩니다.
        • 특히 리뷰 과정은 비동기 소통으로 진행하기 때문에 대기 시간이 꽤 깁니다.
 

1-2. 자동화된 테스트와의 비교

 

자동화된 테스트란

  • 일부 소스 코드 혹은 실행되는 애플리케이션 자체에 대해 TC를 실행하는 프로그램
  • 즉, 사람이 실행할 TC를 대신 실행하는 프로그램, “테스트 코드”
  • TC 실행의 자동화
 

테스트 코드는 일일이 컴퓨터에게 명령을 내려야 한다.

  • 자동화된 테스트를 사람이 쓰면서 해야 할 일
    • TC를 사람이 떠올리고 작성해야 합니다. 🙏
    • TC의 실행 절차를 구체적으로 컴퓨터에게 지시해야 합니다. ☠️☠️☠️
      • “테스트 코드를 정확하게 작성했음”을 판정하는 일이 생긴 것입니다.
        • 수동 테스트에서는 없던 어려운 일입니다.
        • 사람이 테스트할 때보다 훨씬 구체적이기 때문입니다.
    • TC의 목록이 테스트 대상을 확실하게 검증하는지 사람이 보장해야 합니다.
 

테스트 코드 유지보수

  • 테스트 코드는 만들고 나서도 긴장을 놓을 수 없습니다.
  • 테스트 코드는 2가지 이유로 제품 코드가 변경되는 경우, 대응이 필요합니다.
    • 요구사항 자체가 변경되는 경우
      • TC 자체가 무효화되고, 신규 TC가 필요합니다.
    • 테스트 대상(코드)가 재설계되는 경우
      • 즉, 리팩토링을 진행한 대상의 구현 상세 부분을 테스트하고 있던 경우
      • TC 자체가 무효화되고, 신규 TC가 필요합니다.
  • 즉, 테스트 코드는 자동화 대상이지만, 수명이 짧을 수 있습니다. (길 수도 있다)
 

테스트 코드 작성은 쉽고 단순한가?

  • 테스트 코드가 제품 코드의 구현 상세를 테스트하는 경우, 굉장히 자주 테스트 코드가 깨질 수 있습니다.
  • 이 때문에 테스트 자동화와 관련해서 항상 설계 개념이 등장합니다.
    • (ex) 테스트하기 좋은 코드가 좋은 설계입니다.
  • 즉, 테스트 코드는 설계 능력과 관계가 크며, 설계 능력이 미약할수록 깔끔한 테스트 코드 작성은 어렵습니다.
  • 즉, 어렵고 복잡합니다.
  • 테스트 코드 작성 방법에 대한 학습과 숙련이 필요합니다.
 

테스트 자동화의 비용 요약

  • 테스트 코드 작성 작업 추가
  • 테스트 코드 유지보수 작업 추가
 

테스트 자동화의 이익 요약

  • 테스트 수동 반복의 제거
  • 테스트 누락의 제거
  • 회귀 테스트 방지
  • 테스트 대상의 스펙과 이를 검증하는 테스트 절차에 대한 아주 구체적인 문서
    • 깔끔한 테스트 코드만 문서화의 효과가 있을 것입니다.
 

테스트 자동화를 해야 할지, 말지의 기준을 생각해본다면

  • 수동으로 해야 할 때
    • 작업 대부분을 기존 코드와 독립적인 신규 제품 코드를 작성하며 앞으로도 그럴 때
    • 제품 스펙이 변경되기까지의 평균 시간이 한 스프린트 정도(2주)보다 짧을 때
  • 자동으로 해야 할 때
    • 서비스를 유지보수하고 있고, 기존 제품 코드를 수정하는 일이 대부분일 때
    • 언젠가 전역 영향 범위의 있는 기능/리팩토링 작업이 있을 것 같을 때
  • 회사에선 수동으로 하고, 집에서 연습해야 할 때
    • 테스트 코드 작성으로 인해 업무 시간이 10% 이상 늘어날 때
    • 내 테스트 코드가 자주 깨져 동료가 불편함을 토로했을 때
 

자동화할 수 없는 테스트

  • 절차가 과도하게 길거나, 컴퓨터에게 시키기가 과도하게 어려운 경우
    • (ex) mock 없이 캡쳐 인증이 포함된 경로를 테스트
    • (ex) mock 없이 주민등록증 사진 인증이 포함된 경로를 테스트
  • 테스트 도구의 한계로 검증이 불가능한 경우
    • Playwright, Cypress 등에서 제공할 수 없는 경우 불가능
 

브라우저 동작 녹화를 이용한 테스트 코드 작성

  • Playwright를 사용하는 경우, npx playwright codegen로 브라우저가 열리고 사용자의 행동이 녹화된 후 코드로 작성됩니다.
    • 일부 브라우저를 직접 띄워 테스트해야 하는 경우 해당 방식이 유용할 것입니다.
    • (단, 코드 퀄리티는 낮을 수 있습니다.)
 

LLM으로 테스트 코드 작성하기 (불가능?)

  • LLM을 사용하는 경우, 코드를 주고 단위 테스트를 작성해달라고 할 수 있습니다.
  • 알고리즘 문제의 정답 코드를 주고 (입력, 출력) 쌍을 30개 정도 만들어달라고 해보았습니다.
    • 실제로는 정답 코드라는 게 없을 테니 덜 유용할 것입니다.
    • GPT 4o
      • 알고리즘 문제의 정답 코드를 주고 (입력, 출력) 쌍을 30개 정도 만들어달라고 했을 때, 13개의 틀린 출력 값을 제공받았습니다.
      • 단순한 TC 개발은 가능할 것 같습니다.
    • GPT o1
      • 알고리즘 문제의 정답 코드를 주고 (입력, 출력) 쌍을 30개 정도 만들어달라고 했을 때, 거의 한 5분 동안 무한루프에 걸렸습니다. (직접 취소)
        • 매우 긴 추론 내용
          • notion image
      • 아무래도 코드를 직접 실행시키는 게 아니라 결과를 추론하다보니 이런 것 같습니다.
        • notion image