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); }
以上,詳細介紹了硬性等待、隱式等待、只能等待、頁面加載超時、異步腳本超時的常用方法。希望給大家帶來幫助。