天天看點

在selenium中使用AjaxElementLocatorFactory來優化PO模式

作者:Java網際網路技術棧

PO模式是page object factory設計模式的簡稱,主要是以頁面為次元來聚合一些元素的定位,讓代碼有更好的維護性和重用性,具體細節可以看這裡:https://www.selenium.dev/documentation/test_practices/encouraged/page_object_models。這裡是官方文檔,非常值得精讀。

Page Factory

如果你已經對po很熟悉了,下面的内容可以放心跳過。

下面是最基本的Page Factory套路,本質上是按頁面去封裝元素定位和操作。

public class PageObjectExample {

    private final WebDriver driver;

    public PageObjectExample(WebDriver driver) {
        this.driver = driver;
    }

    public void login(String email, String password) {
        driver.findElement(By.id("email")).sendKeys(email);
        driver.findElement(By.id("password")).sendKeys(password);
        driver.findElement(By.name("next")).click();
    }
}           

上面的代碼隻能說懂得都懂,不過這裡有個問題,在login方法裡,我們頻繁使用 driver.findElement 方法,這會顯得有一些的啰嗦,下面是改進版本,優雅了很多。

public class PageObjectExample {
    
    @FindBy(id = "email")
    private WebElement email;

    @FindBy(id = "password")
    private WebElement password;

    @FindBy(name = "next")
    private WebElement next;

    public PageObjectExample(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void login(String email, String password) {
        this.email.sendKeys(email);
        this.password.sendKeys(password);
        next.click();
    }
}           

這裡要注意的是在進行初始化的時候,需要調用 PageFactory.initElements(driver, this);

本質上這行代碼的作用是将上面的注解@FindBy轉換成基本的 findElement 形式。

參考資料:https://github.com/SeleniumHQ/selenium/wiki/PageFactory

PO模式的常見問題

等待政策。selenium提供了3種測試,分别是顯示,隐式,以及流利等待(fluent wait),一般情況下隐式等待是不推薦的。

在po中,我們會在2種情況下用到等待,分别是初始化po對象時以及在action方法時,action方式其實就是指的包含有元素操作的方法。

初始化時等待

如果操作的對象在頁面加載的時候就會渲染完畢的話,那麼在初始化時等待将會是一個非常好的實踐。總體的實作思路是在初始化時告訴po,我們明确希望等待哪個元素出現,并且最多等待多久。

public class PageObjectExample {

    private WebDriver driver;

    @FindBy(id = "email")
    private WebElement email;

    @FindBy(id = "password")
    private WebElement password;

    @FindBy(name = "next")
    private WebElement next;

    public PageObjectExample(WebDriver driver) {
        this.driver = driver;

        PageFactory.initElements(driver, this);
        new WebDriverWait(driver, Duration.of(5, ChronoUnit.SECONDS))
            .until(ExpectedConditions.visibilityOf(email));
    }

    public void login(String email, String password) {
        this.email.sendKeys(email);
        this.password.sendKeys(password);
        next.click();
    }
}           

上面的代碼中我們希望在初始化頁面對象時,其實也就是在頁面加載的時候明确等待email這個元素出現,逾時時間為5s。

操作時等待

這裡的做法是先等待再操作,比如

public class PageObjectExample {

    private WebDriver driver;

    @FindBy(id = "email")
    private WebElement email;

    @FindBy(id = "password")
    private WebElement password;

    @FindBy(name = "next")
    private WebElement next;

    public PageObjectExample(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void fillEmail(String email) {
        new WebDriverWait(driver, Duration.of(5, ChronoUnit.SECONDS))
            .until(ExpectedConditions.visibilityOf(this.email));
        
        this.email.sendKeys(email);
    }
}           

其實就是把等待的代碼換了個位置而已。

簡化等待操作

上面的方式可以運作得很好,不過還是有點太啰嗦了,下面的做法可以緩解一下

• 在 PageFactory.initiElements 中調用 AjaxElementLocatorFactory 方法,這樣可以無腦等待; • 繼承PageFactory.initiElements方法,這樣子類裡就不用反複寫了

下面是基本的代碼

public class PageObjectExample {

    private WebDriver driver;

    // WebElements ignored

    public PageObjectExample(WebDriver driver) {
        PageFactory.initElements(new AjaxElementLocatorFactory(driver, 5), this);
    }
}           

使用繼承來簡化代碼

public abstract class AbstractPageObject {

    private WebDriver driver;
    
    protected AbstractPageObject(WebDriver driver) {
        PageFactory.initElements(new AjaxElementLocatorFactory(driver, 5), this);
    }
}

public class PageObject extends AbstractPageObject {

    // WebElements ignored

    protected PageObject(WebDriver driver) {
        super(driver);
    }

   // action steps ignored
}           

總結

大家可以通過https://github.com/eliasnogueira/selenium-java-lean-test-architecture這個項目來熟悉上面的概念,如果你使用java的話,該項目可以直接做腳手架使用,寫架構的同學可以參考。

繼續閱讀