Cucumber java + Webdriver (7) 结合Page Object,使用LoadableComponent

8 篇文章 2 订阅
8 篇文章 0 订阅
进行页面自动化过程中,页面间的跳转经常是比较痛苦的。

1、未使用LoadableComponent前的做法

比如我们经常需要写一些js的代码来判断页面是否加载完整

如:
JavascriptExecutor je=(JavascriptExecutor) driver;
                final String docstate=(String) je.executeScript("return document.readyState");
                ExpectedCondition<Boolean> ec = new ExpectedCondition<Boolean>() {
                    @Override
                    public Boolean apply(WebDriver d) {
                        return (docstate.equals("complete"));
                    }
                };

但这样只是说明页面加载好了,所以这样写也是不能保证页面的元素是可见、可点击等所需要的特性
一般情况下我们可以使用wait来解决该问题
如:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                    .withTimeout(30, TimeUnit.SECONDS)
                    .pollingEvery(500, TimeUnit.MILLISECONDS)
                    .ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.presenceOfElementLocated(by));
wait.until(ExpectedConditions.visibilityOfElementLocated(by));

但是这个对于想用一个通用的方法来评估页面加载状态,却不是最好的方法

2、使用LoadableComponent

则我们可以使用LoadableComponent,它是selenium的一个基础类,为我们提供了一个加载页面的标准方式
下面我们修改以前写的BaiduHome_page.java
首先,让类继承LoadableComponent

这里我们需要实现两个方法: load() 和 isLoaded()
load()方法中的代码一般是用来写跳转到某个页面,如driver.get(url)
isLoaded() 方法中的代码一般是用来验证页面是否加载完成并成功
则该类的代码改为

import com.helpermethods.PageLoad;
import org.openqa.selenium.*;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.*;

import java.util.concurrent.TimeUnit;

public class BaiduHome_page extends LoadableComponent<BaiduHome_page> {

    public WebDriver driver;

    public BaiduHome_page(WebDriver driver,String Url){
        this.driver = driver;
        PageFactory.initElements(driver, this);
        driver.get(Url);
    }

    @Override
    protected void load() {
    }

    @Override
    protected void isLoaded() throws Error {
        
        System.out.println("=====判断BaiduHome_page是否加载完成=====");

        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(500, TimeUnit.MILLISECONDS)
                .ignoring(NoSuchElementException.class);

        wait.until((new ExpectedCondition<Boolean>() {
            @Override
            public Boolean apply(WebDriver driverObject) {
                System.out.println("Waiting BaiduHome_page Dom loading complete\n ");
                return (Boolean) ((JavascriptExecutor) driverObject).executeScript("return document.readyState === 'complete'");
            }
        }));

        if(!PageLoad.myElementIsClickable(this.driver, By.id("kw"))) {
            throw new Error("BaiduHome_page was not successfully loaded");
        }
        System.out.println("*****BaiduHome_page is loading complete*****");
    }

    //百度logo
    @FindBy(xpath="//div[@id='lg']/img")
    private WebElement ElementBaiduLogo;

    //输入框
    @FindBy(id="kw")
    private WebElement ElementBaiduInput;

    //按钮 查询一下
    @FindBy(id="su")
    private WebElement ElementSubmit;


    public WebElement getBaiduLogo(){
        return ElementBaiduLogo;
    }

    //获取当前页面title
    public String getPageTitle(){
        return driver.getTitle();
    }

    // 输入查询内容,并点击查询按钮
    public void enterSearch(String searchText){
        WebDriverWait wait = new WebDriverWait(driver,30);
        wait.until(ExpectedConditions.elementToBeClickable(ElementBaiduInput));
        ElementBaiduInput.clear();
        ElementBaiduInput.sendKeys(searchText);
    }

    // 输入查询内容,并点击查询按钮
    public void submit(){
        WebDriverWait wait = new WebDriverWait(driver,30);
        wait.until(ExpectedConditions.elementToBeClickable(ElementSubmit));
        ElementSubmit.click();
    }
}


其中myElementIsClickable() 方法是为了验证页面是否真的加载成功。当做一种通用的方法来判断页面加载完成后必须存在某个指定的元素

该方法的代码如下(在com目录下新建helpermethods,之后在该目录下新建PageLoad.java):

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class PageLoad {
    public static boolean myElementIsClickable (WebDriver driver, By by) {
        try
        {
            new WebDriverWait(driver,30).until(ExpectedConditions.elementToBeClickable(by));
        }
        catch (WebDriverException ex)
        {
            return false;
        }
        return true;
    }
}
另外在BaiduHome_page类中,可发现load()里面没有写任何代码,这是因为对于大部分应用程序来说,页面的跳转一般是通过触发某个动作完成的,而不是直接跳到某个页面
 但在应用程序的首个页面中,会把driver.get(url)写在页面的构造方法中。因为这样的话,我们就不必在跳转页面前,先等待isload()超时然后在执行driver.get(url)

 则在使用时,需要new BaiduHome_page(driver).get()
 其中get()方法的内部实现是这样的:

public T get() {
    try {
        isLoaded();
        return (T) this;
    } catch (Error e) {
        load();
    }
  
    isLoaded();
  
    return (T) this;
}
可看到是先调用isLoaded()来判断页面是否如预期一样的加载成功,如果没有加载成功,则调用load()来加载页面,之后再调用isLoaded()查看页面是否加载成功

3、修改类BaiduSearchStepfs.java

注意和之前代码的差别,即修改的地方

import com.BaiduHome_page;
import com.cucumber.config.ConfigManager;
import com.cucumber.utl.SharedDriver;
import cucumber.api.PendingException;
import cucumber.api.java.en.And;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.junit.Assert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;


import java.util.concurrent.TimeUnit;

public class BaiduSearchStepfs {

    private final WebDriver driver;
    private final ConfigManager config;
    private BaiduHome_page baiduHome_page;
    private static String baseUrl;

    public BaiduSearchStepfs(SharedDriver driver, ConfigManager config) {   //这里删除了BaiduHome_page的初始化,改放到下面去
        this.driver = driver;
        this.config = config;
    }

    @Given("^Go to baidu home$")
    public void go_to_baidu_home() throws Exception {
        baseUrl = this.config.get("base_path");
        baiduHome_page = new BaiduHome_page(driver,baseUrl);  //新增
        baiduHome_page.get();  //新增
    }

    @When("^I find baidu logo")
    public WebElement i_find_baidu_logo() {
        WebElement element = this.baiduHome_page.getBaiduLogo();
        return element;
    }

    @And("^Type the search text \"([^\"]*)\"$")
    public void type_the_search_text(String searchText) throws Throwable {
        this.baiduHome_page.enterSearch(searchText);
    }

    @And("^Click the submit$")
    public void click_the_submit() {
        this.baiduHome_page.submit();
    }

    @Then("^Wait the query result")
    public void wait_the_query_result() throws InterruptedException {
        Thread.sleep(10000);    //后面可以用显示等待或者隐示等待来优化代码
        Assert.assertEquals("selenium_百度搜索", this.baiduHome_page.getPageTitle());
    }
}
 

4、其他则不做任何修改,运行cucumber代码

可看到新添加方法打印出来的日志信息,如图所示



则上述就是使用LoadableComponent的一个简易例子

官网也有例子:https://github.com/SeleniumHQ/selenium/wiki/LoadableComponent

在官网中也有介绍了LoadableComponent的高级用法,可以具体看是否需要使用这个高级用法,则《页面嵌套》


该文档参考,这些链接有的如果打不开则是需要翻墙才能查看:

http://www.ontestautomation.com/using-the-loadablecomponent-pattern-for-better-page-object-handling-in-selenium/

http://blog.wedoqa.com/2014/10/simple-and-advanced-usage-of-loadablecomponent/

http://www.johnantony.com/using-selenium-to-test-tumblr/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值