Cách xử lý Stale Element Reference Exception trong selenium

Lỗi này xảy ra khi nào?

  • Lúc đầu bạn tương tác vào DOM của trang web, selenium lưu lại reference đến element đó. Ví dụ: x --> WebElement A , x ở đây là reference.
  • Khi trang web của bị refresh thì DOM được tạo lại, dẫn đến tình trạng, reference bị stale (hỏng, ôi thiu, từ stale này hay dùng cho đồ ăn), có nghĩa là reference x này không trỏ đến WebElement A mới mà đang trỏ vào cái WebElement A cũ.
  • Khi bạn dùng x như click() hoặc getText() thì có nghĩa bạn đang trỏ vào thằng WebElement A cũ –> bị Stale Element Reference Exception.

Các cách để fix lỗi này:

I. Thêm wait time

  • Hãy đợi 1 khoảng thời gian, ví dụ: Thread.sleep(3000) –> đợi 3s
  • Rồi get lại Element mà mình muốn tương tác:
    • var name = driver.getElement(username).getText();

Cách này có điểm dở là:

  • Có khi thời gian đợi không đủ, có khi 2s, có khi là 5s. Khi nó chỉ cần 2s mà mình đợi 3s thì đợi thừa mất 1s, còn khi nó cần đến 5s mà mình chỉ đợi 3s sẽ vẫn bị Stale Element Reference Exception

II. Kết thúc hành động ở trạng thái ready

  • Khi 1 hành động tương tác với DOM, hãy đợi đến khi trang web refresh xong, hoàn thành việc render.

Ví dụ:

  • Click button A –> refresh 1 phần của trang web –> hãy đợi đến khi 1 Element nào đó thay đổi trạng thái, đừng wait chính cái element mà đang bị Stale Element Reference Exception. Giả sử bạn đang muốn lấy Item Two đừng kiểm tra chính Item Two mà hãy dùng Text X
Trước khi click vào button A
Sau khi click button A
@Test
void checkItemTwo(){
   clickA();
   wait.util(ExpectedConditions.invisibilityOfElementLocated(TextX));
   getItemTwo();
}

Vì mục tiêu là để web ở trạng thái ready sau khi 1 hành động được diễn ra, nên wait kia nên đặt vào trong method clickA().

@Test
void checkItemTwo(){
   clickA();
   getItemTwo();
}


void clickA(){
   ...
   wait.util(ExpectedConditions.invisibilityOfElementLocated(TextX));
}

III. Retry đến khi tương tác được thì thôi.

Flow có thể như sau:

  • Get Item Two, nếu bị StaleElementReferenceException thì tiếp tục get lại thêm 1 lần nữa, giữa 2 lần tương tác sẽ đợi tầm 500ms. Hết n lần retry mà không được khi throw ra RuntimeException.
public String retryGetText(By by) {
    int attempts = 0;
    while (attempts < 5) {
        try {
            return driver.findElement(by).getText();
        } catch (StaleElementReferenceException e) {}
        attempts++;
        waitIn(500);
    }
    throw new RuntimeException("Cannot get text from element: " + by);;
}

private void waitIn(long mili){
    try {
        Thread.sleep(mili);
    } catch (Exception ignored) {}
}

IV. Tổng kết

Trên đây là 1 vài cách để xử lý Stale Element Reference Exception, nếu nó vẫn không work thì bạn nên kết hợp các cách này với nhau. Đây là nỗi nhức nhối của các ace tester, hi vọng bài viết có ích, chứ mình đi fix dạo lỗi này cũng thấy mệt. T__T

5 2 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments