고정 대기 대신 상태 확인
130분 안팎
학습 목표
지연과 오류 표시를 관찰 가능한 조건으로 기다립니다.
개념
시간은 업무 완료 조건이 아닙니다
로그인 클릭 후 1초를 기다리는 코드는 1초가 지났다는 사실만 확인합니다. 응답이 더 늦으면 실패하고 더 빠르면 시간을 낭비합니다. 동아리 서비스에서 기다려야 할 것은 자기 프로필 영역의 표시와 정확한 이메일, 로그인 완료 안내입니다. 이 상태가 보일 때 다음 수정 행동으로 넘어갑니다. 타임아웃은 기다림의 상한이며 업무 완료를 대신하는 고정 지연과 다릅니다.
브라우저의 클릭 자동 대기는 대상이 행동 가능한지 확인하는 기능입니다. 그것만으로 로그인 결과가 올바르거나 프로필 저장이 끝났다고 판단할 수 없습니다. 행동 뒤 별도로 기대 상태를 단언합니다. 사용한 자동 대기 API의 기준은 Playwright 행동 가능성 문서에 있으며 이 실습의 업무 기대값은 합의한 회원 흐름에서 정합니다.
지연을 재현 가능한 장벽으로 만듭니다
제공 delayed 테스트는 로그인 요청을 route에서 잡고 gate라는 Promise가 풀릴 때까지 응답을 진행하지 않습니다. 실제 잠든 밀리초 수로 지연을 만드는 방식과 다릅니다. 요청 진입을 알리는 started를 기다린 뒤 status가 처리 중이고 로그인 버튼이 disabled인지 확인합니다. 그 다음 release를 호출해 서버로 요청을 진행하고 정상 로그인 완료를 검증합니다.
이 구성은 지연 중 화면이 사라지는 경쟁을 줄입니다. 응답을 통제하지 않고 로딩 문구가 잠깐 나올 때를 노리면 빠른 환경에서 문구가 이미 없어질 수 있습니다. gate는 처리 중 상태를 관찰하는 동안 응답 경계를 닫아 둡니다. 단언이 실패해도 finally가 release를 호출하여 요청을 막힌 채 남기지 않습니다. 기다리는 조건과 종료 경로를 한 쌍으로 설계합니다.
게이트를 풀기 전에 로그인 완료를 기다리면 자신이 막아 둔 요청을 스스로 기다리는 교착 구조가 됩니다. 준비→요청 도착→로딩 단언→해제→완료 단언의 순서를 지킵니다. 요청이 오지 않아 started에서 멈추면 클릭 단계와 route 패턴, 브라우저 로그를 조사합니다. 시간 상한에 도달한 것을 정상 지연으로 숨기지 않습니다.
업무 상태와 표시값을 함께 기다립니다
loggedIn은 내 프로필 영역이 보이고 표시 이메일이 이번 fixture의 값이며 status가 로그인 완료인지 확인합니다. 어느 조건이든 틀리면 다음 단계로 넘어가지 않습니다. 이전 화면의 로그인 완료 문구가 남았더라도 자기 계정 조건을 함께 검증하면 거짓 성공을 줄입니다. 단언마다 관찰값을 명확히 하여 메시지의 expected와 actual 차이를 읽을 수 있게 합니다.
saved는 저장 완료 문구와 다시 조회된 닉네임을 비교합니다. starter는 닉네임 기대값을 처리 전으로 잘못 고정했습니다. 이를 nickname 매개변수로 바꾸고 비동기 단언의 await를 유지합니다. 기다렸다는 이유로 값 검사를 없애지 않습니다. 화면이 바뀌기를 기다리는 것과 그 변화가 요구한 결과인지 판단하는 것은 함께 필요합니다.
일시 오류와 복구를 한 사례에 묶습니다
recovery는 프로필 PATCH에 503 응답을 한 번 주입합니다. 제품 UI는 잠시 후 다시 시도해 주세요를 보여 주고 버튼을 다시 활성화하며 이전 닉네임을 보존해야 합니다. API로 저장값도 그대로인지 확인합니다. 오류 문구가 보였다는 사실만 확인하면 버튼이 계속 잠겨 사용자가 복구할 수 없는 결함을 놓칩니다.
두 번째 시도에는 route가 실제 API로 요청을 보냅니다. 같은 입력을 다시 제출한 뒤 저장 완료와 복구회원 표시를 확인하고 alert가 비었는지도 검사합니다. 재시도로 이전 실패를 없애는 러너 정책과 사용자가 오류 뒤 재시도하는 요구는 다릅니다. 이 테스트는 첫 실패 UI 자체도 성공 조건으로 검사한 뒤 두 번째 행동의 결과를 관찰합니다.
503은 테스트 경계에서 응답을 바꾼 합성 오류입니다. Java 저장 함수가 실제로 503을 생성한다는 증거로 보고하지 않습니다. 그 응답을 받은 브라우저의 표시·버튼·복구 동작이 검증 대상입니다. 실제 네트워크 단절과 요청 유실, 저장 성공 후 응답 유실은 다른 상태이므로 후속 사례로 적습니다.
세션 만료와 빈 입력을 구별합니다
expired 테스트는 로그인한 context의 API 요청으로 서버 세션을 명시적으로 무효화합니다. 다음 다시 조회에서 401과 로그인이 필요합니다 안내, 프로필 영역 숨김을 기대합니다. 자연 시간 경과로 세션이 만료되는 정책이나 타이머 정확성은 이 검사의 범위가 아닙니다. 서버 상태 변화 뒤 다음 사용자 행동의 대응을 확인합니다.
blank 사례는 새 닉네임을 빈 값으로 두고 저장을 시도합니다. 제공 HTML의 required 검증이 제출을 막아 PATCH가 없고 기존 닉네임이 유지되는지 봅니다. 반면 공백 문자열의 서버 거절은 앞 API 검사에 있습니다. 브라우저가 막은 입력과 서버가 거절한 입력을 한 결과로 합치지 않아야 빠진 경로를 찾을 수 있습니다.
대기 실패를 진단합니다
Expected string과 Received string이 다르면 데이터·화면 반영·기대값을 순서대로 비교합니다. 예를 들어 API는 복구회원인데 화면은 합성회원이면 UI 반영을 조사합니다. API도 이전 값이면 저장 요청 상태를 읽습니다. Timeout이 같아 보여도 요소가 없는 선택 문제, 상태가 오지 않는 제품 문제, 앱 기동 실패는 다음 조치가 다릅니다.
catch에서 대기 오류를 삼키고 진행하면 저장되지 않은 상태로 로그아웃 검사까지 통과할 수 있습니다. 증거를 수집한 뒤 원래 오류를 전파합니다. expect의 기다리는 단언에 await가 빠지면 검사 종료와 비동기 실패가 엇갈리므로 함수 전체가 async인지 확인합니다. async 함수의 반환과 오류 전파 일반 원리는 서재에서 더 읽고 여기서는 완료 조건의 독립성을 점검합니다.
대기 전략의 완료 기준입니다
qa-ui-waiting에서는 지연 로그인, 강제 세션 만료, 503 후 복구, 빈 닉네임 네 사례를 구성했습니다. 지연 장벽은 테스트가 만들고 업무 완료는 locator assertion이 관찰합니다. actions와 browser 테스트에는 고정 sleep 호출을 넣지 않습니다. 제한 시간을 늘리는 조정이 필요하면 환경 근거와 관찰한 지연을 남기고 기능이 끝나지 않는 결함을 숨기지 않습니다.
제출에는 로딩 전·중·후의 기대 상태, 오류 때 보존할 저장값, 복구 후 표시값을 기록합니다. 실행할 수 없는 환경의 결과는 미실행으로 남깁니다. UI 대기 조건을 고친 뒤 기존 API와 격리 검사가 유지되는지 핵심 검사로 확인하고 실제 브라우저 검사 결과를 별도로 제출합니다. 이 구분이 다음 모듈에서 CI 환경 문제와 제품 결함을 분류할 근거가 됩니다.
따라하기
게이트가 풀린 뒤 완료됩니다
독립 실행 예제로 요청을 잠근 상태와 해제 후 상태를 구별합니다. 타이머 없이 Promise 경계를 통제합니다.
(async()=>{let release;const gate=new Promise(r=>release=r);let state='처리 중';const request=(async()=>{await gate;state='로그인 완료';})();console.log(state);release();await request;console.log(state);})().catch(e=>{console.error(e);process.exitCode=1;});실행 결과
처리 중 로그인 완료
저장 완료의 정확한 값을 기다립니다
qa-ui-waiting의 app/ui/actions.cjs에서 saved의 TODO를 아래 단언으로 고칩니다. nickname은 호출자가 요구한 기대값입니다.
await expect(page.locator('#nickname')).toHaveText(nickname);오류와 완료를 구별합니다
상태 코드만 보고 성공 안내로 합치지 않습니다. 이 단계는 응답 분기 개념을 실행한 것이며 실제 앱 화면 결과는 별도 검사합니다.
for(const status of [200,401,503])console.log(status,status===200?'완료':status===401?'재로그인':'재시도 안내');실행 결과
200 완료 401 재로그인 503 재시도 안내
지연과 복구 사례를 확인합니다
압축 루트에서 실행해 delayed·expired·recovery·blank 네 사례를 확인합니다. delayed는 gate 해제 전 로딩과 버튼 잠금을, 해제 후 정확한 자기 계정을 검사합니다. 실제 출력은 외부 브라우저 실행 후 기록합니다.
bash check.sh확인 문제
실습
actions.cjs의 saved TODO에 요청한 nickname의 상태 기반 단언을 완성합니다. 지연·만료·503 복구·빈 입력 네 사례를 유지합니다.
실행 명령
bash check.sh
기대 결과
기존 API 검사와 브라우저 4사례 실패 0
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- UI 자동화에서 고정 시간 대기를 줄이는 방법을 설명해 주시면 됩니다.