自動化測試--8種定位方式以及等待詳解


1.id--標簽中id 的值

如果開發人員編程規范,頁面的元素id 不重復的且不是動態生成的id時,使用id 定位非常容易。

//<select style="width: 33%" id="CityCode" name="CityCode" class="form-control lopicker">
//使用id定位元素
WebElement element =  driver.findElement(By.id("CityCode"));

2.name--標簽中name的值

//<select style="width: 33%" id="CityCode" name="CityCode" class="form-control lopicker">

//使用name定位元素
WebElement cityelement = driver.findElement(By.name("CityCode"));

3.className--標簽中class屬性的值

 //<select style="width: 33%" id="ProvinceCode" name="ProvinceCode" class="form-control lopicker">
//使用className定位
WebElement element = driver.findElement(By.className("form-control"));

4.tagName--標簽名

//<select style="width: 33%" id="ProvinceCode" name="ProvinceCode" class="form-control lopicker">
//使用標簽名定位元素
WebElement element = driver.findElement(By.tagName("select"));

5.linkText--a標簽中全部的文本值

//<a href="/Competition/Detail/c05a5ae3-32c6-4b81-b042-646ad8de275a" title="尋寶機器人賽" class="link item_title">尋寶機器人賽</a>
    WebElement comElement = driver.findElement(By.linkText("尋寶機器人賽"));

6.partialLinkText--a標簽中部分的文本值

//<a href="/Competition/Detail/c05a5ae3-32c6-4b81-b042-646ad8de275a" title="尋寶機器人賽" class="link item_title">尋寶機器人賽</a>
     WebElement comElement = driver.findElement(By.partialLinkText("尋寶"));

7.CSSSelector--css選擇器(非常重要)

 //<select style="width: 33%" id="ProvinceCode" name="ProvinceCode" class="form-control lopicker">
     WebElement element = driver.findElement(By.cssSelector(".form-control"));
        WebElement element1= driver.findElement(By.cssSelector("select.form-control"));
  /**
       * (有屬性的標簽)非常常用CssSelector:標簽名[屬性名='屬性值'][屬性名='屬性值'][屬性名='屬性值'][屬性名='屬性值']
       */
     //<select style="width: 33%" id="CityCode" name="CityCode" class="form-control lopicker">
    WebElement cityelement = driver.findElement(By.cssSelector("select#CityCode"));
    WebElement cityelement1 = driver.findElement(By.cssSelector("#CityCode"));
    WebElement cityelement2 = driver.findElement(By.cssSelector("select[name='CityCode']"));
    WebElement cityelement3 = driver.findElement(By.cssSelector("select[class='form-control lopicker'][name='CityCode']"));

8.xpath--相對路徑/絕對路徑

使用chrome自帶或者火狐的xpath的插件可以獲得元素的相對或者絕對路徑。

chrome:

 

fireFox:

     //<select style="width: 33%" id="AreaCode" name="AreaCode" class="form-control lopicker">
     //通過單個屬性定位
     WebElement areaElement = driver.findElement(By.xpath("//*[@id=\"AreaCode\"]"));
     //通過多個屬性定位
     WebElement areaElement1 = driver.findElement(By.xpath("//select[@style='width: 33%' and @name='AreaCode']"));

 

    //<a href="/Competition/Detail/c05a5ae3-32c6-4b81-b042-646ad8de275a" title="尋寶機器人賽" class="link item_title">尋寶機器人賽</a>
     //通過contains表達式
     WebElement comElement1 = driver.findElement(By.xpath("//a[@class='link item_title' and contains(text(),'機器人賽')]"));
     //通過startsWith表達式
     WebElement comElement2 = driver.findElement(By.xpath("//a[@class='link item_title' and starts-with(text(),'尋寶')]"));
     //如果讀者的谷歌版本只支持xpath1.0,所以ends-with不能使用
    // WebElement comElement3 = driver.findElement(By.xpath("//a[@class='link item_title' and ends-with(text(),'機器人賽')]"));
     //如果ends-with不支持,可以使用下面方式代替
     WebElement comElement4 = driver.findElement(By.xpath("//a[substring(text(), string-length(text()) - string-length('人賽') +1) = '人賽']"));

 

上面總結了8種定位元素的方法。

下面說明一些特殊情況:

1.id是動態生成的。

這種情況下,可以選擇其他的定位方式。如cssSelector xPath等

如,生成的id總是以register字符串結尾:

<input id="m.f0.menu.f2.volumeTabs.BLOCK_COMMON.tcw.form.register" name="m.f0.menu.f2.volumeTabs.BLOCK_COMMON.tcw.form.register" class="aranea-checkbox" type="checkbox"> </td>

此時,可以通過xpath的方式來查找

driver.findElement(By.xpath("//input[ends-with(@id,'register')]"));

如果這個動態id有規律可循的話,也可以通過id來定位元素。具體就不舉例了。

 

2.可以將查找元素封裝成相應的方法,直接調用。方便添加日志信息。

    /**
     * 查找元素的方法 element
     */
    public WebElement findElementBy(By by) {
        return driver.findElement(by);
    }

    /**
     * 查找多個元素的方法 elements
     */
    public List<WebElement> findElementsBy(By by) {
        return driver.findElements(by);
    }

    /**
     * 查找到多個元素后,繼續向下查找(定位出一個元素這是一堆相同的elements中 選擇 其中方的 一個 然后在這個選定的中 繼續定位
  */
public WebElement getOneElement(By bys, By by, int index) {
    return findElementsBy(bys).get(index).findElement(by);
}

 

3.在查找元素的時候,會考慮到該元素資源是否已經加載完成。

下面給大家總結一下,關於自動化測試中的“等待”:

1.硬性等待---封裝成方法,方便調用。

/**
* 硬性等待,等待時間為:sleepTime。
*/
public void Wait(int sleepTime) {
if (sleepTime <= 0) {
return;
}
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

 

2.隱式等待---這個等待是全局的,是針對當前driver的。一旦設置之后,只要該driver執行findElement或者findElements方法,首先回去找元素,如果沒找到,會在設置的時間內一直輪詢查找,直到timeOut.由於是全局性的,有些元素不需要等待,所以會造成時間的浪費。因為瀏覽器是自上而下渲染的,如果元素1在元素2的上面,當你第一次查找過元素2,之后再查找元素1的時候,是不需要等待的。但是設置了該全局參數之后,還是會去等待。

driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

3.顯示等待(推薦使用)

/**
     * 對外提供智能等待 查找元素的方法
     * @param driver
     * @param time
     * 元素的超時等待時間
     * @param by
     * @return
     */
    public static WebElement waitElement(WebDriver driver,int time,By by) {
        WebElement element=null;
        
        WebDriverWait wait = new WebDriverWait(driver, time);
        
        try {
            element = wait.until(new ExpectedCondition<WebElement>() {

                public WebElement apply(WebDriver driver) {
                    WebElement element = driver.findElement(by);
                    return element;
                }
            });
        } catch (TimeoutException e) {
            System.out.println("元素"+by.toString()+" "+time+"S內未能找到");
            logger.info("元素未找到");
        }
        
        
        return element;
        
    }
    
    /**
     * 對外提供智能等待 查找元素的方法,固定的等待超時時間為5S
     * @param by
     * @return
     */
    public static WebElement waitElement(By by) {
        
        WebDriver driver= GetDriverUtil.getDriver();
        return waitElement(driver, 5, by);
        /*WebElement element = null;
        try {
            element = (new WebDriverWait(driver, 5)).until(new ExpectedCondition<WebElement>() {

                @Override
                public WebElement apply(WebDriver driver) {
                    
                    return driver.findElement(by);
                }

            
            });
        } catch (Exception e) {
            System.out.println("元素"+by.toString()+" "+"5S內未能找到");
            e.printStackTrace();
        }
        
        return element;*/
    }

 上面的ExpectedCondition是我們自己編寫的,實際上,在selenium的ExpectedConditions類中,已經封裝了各種元素等待條件。有興趣可以去了解下

可以去看一下源碼,內部也是使用的匿名內部類new ExpectedCondition{},下面是拿出一個來舉例:

判斷一個元素是否可點擊:

1.該元素在dom中存在

2.該元素可見

3.該元素為enabled

 

  /**
   * An expectation for checking an element is visible and enabled such that you can click it.
   *
   * @param locator used to find the element
   * @return the WebElement once it is located and clickable (visible and enabled)
   */
  public static ExpectedCondition<WebElement> elementToBeClickable(final By locator) {
//匿名內部類
return new ExpectedCondition<WebElement>() { @Override public WebElement apply(WebDriver driver) {
//判斷元素是否可見 WebElement element
= visibilityOfElementLocated(locator).apply(driver); try {
//如果元素可見並且元素生效的話則返回元素
if (element != null && element.isEnabled()) { return element; } return null; } catch (StaleElementReferenceException e) { return null; } } @Override public String toString() { return "element to be clickable: " + locator; } }; }

 

上面總結的是元素的等待,自動化測試用,還有:等待頁面加載的超時時間測試

a.等待頁面加載,設置超時時間。超時之后,不再等待,直接去定位某元素。(需要執行js腳本)

    /**
     *等待頁面加載,設置頁面加載的超時時間,如果規定時間內還未加載完成,則停止加載,並定位指定元素
     * @param driver
     * @param timeout
     * @param by
     */
    
    public static void pageLoad(WebDriver driver,int timeout,String url) {
        try {
            //設置頁面加載超時時間
            driver.manage().timeouts().pageLoadTimeout(timeout, TimeUnit.SECONDS);
            driver.get(url);
        } catch (Exception e) {
            ((JavascriptExecutor)driver).executeScript("window.stop()");
        }
        
        driver.findElement(By.id("user[login]")).sendKeys("feifeifei");
        
    }
    

b.有時加載頁面超時,需要刷新一次,並輸出頁面的加載狀態。(需要執行js腳本)

/***
     * 啟動瀏覽器並打開頁面
     */
    public void launchBrowser(String webUrl, int timeOut) {
        //getDriver()就是上一篇博客中講的 封裝獲取driver的方法
        driver = GetDriverUtil.getDriver();
        try {
            //最大化瀏覽器窗口(已經封裝成方法)
            maxWindow();
            //設置等待頁面加載的時間(已經封裝成方法)
            waitForPageLoading(timeOut);
            //打開瀏覽器指定頁面(已經封裝成方法)
            get(webUrl);
        } catch (TimeoutException e) {
            logger.warn("頁面沒有完全加載出來,刷新重試");
            //刷新頁面
            refresh();
            //創建js腳本執行器
            JavascriptExecutor js = (JavascriptExecutor) driver;
            //執行腳本,描述了文檔的加載狀態. 狀態分為
            //loading document 仍在加載
            //interactive / 互動    文檔已經完成加載,文檔已被解析,但是諸如圖像,樣式表和框架之類的子資源仍在加載
            //complete / 完成   T文檔和所有子資源已完成加載。狀態表示 load 事件即將被觸發。
            
            String status = (String) js.executeScript("return document.readyState");
            //將返回的狀態通過日志打印出來
            logger.info("打印狀態:" + status);
        }

    }

 

    在自動化測試過程中,還經常遇到異步請求的情況,如下圖:


當需要進行異步請求元素的定位時,則需要等待異步腳本執行完成並返回結果。這時需要設置異步腳本的超時時間。
/** setScriptTimeout。異步腳本的超時時間。(封裝成方法,方便調用)webdriver可以異步執行腳本,這個是設置異步執行腳本腳本返回結果的超時時間 */
    public void setScriptTimeout(int timeOut) {
        driver.manage().timeouts().setScriptTimeout(timeOut, TimeUnit.SECONDS);
    }
 
        

 

以上,詳細介紹了硬性等待、隱式等待、只能等待、頁面加載超時、異步腳本超時的常用方法。希望給大家帶來幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM