Playwright는 프론트엔드 개발자에게 강력한 웹 자동화 및 테스트 도구를 제공합니다. 하지만 UI에서 발생하는 이벤트와 비동기로 동작하는 API 요청 사이의 타이밍 문제로 인해 예상치 못한 타임아웃 오류가 발생할 수 있습니다. 특히 API 호출을 기다리고 그 응답을 검증하는 테스트의 경우, 응답을 제대로 기다리지 못해 타임아웃 문제가 빈번하게 발생할 수 있습니다.
이 글에서는 Playwright에서 확실하게 API Response를 기다리는 방법에 대해 다루고, 더 안정적이고 신뢰성 있는 테스트를 작성하는 방법을 소개하겠습니다.
waitForResponse를 잘못 사용한 비동기 예시Playwright는 page.waitForResponse 메서드를 통해 특정 URL에 대한 응답을 기다릴 수 있습니다. 하지만 이 메서드를 비동기 환경에서 적절히 사용하지 않으면 타이밍 문제로 인해 타임아웃 오류가 발생할 수 있습니다. 우선 waitForResponse를 잘못 사용한 예시 코드를 살펴보겠습니다.
test("test for assert after api response", async ({ page }) => {
await page.getByRole("button", { name: "제출" }).click();
await page.waitForResponse("https://api.service.com/api/something");
});
이 코드의 의도는 비동기적으로 버튼 클릭 후 API 호출을 기다리고 그 응답을 검증하는 것입니다. 하지만 이 방식에는 몇 가지 문제가 있습니다.
위 코드에서 waitForResponse는 버튼 클릭 이후에 실행됩니다. 하지만 실제로는 버튼 클릭 후 API 요청이 발생하기 전에 응답 대기가 실행되어야 합니다. API 호출은 비동기적으로 작동하기 때문에, 버튼을 클릭한 후 즉시 API 요청이 생성되고 응답이 반환될 수 있습니다. 만약 API 요청이 매우 빠르게 처리되었다면, waitForResponse가 실행될 때 이미 응답이 완료된 상태일 수 있습니다. 이 경우 응답을 놓치게 되어 타임아웃 오류가 발생할 수 있습니다.
또한, 위 코드에서는 특정 URL에 대한 응답을 기다리기만 할 뿐, 해당 요청이 성공했는지(status 200) 여부는 전혀 확인하지 않습니다. 비동기적으로 동작하는 API 호출이 실패했을 경우에도 테스트가 통과할 수 있어, 서버 오류(4xx, 5xx)나 잘못된 응답이 발생하더라도 테스트가 실패하지 않을 수 있습니다.
비동기 API 호출의 타이밍 문제를 방지하고 안정적인 테스트를 작성하려면 API 요청에 대한 응답을 기다리는 대기 작업을 미리 설정한 후, 버튼을 클릭해 API 요청을 트리거해야 합니다. 이렇게 하면 요청과 응답의 비동기 타이밍 문제를 피할 수 있습니다. 또한, 응답의 상태를 명시적으로 검증하여 요청이 성공적으로 처리되었는지 확인해야 합니다.
다음은 이러한 문제를 해결한 코드입니다:
test("test for assert after api response", async ({ page }) => {
// 응답 대기를 먼저 설정
const responsePromise = page.waitForResponse(async (response) => {
// URL과 응답 상태를 검증
return response.url().includes("https://api.service.com/api/something") && response.status() === 200;
});
// 버튼을 클릭하여 비동기 API 호출 트리거
await page.getByRole("button", { name: "제출" }).click();
// 미리 설정한 응답 대기 프라미스를 대기
const res = await responsePromise;
// 응답 내용을 JSON으로 파싱
const jsonResponse = await res.json();
// 응답의 내용에 대한 추가적인 검증 수행
expect(jsonResponse).toHaveProperty('data');
});
이 코드는 버튼을 클릭하기 전에 응답 대기를 설정합니다. Playwright는 이제 비동기 API 요청이 발생할 때까지 기다리고, 요청이 발생한 후에 응답이 올 때까지 타이밍 문제 없이 정확하게 응답을 받을 수 있습니다.
page.waitForResponse에서 URL뿐만 아니라 응답의 상태 코드도 함께 확인합니다. 이로 인해 응답이 성공적(status 200)인지 명확하게 확인할 수 있습니다. 이는 서버 오류나 잘못된 응답이 있을 때 테스트가 올바르게 실패하도록 만듭니다.
응답을 JSON으로 파싱한 후, 그 데이터에 대한 추가 검증을 수행할 수 있습니다. 이를 통해 API가 예상대로 데이터를 반환했는지 확인할 수 있으며, 이는 테스트의 신뢰성을 높입니다.
타이밍 문제 해결:
비동기 API 요청이 이루어지기 전에 응답을 대기하는 구조로 타이밍 문제를 해결할 수 있습니다. 이 방식은 응답을 놓치는 상황을 방지하여 타임아웃 오류를 줄여줍니다.
응답 상태 및 데이터 검증:
단순히 응답이 오는 것뿐만 아니라, 그 응답이 성공적인지(예: status 200) 확인하고, 반환된 데이터를 검증할 수 있습니다. 이를 통해 더욱 신뢰성 있는 테스트를 만들 수 있습니다.
안정적인 테스트:
이런 구조의 테스트는 비동기 API 호출의 성공 여부를 확실하게 검증하므로, 서버의 상태나 API의 응답이 예상과 다를 때 제대로 실패하도록 만듭니다. 이는 이후 디버깅이나 유지보수를 훨씬 쉽게 만들어줍니다.
Playwright에서 비동기 API 응답을 기다리는 테스트를 작성할 때, 타이밍 문제로 인한 타임아웃 오류를 방지하려면 응답 대기 작업을 버튼 클릭 전에 설정하고, 응답의 상태를 명확히 검증하는 것이 중요합니다. 이 방법은 테스트의 안정성을 높이고, 타이밍 문제를 해결하여 타임아웃 오류를 피할 수 있는 가장 효과적인 방법입니다.
프론트엔드 테스트는 UI와 백엔드 API 간의 상호작용이 잘 맞물려야 신뢰할 수 있습니다. 이번에 소개한 방법을 통해 더욱 견고하고 안정적인 Playwright 테스트를 작성해 보세요!
test("test for assert after api response", async ({ page }) => {
const responsePromise = page.waitForResponse(async (response) => {
return response.url().includes("https://api.service.com/api/something") && response.status() === 200;
});
await page.getByRole("button", { name: "제출" }).click();
const res = await responsePromise;
const jsonResponse = await res.json();
expect(jsonResponse).toHaveProperty('data');
});
이 방법을 사용하면 비동기 API 응답을 확실하게 기다릴 수 있으며, 타임아웃 오류를 방지하면서 테스트의 신뢰성을 크게 높일 수 있습니다.