Wait의 종류

정태경·2022년 9월 3일
1
post-thumbnail
post-custom-banner

Implicit Wait (암묵적 대기)

암묵적 대기는 대기 시간을 전역적으로 정의할 때 사용하는 Wait의 종류이다.
우리는 일반적으로 새로운 웹 페이지에 접속하거나 특정 요소를 클릭했을 때 페이지를 로드하는 과정을 겪게 된다. 만약 페이지가 로드되지 않았는데 특정 엘리먼트를 식별하려 한다면 에러가 발생하게 되는데 이를 해결할 방법이 암묵적 대기이다.

암묵적 대기는 웹 드라이버를 통해 엘리먼트를 식별하거나 클릭 등의 액션을 시도할 때 오류를 발생시키기 전에 n 초까지 기다리라고 명령하는 방식이다. 드바이버 생성 후 전역적으로 한 번만 선언해주면 드라이버 객체가 소멸할 때까지 전역적으로 적용된다.

그렇다고 매 엘리먼트를 식별할 때마다 무조건 n 초를 대기하는 것이 아니다. 암묵적 대기 상태에서 계속 DOM을 읽어오고 페이지가 로드되어 엘리먼트를 인식했다면 n 초가 지나기 전에 다음 코드를 수행하게 된다. 다시 말해 암묵적 대기 시간을 10초로 설정했으나, 페이지가 2초 만에 로드되어 엘리먼트를 식별했다면 루프를 빠져나와 다음 코드를 실행하게 된다는 의미이다.

// 암묵적 대기
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import java.time.Duration;


public class Waitdemo {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
    }
}

Explicit Wait (명시적 대기)

명시적 대기는 대기 시간을 명시적으로 정의할 때 사용하는 Wait의 종류이다.
로드하는데 10~13초 정도 소요되는 특정 페이지가 있다고 가정해보자. 이 페이지를 위해 암묵적 대기 시간을 전역적으로 15초로 설정하게 되면 테스트 케이스는 성공하겠지만 좋은 구현 방법이 아니다.

그 첫 번째 이유로는 테스트 수행 시간이 늘어나게 된다. 특정 엘리먼트를 찾는 10개의 테스트 케이스가 존재한다고 가정해보자. 만약, 10개의 테스트 케이스가 모두 실패하는 경우라면 15초 * 10 = 150초의 테스트 시간이 소요된다. 이처럼 암묵적 대기는 전역적으로 선언하여 사용하는 방식이기 때문에 테스트 케이스가 늘어나면 늘어날수록, 실패하는 케이스가 많으면 많을수록 더 많은 시간을 소모하게 된다.

두 번째, 성능 이슈를 필터할 수 없다. 100개의 페이지 중 99개의 페이지는 5초 이내에 로드되어야 하는 페이지이고 1개의 페이지만 10~13초 정도 소요되는 페이지라고 가정해보자. 후자의 테스트케이스를 위해 암묵적 대기를 15초로 설정해버리면 나머지 99개의 페이지의 로드 시간이 늘어났을 때 성능 이슈를 탐지할 수 없다.

이런 상황에서 활용할 수 있는 Wait의 종류가 바로 명시적 대기이다. 명시적 대기는 특정 요소, 특정 시나리오를 타겟팅하여 대기 시간을 설정할 수 있다. 예를 들어 "A"라는 엘리먼트를 찾는데 15초 정도 소요된다고 가정해보면 이 요소, 이 시나리오에만 최대 15초의 대기 시간을 줄 수 있다는 것이다.

Web Driver Explicit Wait

명시적 대기는 크게 두가지 방법으로 분류할 수 있는데, 그중 첫 번째 방법은 웹 드라이버를 활용하는 방법이다. WebDriverWait 객체를 생성하고 loacator를 인자로 넘겨주면 된다.

// 웹 드라이버 명시적 대기
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;


public class Waitdemo {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("span.promoInfo"))).click();
    }
}

Fluent Wait

웹 드라이버 명시적 대기는 코드가 직관적이지만, Fluent Wait는 코드가 매우 지저분하다. 또한 일반적으로 잘 사용하지 않는 방식이라 가볍게 알아보고 넘어가자. Fluent Wait는 엘리먼트를 식별하기까지 최대 대기하는 시간과 엘리먼트를 식별하는 반복 주기 등을 정의할 수 있다.

예를 들어, 특정 엘리먼트를 식별하기 위해 최대 30초 동안 대기하는데 5초마다 엘리먼트를 체크하고 싶다면 아래와 같이 코드를 작성하면 된다. 다만 Fluent Wait는 아래 예제처럼 코드가 지저분해지기 때문에 용도에 따라서 적절히 활용하면 될 것 같다.

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

import java.time.Duration;
import java.util.function.Function;


public class Waitdemo {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(Duration.ofSeconds(30))
                .pollingEvery(Duration.ofSeconds(5))
                .ignoring(NoSuchElementException.class);

        WebElement e = wait.until(new Function<WebDriver, WebElement>() {
            @Override
            public WebElement apply(WebDriver driver) {
                return driver.findElement(By.cssSelector("span.promoInfo"));
            }
        });
    }
}

Thread.Sleep(Time.sleep)

Thread.Sleep(Time.sleep)은 프로그래밍 언어에서 지원하는 Sleep 메서드를 통해 스크립트를 일정시간 동안 정지하는 방식이다. 만약 sleep 시간을 10초로 주었다면 3초만에 엘리먼트가 등장했음에도 무조건 10초를 기다리게 된다. 따라서 권장되는 방식은 아니다.

profile
두나무 업비트 QA 엔지니어
post-custom-banner

0개의 댓글