在selenium中使用AjaxElementLocatorFactory来优化PO模式

2644 篇文章 26 订阅
2322 篇文章 14 订阅

之前看到的一篇对于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的话,该项目可以直接做脚手架使用,写框架的同学可以参考。


资源分享

下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Selenium PO(Page Object)设计模式是一种自动化测试的最佳实践,它将页面对象封装在一个类,使测试代码更加模块化、可读性更高、易于维护。下面是一个简单的Selenium PO设计模式的例子: ```python from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class LoginPage: def __init__(self, driver): self.driver = driver self.username_input = (By.ID, 'username') self.password_input = (By.ID, 'password') self.login_button = (By.ID, 'login-button') self.error_message = (By.ID, 'error-message') def enter_username(self, username): WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.username_input)) self.driver.find_element(*self.username_input).send_keys(username) def enter_password(self, password): WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.password_input)) self.driver.find_element(*self.password_input).send_keys(password) def click_login_button(self): WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable(self.login_button)) self.driver.find_element(*self.login_button).click() def get_error_message(self): WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.error_message)) return self.driver.find_element(*self.error_message).text ``` 在这个例子,我们定义了一个名为LoginPage的类,它包含了登录页面的所有元素和操作。在类的构造函数,我们使用Selenium的By类来定义了页面元素的定位方式,例如ID、CSS选择器等。然后,我们定义了一些方法来操作这些元素,例如输入用户名、输入密码、点击登录按钮等。在每个方法,我们使用Selenium的WebDriverWait类来等待元素的出现或可点击,以确保测试的稳定性和可靠性。 使用Selenium PO设计模式,我们可以将测试代码和页面元素分离开来,使测试代码更加清晰、易于维护。同时,我们还可以将页面元素的定位方式封装在类,以便于修改和维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值