Some method of ExpectedCondition on Selenium Java

Dahun Yoo·2021년 7월 17일
2

회사 코드를 리팩토링하면서 구글링하면서 얻은 지식을 좀 정리해봅니다...

Explict wait를 사용할 때, 조건을 부여하기 위해 사용하는 ExpectedCondtion 에 대해 알아봅니다.


WebDriverWait.until()

Selenium으로 자동화를 하다보면, 페이지에 Webelement를 찾을 수 없다면서 NoSuchElementException 을 내뱉습니다. 이것은 대부분의 경우 Selenium의 실행속도가 웹페이지의 로딩속도보다 훨씬 빨라서 나타나는 issue이기도 하고, 아니면 정말 조작하고자 하는 element가 어떠한 이유로 웹페이지에 존재하지 않아서 발생합니다.
단순히 로딩속도가 느려서 그런 것이라면, 해당 element가 로딩될때까지 기다려주면 해결됩니다.

이렇게 특정 요소만 확인될때까지 Webdriver에 대기 하라고 지시하는 것을, 명시적 대기(Explict wait) 라고 합니다.

WebDriver driver = new ChromeDriver();
driver.get("https://google.com/ncr");
driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER);
// Initialize and wait till element(link) became clickable - timeout in 10 seconds
WebElement firstResult = new WebDriverWait(driver, Duration.ofSeconds(10))
        .until(ExpectedConditions.elementToBeClickable(By.xpath("//a/h3")));
// Print the first result
System.out.println(firstResult.getText());

위 코드에서는 //a/h3 이라는 xpath를 가진 element를 클릭할 수 있을 때까지, 최대 10초 간 대기하라는 코드가 작성되어있습니다.

이 대기하는 조건에, 어떠한 조건을 넘길 것인지에 대해 일반적으로 사용되는 몇가지 조건들에 대해 준비해놓은 클래스가 ExpectedCondition 입니다.

  • alert is present
  • element exists
  • element is visible
  • title contains
  • title is
  • element staleness
  • visible text

ExpectedCondition

ExpectedCondition 의 메소드의 사용방법으로는 리턴타입으로 크게 3가지로 나뉩니다.

ExpectedCondition WebElement

해당 Webelement의 상태를 확인하고, 찾은 경우라면 해당 WebElement를 리턴합니다.

ExpectedCondition WebDriver

특정 요소를 찾은 다음 WebDriver를 반환합니다.
frameToBeAvailableAndSwitchToIt 와 같이, 특정 iframe 등이 가능한지 확인하고, 가능하면, 스위칭하여 해당 프레임을 반환하는 식입니다.

ExpectedCondition Boolean

특정 조건을 전달하여, 해당 특정 조건을 만족하면, 대기하는 조건이 충족되었다는 식의 판정을 할 수 있습니다.


ExpectedCondition에 대한 설명은 간단하게 여기까지면 될 것 같고, 보통 WebElement를 식별할 때 자주쓰이는 세가지 방법에 대해 기술해봅니다.

ExpectedCondition.visibilityOf(WebElement element)

찾고자하는 Webelement가 페이지상에서 출력되는지를 확인하고, 보이면 해당 WebElement를 리턴합니다.

ExpectedCondition.visibilityOfElementLocated(By locator)

찾고자하는 WebElement의 locator(Id, Class, Css, Xpath 등등)을 전달하여, 조작하는 페이지에 존재하고, 실제로 출력되고 있다면, locator를 이용하여 WebElemenet를 식별하고, 리턴합니다.

ExpectedCondition.presenseOfElementLocated(By locator)

찾고자하는 WebElement의 locator를 전달하여, 조작하는 페이지에 존재한다면, locator를 이용하여 WebElement를 식별하고, 리턴합니다.
단, 존재하는지의 여부만 확인할 뿐, 실제로 화면상에 표시되는지는 체크하지 않습니다.


담당 프로덕트에서 UI의 변경이 있었는데, 기존에 visibilityOf() 로는 locator를 제대로 지정해주어도 식별해내지 못하는 issue가 있었습니다. locator는 제대로 지정해주었고, 화면상에서도 일정한 로딩동작을 포함해서 잘 표시해주고 있었는데 말이죠.
구글링의 결과 위 메소드들의 차이점을 이해할 수 있었고, 저는 visibilityOfElementLocated() 를 이용해 해결할 수 있었습니다.
기존의 visibilityOf() 로 해결할 수 없던 것은 html 페이지 상에 제대로 로딩이 되지 않아서 인게 아닐까 생각하게 되었습니다.


Summary

methodNameDescription
visibilityOf()이미 html document에 element가 존재하고 있는 것을 전제로, 화면 상에 보여지는지 여부를 체크한다.
visibilityOfElementLocated()html document에 element의 존재여부와 함께, 화면 상에 보여지는지의 여부, 둘을 모두 체크한다.
presenceOfElementLocated()html document에 존재하는지 여부만 체크하고, 화면 상에 보여지는지의 여부는 체크하지 않는다.

즉, visibilityOf() 의 동작내용이라면, 저의 코드가 실패했던 것은 html 문서내에도 WebElement가 존재하지 않았기 때문이라고 생각해볼 수 있습니다.

Performance

퍼포먼스는, 설명을 읽어보시면 아시다시피 아래의 순서와 같습니다.
presenceOfElementLocated() > visibilityOf() > visibilityOfElementLocated()


Ref.

profile
QA Engineer