시각적 회귀 테스트
시각적 회귀 테스트
스타일 변화는 다양한 요소에 영향을 받으므로 코드만으로 예측하기는 어렵다.
이상적인 방법으로 브라우저별로 모든 페이지를 육안으로 확인하는 것은 어렵기에 불가능
이전에 작성한 CSS 코드를 수정하거나 삭제하다보면 의도치 않은 곳에서 변경이 되기도 함
이같은 부작용을 대처하고자 '문제가 생기면 이전에 작성한 코드는 건드리지 않고 새로 작성한 코드에서 해결한다" 라는 소극적인 방침을 세우는 팀도 존재
이런 소극적인 방침은 리팩터링을 불가능하게 만드는 대증치료에 불과함
SPA는 작은 UI 컴포넌트를 조합하여 화면을 만듬
마치 레고 블럭을 조립하는 방식과 비슷하며 컴포넌트 기반 개발이라 불린다.
로직과 중복되는 CSS 코드를 한곳에서 관리 할 수 있게 된다.
많은 화면이 수많은 공통 컴포넌트를 공유하기 때문에 한 컴포넌트의 수정 여파가 크다는 단점도 있음
시각적 회귀 테스트를 스냅샷 테스트로 대체할 수 있나?
스냅샷 테스트는 시각적 회귀 테스트의 한 방법이지만 전역에 정의한 스타일의 영향을 알긴 어렵다.
마치 단위 테스트에서 알아채지못한 문제를 통합 테스트에서 발견하는 상황과 비슷
스냅샷은 단순히 HTML 출력 결과를 비교할 뿐이라 모든 시각적 회귀 테스트를 대체할 수 없다.
시각적 회귀 테스트 선택지
가장 신뢰도가 높은 방법은 브라우저에 렌더링된 화면을 비교하는 것
테스트할 화면을 브라우저에 렌더링하고 특정 시점에 캡처한 이미지들을 픽셀단위로 비교하는 것이 가장 기본 방법
시각적 회귀 테스트는 크로미엄같은 브라우저를 헤드리스 모드로 실행한 상태에서 실시함
헤드리스 브라우저는 보통 E2E 테스트 프레임워크에 포함되어있음
E2E 프레임워크에선 공식적으로 시각적 회귀 테스트를 지원한다.
페이지 단위로 캡처하여 스타일 변경 전후의 차이점을 발견
단점으로 세세한 부분 (A가 변경되어 다른 영역에 영향을 끼친 경우 전부 변경됬다고 보게됨) 어디가 정확히 변경됬는지 알지 못함
세세하게 검출하고 싶다면 UI 컴포넌트 단위로 실시해야함
컴포넌트 단위로 이미지를 캡처하면 영향을 받는 중간 크기의 컴포넌트를 검출할 수 있다.
작은 크기의 컴포넌트와 중간 크기의 컴포넌트를 개별적인 스토리로 등록하면 컴포넌트 탐색기에서 확인할 수 있을 뿐만 아니라 시각적 회귀 테스트에서도 활용 가능
reg-cli로 이미지 비교
시각적 회귀 테스트용 플랫폼으로 스토리북을 사용할 수 있지만 별도 시각적 회귀 테스트 프레임워크를 사용해보자
reg-suit
는 AWS S3 같은 실제 버킷이 없어도 로컬에서 테스트 가능하다.reg-suit
의 핵심 기능인reg-cli
를 사용해서 이미지를 비교해보자.
스토리북 - 스토리캡 도입
스토리북을 활용한 시각적 회귀 테스트 방법
스토리캡은 스토리북에 등록된 스토리를 캡처하는 도구
스토리캡도 reg-suit를 중심으로 한 reg-viz 생태계에 속하지만, reg-suit 플러그인과 달리 별도로 설치해야한다.
스토리 단위로 캡처하기 떄문에 스토리북을 잘 활용할수록 테스트 효율이 높아진다.
설정
스토리캡 설정을 스토리북 설정 파일에 추가
해당 설정들을 추가하면 프로젝트에 있는 모든 스토리 파일이 캡처 대상이되며 시각적 회귀 테스트를 할 수 있게됨
실행
스토리를 캡처하기 전 스토리북을 빌드
빌드를 해야 응답 속도가 빨라지므로 사전에 빌드하는 것을 권장
빌드가 끝나고
npm run storycap
을 실행하면 빌드된 스토리북을 정적 사이트로 실행해 모든 스토리를 캡처한다.캡처가 완료된 이미지는
__screenshots__
디렉터리에 저장됨디렉터리 컨벤션에 맞추려면
mv __screenshots__ expected
actual: 기존 이미지를 저장하는 디렉터리
expected: 비교할 이미지를 저장하는 디렉터리
diff: 비교 결과를 검출할 이미지를 저장하는 디렉터리
스타일을 수정 후 스토리북을 다시 빌드 & 스토리캡을 실행하면
__screenshots__
에 변경된 스타일이 반영된 스토리 이미지가 저장됨해당 디렉터리를
actual
로 변경
reg-cli로 이미지 간 차이 검출하기
expected
와actual
디렉터리가 만들어졌으므로reg-cli
로 이미지 간 차이점을 검출해보자.HTML 리포트를 열어 차이점을 확인
reg-suit 도입하기
reg-cli
를 사용하여 로컬 환경에서만 시각적 회귀 테스트를 진행했다.시각적 회귀 테스트를 자동화해서 깃허브와 연동해보자.
깃허브와 연동하면 저장소에 push 할 때 마다 토픽 브랜치의 시각적 회귀 테스트가 실시되기 때문에 변경된 코드에서 어떤 차이점이 발생하는지 자동으로 리포트 받을 수 있다.
reg-suit 도입
프로젝트 저장소 최상위 경로로 이동 후
npx reg-suit init
실행개발 환경에
reg-suit
을 글로벌 설치했다면reg-suit init
만 실행해도 됨
커맨드 실행 후 어떤 플러그인을 설치할지 물어보는데 기본값 세팅 그대로 엔터키 ㄱ
해당 플러그인들은 임의의 CI 환경에
reg-suit
를 도입시켜주는 편리한 라이브러리임reg-keygen-git-hash-plugin
,reg-publish-s3-plugin
은 원격 환경에서 이미지를 비교하기 위한 라이브러리임
커밋 해시로 파일명을 지은 스냅샷셋과 검증 결과 리포트를 외부 파일 저장소 서비스(AWS S3)에 전송한다.
토픽 브랜치의 기반이 되는 커밋에서 스냅샷셋을 추출하여 기댓값으로 두고, 이후 커밋에서 추출한 이미지와 차이점을 검출한다.
검증 결과를 PR에 알려주는
reg-notify-github-plugin
을 사용하면 통상적인 워크플로에 시각적 회귀 테스트를 도입할 수 있다.슬랙 등의 채팅 도구에 알림을 보내는 플러그인도 존재
reg-suit 설정파일 생성
reg-notify-github-plugin
질문에 Yes를 선택하면 브라우저 창 열림reg-suit
의 깃허브 애플리케이션 설치와 저장소 연동을 위한 것이렇게 설치하는 것만으로 PR에 검증 결과를 알려주게 됨
[Configure] 버튼을 클릭하면 저장소 연동화면으로 이동되며, 테스트를 실시할 저장소를 선택,
연동이 완료되면 선택된 저장소가 화면에 표시됨
연동한 저장소에 있는 [Get Client ID] 버튼을 클릭하면 모달이 열림
해당 Client ID는 환경 변수로 설정할 것이므로 [Copy to clipboard] 버튼ㅇ르 클릭해서 복사
Client ID 취득
설치가 완료되면 reg-suit 설정 파일인
regconfig.json
이 생성됨파일을 열어
clientId
에는"$REG_NOTIFY_CLIENT_ID"
를bucketName
에는"$AWS_BUCKET_NAME"
를 입력이값들은 깃허브 액션 실행 시에 환경 변수에서 참조된다.
실제 운영 환경을 고려한 오차 범위 설정
실제 운영 환경에 자동화된 시각적 회귀 테스트는 불안정한 테스트(코드나 테스트에 변경 사항이 없는데도 상황에 따라 성공하기도 실패하기도 하는 테스트)로 변질되곤 한다.
이는 브라우저에서 여러 요소가 트리 구조로 계층화될 때 안티에일리어싱(위신호 제거)이 발생하는 과정에 차이점이 검출되는것이 원인
불안정한 테스트가 발견되면 차이점을 검출하는 강도를 낮추는것을 검토해야함
thresholdRate: 차이점이 검출된 곳의 픽셀 수를 전체 대비 비율로 계산
thresholdPixel: 차이점이 검출된 픽셀수의 절대값
을 조정함녀서 안정적인 운용이 가능한 임계치를 찾아야함
외부 스토리지 서비스 설정
스냅샷 에셋과 검증 결과 리포트를 저장할 외부 스토리지 서비스를 설정
reg-publish-s3-plugin
을 선택했으므로 AWS S3 버킷을 생성
버킷 생성
AWS Management Console 에 로그인해서 S3에 새 버킷을 생성
reg-suit
깃허브 애플리케이션이 생성된 버킷에 검증 결과 리포트를 전송, 열람할 수있도록 일부 권한을 설정우선 객체 소유권에서 ACL(접근 제어 목록)access control list을 활성화한다.
버킷의 퍼블릭 액세스 차단 설정에서 일부 차단 설정을 해제
새 ACL을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단 - 해제
임의의 ACL을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단 - 해제
IAM 사용자 생성
버킷에 접근할 사용자를 IAM에서 생성해보자.
원하는 사용자명을 입력 후 [다음] 클릭
AmazonS3FullAccess 권한을 연결해서 사용자가 S3 버킷에 자유롭게 접근할 수 있도록 설정
사용자 생서을 완료 후 액세스 키와 비밀 액세스 키를 취득
.csv 파일을 저장하거나 다른 곳에 복사
액세스 키들은 절대 저장소에 커밋하지 않도록 주의
깃허브 액션에 reg-suit 연동하기
깃허브 액션이 완료되면 PR을 생성할 때 마다 자동으로 시각적 회귀 테스트가 실시되며, 테스트가 끝나면 검증 결과를 PR에 알린다.
크리덴셜을 Actions Screts에 등록
지금까지 메모한 크리덴셜을 저장소의 Actions Scretes에 설정한다.
[Settings] -> [Secrets and variables] -> [Actions] -> [New repository Secret] 버튼을 클릭
AWS_ACCESS_KEY_ID
: IAM 사용자의 액세스 키AWS_BUCKET_NAME
: S3 버킷 이름AWS_SECRET_ACCESS_KEY
: IAM 사용자의 비밀 액세스 키REG_NOTIFY_CLIENT_ID
:reg-suit
의 Client ID
AWS_BUCKET_NAME, REG_NOTIFY_CLIENT_ID는 최종적으로
regconfig.json
에 적용된다.이 값들은 중요한 정보가 아니므로
json
에 직접 작성해도 되지만, 저장소별로 설정해야하는 값이므로 편의상 환경 변수에서 불러오도록 세팅
깃허브 액션 설정
깃허브 액션 워크플로 작성
fetch-depth: 0
반드시 추가해야 한다.이 값이 없으면 부모 커밋을 취득하지 못해 테스트가 실패하게 됨
연동 확인
깃허브 액션에서 시각적 회귀 테스트가 실행되는지 확인해보자.
PR 생성 후 깃헙 액션이 완료되면 reg-suit 봇이 코멘트를 남김
뻘건색 동그라미: 차이점이 검출된 아이템
흰색 동그라미: 새롭게 추가된 아이템
검은색 동그라미: 삭제된 아이템
파란색 동그라미: 차이점이 발견되지 않은 아이템
봇이 남긴 코멘트에 있는 [this report] 링크를 클릭하면 S3에 저장한 검증 결과 리포트를 확인 가능
차이점이 없어지거나 리뷰어가 PR을 승인하면 체크 상태가 녹색으로 변경됨
시각적 회귀 테스트를 활용한 적극적 리팩토링
회귀 테스트는 릴리스 전에 실시한다고 생각하지만, 반복 작업을 줄이고 싶다면 개발 과정에 도입하는 것이 좋음
반응형 디자인에 활용
반응형 프로젝트는 효율적으로 시각적 회귀 테스트를 활용할 수 있다.
프로젝트 사정상 PC용 디자인을 먼저 완성하고 이후 모바일 용 디자인을 구현해도 시각적 회귀 테스트가 설정됐다면 실수를 줄일 수 있다.
reg-suit는 CI를 도입하지 않았다고 해도 유용하게 사용할 수 있다.
수동으로 편리하게 실시할 수 있을 정도로만 환경을 세팅해놓고 미디어 쿼리로 반응형 대응을 하거나 리팩터링 가능
릴리스 직전의 리팩터링에 활용
스타일 관련 전역 코드를 하나씩 삭제하면서 시각적 회귀 테스트를 통해 플젝에 영향을 미치는 영향을 확인 가능
실제로 필요한 CSS 코드만 남기는 리팩터링은 시각적 회귀 테스트가 없다면 불가능
스토리 커밋 습관화로 시작하는 시각적 회귀 테스트
스토리를 만들면 컴포넌트 단위로 시각적 회귀 테스트를 실시하는 것은 쉽다.
등록된 스토리의 숫자만큼 세밀한 검증이 가능하기 때문에 습관적으로 스토리를 커밋할것을 권장
릴리스 직전에 스토리를 커밋하면 반응형 디자인이 필요할 때 여유롭게 대응하는것이 힘들어 도입 자체가 좌절되기 쉽다.
스토리가 정말로 필요하지 않다고 느껴지지 않는 한, 처음부터 커밋
Last updated