본문 바로가기
javascript

Protractor 제어 흐름 사용 안 함 처리

by it-square 2022. 1. 19.

selenium webdriver

 

반응형

맥락
사용자가 protractor에 대해 작성하는 JS 코드는 비동기적으로 실행됩니다(순서는 아님). 이전 명령이 실행될 때까지 대기하면서 특정 흐름을 따를 수 있는 사양이 필요하기 때문에 자동화 용도로는 사용할 수 없습니다. 이 작업은 protractor ControlFlow에서 처리합니다.

ControlFlow
ControlFlow는 Selenium Promise Manager를 기반으로 합니다. 백그라운드에서 getText(), findElement(), sendKeys(), click() 등과 같이 브라우저와 상호 작용하는 각 호출이 예약되어 ControlFlow 대기열에 푸시됩니다. 그러한 모든 통화는 약속으로 취급된다. 이렇게 하면 약속 체인을 위해 .then()과 같은 것을 사용하는 것에 대해 걱정할 필요가 없습니다.

예를 들어...

browserUtils.waitForPresenceOf(request.button).then(done => {
   request.button.click();
});
 

다음과 같이 쓸 수 있다.

browserUtils.waitForPresenceOf(request.button);
request.button.click();

코드 리팩터링
ControlFlow는 잘 작동하지만 기본적으로 Selenium Promise Manager의 래퍼입니다. 그리고 promise manager가 최신 버전의 selenium(v4.0.0-alpha.1)에서 더 이상 사용되지 않으므로 protractor의 ControlFlow도 마찬가지입니다. 가장 좋은 시나리오는 의존성이 없도록 ControlFlow에서 완전히 마이그레이션하는 것입니다. 이를 해제하기 위해 우리는 protractor config 파일에서 "SELENIUM_PROMISE_MANAGER: false" 플래그를 설정한다.

거기에 두 가지 문제가 있다.

  • 모든 약속은 수동으로 처리해야 합니다. - Async/Await 사용: 이미 이 작업을 수행하고 있을 수 있지만 그렇지 않다면 이전 학교 약속 체인을 사용하지 말고 비동기/Await를 사용하여 코드를 동기화하는 것이 좋습니다. 그것은 여러분의 삶을 훨씬 더 쉽게 만들어 줄 것입니다!
  • 약속 거부 수동 처리 - 비동기 방식을 사용하더라도 거부된 약속은 여전히 몇 가지 문제를 일으킵니다. 테스트는 정상적으로 실행되지만 앞으로는 원래 ControlFlow에서 처리했던 StaleElementReference와 같은 예외와 NoSuchElementError와 같은 오류를 처리해야 합니다. 우리는 각 약속 후에 .catch()를 사용할 수 있지만, 전체 코드 베이스에 대해 그렇게 하는 것은 불가능합니다. 쉬운 방법은 여러분의 모든 "그것"을 트라이 캐치 블록으로 포장하는 것입니다.*****
    다행히 위에 언급한 에러는 일시적인 것이 아니기 때문에 한 번 처리하면 다시 발생할 가능성이 매우 낮습니다.
  • 처리되지 않은 약속 거부 — 처리되지 않은 약속거부 경고: 처리되지 않은 약속 거부(r 꺼내기 ID: 1): 오류: cmd ENT를 생성합니다.
    [1] (node:4796) 사용되지 않음경고: 처리되지 않은 약속 거부는 더 이상 사용되지 않습니다.
    향후 처리되지 않는 약속 거부는 노드를 종료합니다.
    종료 코드가 0이 아닌 js 프로세스입니다.
 

새 테스트를 작성하는 동안 몇 가지 제안 사항

  • wait Everywhere 사용: 모든 약속 앞에 "await"(예상치도)를 붙입니다. 기다림은 기본적으로 테스트를 위한 신호등과 같은 역할을 합니다. 이렇게 하면 순차 실행이 보장되며 다음 단계마다 체인을 약속할 필요가 없습니다. 그리고 깔끔해 보이고, 코드가 더 읽기 쉽고 디버그하기 쉬워요.

예를 들어 -

await browserUtils.waitForPresenceOf(filters.button);
await this.selectFilter(this.filterOptions);
  1. 모든 기능을 비동기식으로 만듭니다. — 비동기 함수는 함수 호출에서 "await"을 사용할 수 있게 합니다(함수가 비동기 함수가 아니면 사용할 수 없음).
 
this.selectFilter = async filterOptions => {
  // Select filters
};
  1. "SELENIUM_PROMISE_MANAGER: false"를 사용하여 새 사양을 작성하고 테스트합니다. 약속 관리자 없이 사양을 실행하는 것은 처음에는 까다로울 수 있지만, 나중에 ControlFlow에서 완전히 벗어나야 할 경우에 대한 증거가 될 것입니다.

일반적인 문제 및 해결 방법(확대)

흐름을 통제하는 데 몇 가지 문제가 있어

오래된 요소 참조 —

 
  • 비동기적으로 새 페이지를 로드하거나 페이지를 변경하는 항목을 누릅니다.
  • 페이지 로드가 완료되기 전에 즉시 요소를 검색하면 해당 요소를 찾을 수 있습니다!
  • 마침내 페이지가 언로드되고 새로운 페이지가 로드됩니다.
  • 이전에 찾은 요소에 액세스하려고 하지만, 새 페이지에 해당 요소가 포함되었더라도 오래된 요소입니다.

Java 연결 재설정 문제 - 선택기 문제입니다. $$()로 매핑된 요소로 인해 두 개 이상의 css 선택기가 문제가 됩니다. 그렇게 하는 것을 피하도록 하세요.

.then()과 aForEach를 결합하는 것도 문제를 일으키고 있다는 것을 알았습니다. 아무데나 사용하지 마세요.

다음은 유용한 몇 가지 링크입니다.
공식 소개 및 마이그레이션 가이드
제어 흐름을 피하기 위한 비동기/대기

댓글