Devin.KR

실패 로그·화면·추적 증거

110분 안팎

학습 목표

UI 실패의 요청·화면 증거를 연결하고 민감값을 제거합니다.

개념

실패가 사라지기 전에 증거를 남깁니다

자동화가 실패했는데 빨간 종료 코드만 있으면 담당자는 어떤 요청과 화면을 보아야 할지 모릅니다. 동아리 프로필 테스트에서는 수정회원이 기대값인데 화면이 다른 닉네임을 그린 시점을 남겨야 합니다. 실행마다 실패 ID를 정하고 같은 ID 아래 요청 요약, 마스킹 화면, 판정 요약을 모읍니다. 증거 수집은 원래 단언 실패를 설명하기 위한 작업이며 통과로 바꾸는 예외 처리와 구분합니다.

화면 캡처는 특정 순간의 표시를 보여 주고 로그는 요청의 순서를 보여 줍니다. trace는 행동·요청·DOM 등 실행 문맥을 조사하는 자료입니다. 이 셋이 서로 대신하지 않습니다. 같은 failureId와 requestId로 연결하면 API 200 뒤 UI 반영 실패처럼 층이 다른 사건도 찾을 수 있습니다. 원본 비밀번호와 세션 쿠키를 공개 자료의 연결 키로 쓰지 않습니다.

공개 로그는 허용 필드로 새로 만듭니다

publicLog는 원본 이벤트를 그대로 돌려주지 않고 requestId·method·path·status·result 다섯 필드로 새 객체를 만듭니다. requestId는 ui와 숫자 조합, method와 path와 result는 제공 계약의 목록, status는 100부터 599까지 정수인지 검사합니다. 예상 밖 문자열은 UNKNOWN 또는 생략 표기로 대체합니다. 경로에 이메일 쿼리가 섞이면 허용 경로와 달라 생략됩니다.

키 이름이 password인 항목만 지우는 차단 목록으로는 중첩 body, headers의 Cookie, 오류 메시지 속 이메일을 놓칠 수 있습니다. 새 필드가 늘어나도 허용 목록에 없는 항목은 공개되지 않도록 만듭니다. 실제 서비스에서 필요한 필드를 추가할 때는 그 필드가 가질 값의 범위와 보안 검토를 함께 변경합니다. 일반적인 문자열 정규식 하나로 모든 비밀을 찾을 수 있다고 주장하지 않습니다.

core.test.cjs는 합성 비밀번호·쿠키·개인 닉네임과 알 수 없는 결과 문자열을 넣어 공개 JSON에 없는지 검사합니다. 정상 메타데이터 보존, 중첩 누출 방어, 상태 코드 경계, 빈 이벤트, 경로 이탈 실패 ID, m06 실패 뒤 정리까지 여섯 사례입니다. starter는 raw events를 반환하므로 일부 검사가 실패합니다. 이 결함은 브라우저 없이 직접 재현할 수 있습니다.

화면과 trace의 공개 정책이 다릅니다

capture는 data-sensitive가 붙은 요소를 검은 영역으로 마스킹하여 PNG를 저장합니다. 이메일·비밀번호 입력과 닉네임 출력은 모두 이 속성을 갖습니다. 원래 페이지 값을 바꾸지 않고 캡처에 마스크를 적용합니다. 마스킹 옵션과 화면 캡처 API는 Playwright 스크린샷 문서를 참고합니다. 다른 곳에 개인정보가 추가되면 화면 계약과 마스크 범위도 재검토합니다.

PNG 안 문자열을 텍스트 검색했다고 비밀값이 없다고 결론 내릴 수 없습니다. 압축된 픽셀은 로그 문자열과 다른 형태입니다. 자동 검사는 PNG 파일 존재와 JSON의 합성 문자열 부재를 확인하고 summary에 imageReview를 required로 기록합니다. 공개 전 사람이 이미지에서 가려진 영역과 나머지 텍스트를 확인하는 절차를 제출 기준에 넣습니다.

스크린샷 마스크가 원본 trace의 DOM·요청까지 지워 주지는 않습니다. 그래서 원본 trace.zip은 artifacts/private의 실패 ID 폴더에 저장하고 공개 폴더에는 넣지 않습니다. trace에는 합성 비밀번호라도 남을 수 있습니다. Playwright trace 조사 문서를 참고해 로컬에서 열고 원본 전체를 공개 저장소나 외부 뷰어에 업로드하지 않습니다.

의도한 UI 결함으로 검사를 검증합니다

mutation 테스트는 실제 서버의 프로필 GET 응답을 받아 nickname만 의도한 UI 결함으로 바꿔 브라우저에 전달합니다. API 저장은 수정회원이어도 UI 재조회가 다른 이름을 표시하도록 만듭니다. 같은 saved 단언이 toHaveText에서 실패해야 합니다. 테스트가 계속 초록색이면 표시값을 단언하지 않거나 오류를 삼켰는지 조사합니다.

외부 테스트는 해당 단언 실패가 실제로 발생했는지 assert.rejects로 확인하고 공개 summary의 failureId, 로그의 비밀 문자열 부재, PNG와 private trace의 존재를 검사합니다. 이것은 의도한 결함 검출을 평가하는 테스트이므로 예상대로 검출하면 전체 검사는 통과합니다. 보고서에는 정상 제품 검사의 통과와 결함 주입 검사의 검출을 서로 다른 항목으로 적습니다.

수집 오류도 원래 오류와 함께 보존합니다

디스크 쓰기나 screenshot이 실패하면 화면 자료가 없을 수 있습니다. catch는 수집을 시도한 뒤 원래 단언 오류를 다시 던집니다. 수집까지 실패하면 AggregateError에 두 원인을 담습니다. 로그 파일을 만들었다고 테스트를 성공 반환하지 않습니다. 실패가 없었던 것처럼 보이는 보고는 후속 회귀의 근거를 훼손합니다.

finally는 소유 계정 정리와 기준 행 보존 확인을 실행하고 trace·browser context를 닫습니다. JUnit은 Node 종료 후 Spring 앱도 닫습니다. 데이터 정리는 증거 수집과 다른 책임이며 성공과 실패 모두 실행해야 합니다. 정리 오류가 추가되면 잔여 ID와 원래 실패를 함께 보고해야 합니다. 제공 정리 API의 실패 처리 범위는 후속 강화 항목으로 남깁니다.

실패 자료에서 다음 조사를 고릅니다

public 로그의 PATCH 200와 GET 200가 보이고 표시 단언이 실패하면 requestId 순서와 화면을 연결해 반영 로직을 조사합니다. PATCH 503이면 사용자 오류 표시와 재시도 상태를 확인합니다. 로그에 요청이 없고 strict mode 메시지가 있다면 locator 범위부터 확인합니다. 종료 코드만으로 제품 결함을 확정하지 않고 각 증거가 관찰한 사실을 구별합니다.

스크린샷에 프로필이 없다면 로그인 실패, 만료 후 정상 숨김, 잘못된 선택 범위를 나누어 봅니다. public summary는 오류 본문 전체를 싣지 않으므로 민감한 원인 문자열이 필요하면 접근을 제한한 원본을 로컬에서 조사합니다. 공개용 요약에는 마지막 허용 요청 상태와 실패 종류, 재현 절차를 적고 비밀값을 설명에 다시 붙이지 않습니다.

미션의 결과물을 검토합니다

qa-ui-automation-mission은 m06 solution의 spec·cases·결함 보고·API·격리 검사를 보존한 채 실제 브라우저 검사를 추가합니다. starter의 가입 폼 범위, 저장 닉네임 기대값, 공개 이벤트 허용 목록을 완성합니다. 핵심 검사는 이전 산출물 보존과 Java·Node 회귀를 확인하며 브라우저 검사는 정상 여정·실패·복구·키보드와 의도한 UI 결함 검출을 실행하도록 구성했습니다.

완료 자료에는 실행 환경, 핵심 검사 결과, 브라우저 결과 또는 PENDING, 실패 ID별 공개 자료 검토 기록을 담습니다. 원본 trace를 공개했다고 완료로 인정하지 않습니다. 마스킹 이미지의 사람 확인과 제외한 브라우저·자연 만료·전체 접근성 범위를 명시합니다. node:test와 디버깅 도구의 일반 기능은 더 읽기로 보내고 이 레슨은 조사 가능한 실패 증거의 생성과 공개 경계에 집중합니다.

따라하기

공개 로그를 새 객체로 만듭니다

원본에 합성 비밀번호와 쿠키가 있어도 허용 메타데이터만 출력합니다. 실습의 publicLog는 값 허용 목록까지 추가합니다.

const raw={requestId:'ui7',method:'PATCH',path:'/practice/profile',status:503,result:'UNAVAILABLE',password:'Abcd1234!',cookie:'synthetic-session'};const {requestId,method,path,status,result}=raw;console.log(JSON.stringify({requestId,method,path,status,result}));

실행 결과

{"requestId":"ui7","method":"PATCH","path":"/practice/profile","status":503,"result":"UNAVAILABLE"}

여섯 core 검사를 실행합니다

qa-ui-artifacts의 app/ui/evidence.cjs에서 raw events 반환을 허용 필드 생성으로 고칩니다. core.test.cjs는 정상 메타데이터·중첩 비밀·상태 경계·빈 배열·실패 ID·정리를 확인합니다. Node 검사 통과는 이미지 마스킹 통과와 다릅니다.

node --test app/ui/core.test.cjs

화면 마스크와 원본 trace를 분리합니다

capture의 제공 코드를 읽습니다. 모든 민감 요소가 data-sensitive로 표시되었는지 확인하며 원본 trace는 private에 둡니다. 이 API 호출은 실제 브라우저 실행 전에는 결과를 적지 않습니다.

await page.screenshot({path:'public.png',mask:[page.locator('[data-sensitive]')],maskColor:'#000000'});
await context.tracing.stop({path:'private/trace.zip'});

의도한 UI 결함과 증거를 확인합니다

압축 루트에서 실행합니다. mutation 단언 검출 뒤 artifacts/public/mutation의 요약·로그·PNG와 private/mutation/trace.zip을 확인합니다. 공개 전 PNG를 사람이 보고 imageReview 확인 기록을 남깁니다. 원본은 로컬에서만 조사합니다.

bash check.sh
cd app/ui
npx playwright show-trace artifacts/private/mutation/trace.zip

확인 문제

실습

evidence.cjs의 publicLog TODO를 허용 필드·값 생성으로 구현합니다. core 여섯 검사와 mutation 검출 및 증거 연결을 확인하고 공개 PNG의 사람 검토 기록을 제출합니다.

시작 코드·테스트 내려받기

실행 명령

bash check.sh

기대 결과

Node core 6사례 실패 0, 의도한 UI 결함 검출 및 공개/제한 증거 생성

모범 답안모범 답안 내려받기

더 읽기

면접 질문

  • 재현하기 좋은 결함 보고서의 구성을 설명해 주시면 됩니다.
  • UI 자동화에서 고정 시간 대기를 줄이는 방법을 설명해 주시면 됩니다.