優秀的框架都有屬於自己的思想,在搭建web自動化測試框架時,我們通常都遵循 PO(Page Object)思想。
簡單理解就是我們會把每個頁面看成一個物件,一切皆物件,物件導向編碼,這樣會讓我們更好的解耦程式碼,也更好的進行封裝和理解。
使用selenium框架來操作頁面時,最常用的都是一些點選,輸入內容,頁面切換等方法,如果每個頁面我們都要寫一遍這樣的操作程式碼,重複性高,程式碼冗餘。所以我們一般都會把這些共性的操作提取成一個基礎類:BasePage。
以下是對該類的簡單封裝,還有其他的方法歡迎大家留言補充:
BasePage類:
import com.ggf.selenium.taxcp.utils.BrowserUtil;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.util.Set;
/**
* @Description: 頁面基礎類,將公共方法提取出來,如:獲取元素內容,點選,等待。。。
* @Author: ggf
* @Date: 2021/05/15
*/
public class BasePage {
/**
* 對元素進行點選
* @param by 定位資訊
*/
public void click(By by) {
waitElementClickable(by).click();
}
/**
* 對元素輸入內容
* @param by 定位資訊
* @param datas 輸入的內容
*/
public void sendKeys(By by, String datas) {
waitElementVisible(by).sendKeys(datas);
}
/**
* 清除元素內容
* @param by
*/
public void clear(By by) {
waitElementVisible(by).clear();
}
/**
* 判斷元素是否存在。
* 使用isDisplayed() 方法,該方法判斷某個元素是否在頁面中存在,包含了:
* visibility=hidden 或 display=none 時,只要在HTML程式碼中存在,
* 就會返回true。
* 擴充套件:
* isEnable()-->用於判斷input、select等元素是否可編輯。
* isSelected()-->判斷元素是否被選中。
* @param by 定位資訊
* @return 存在:true 不存在:false
*/
public boolean isElementExist(By by) {
return waitElementVisible(by).isDisplayed();
}
/**
* 獲取元素文字內容
* @param by 定位資訊
* @return 返回文字內容
*/
public String getElementText(By by) {
return waitElementVisible(by).getText();
}
/**
* 獲取元素屬性值
* @param by 定位資訊
* @param attributeName 屬性名稱
* @return 返回屬性值
*/
public String getElementAttributeValue(By by, String attributeName) {
return waitElementVisible(by).getAttribute(attributeName);
}
/**
* 等待元素可見,顯式等待10秒。
* @param by 定位資訊
* @return 返回element物件
*/
public WebElement waitElementVisible(By by) {
WebDriverWait webDriverWait = new WebDriverWait(BrowserUtil.getDriver(),10);
return webDriverWait.until(ExpectedConditions.visibilityOfElementLocated(by));
}
/**
* 等待元素可點選,顯式等待10秒。
* @param by 定位資訊
* @return 返回element物件
*/
public WebElement waitElementClickable(By by) {
WebDriverWait webDriverWait = new WebDriverWait(BrowserUtil.getDriver(), 10);
return webDriverWait.until(ExpectedConditions.elementToBeClickable(by));
}
/**
* 等待iframe可見並且根據By切換到iframe框架中
* @param by 元素定位資訊
*/
public void waitIframeAndSwitch(By by) {
WebDriverWait webDriverWait = new WebDriverWait(BrowserUtil.getDriver(), 10);
webDriverWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(by));
}
/**
* 等待iframe可見並且根據名稱切換。
* @param frameName iframe名稱
*/
public void waitIframeAndSwitch(String frameName) {
WebDriverWait webDriverWait = new WebDriverWait(BrowserUtil.getDriver(), 10);
webDriverWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frameName));
}
/**
* 滑動列表找元素並且進行點選
* @param selectedText 選中元素文字
* @param by 正在載入類似元素的定位表示式
* @throws InterruptedException
*/
public static void clickElementInList(String selectedText, By by) throws InterruptedException {
// 滑動之前的頁面原始碼資訊
String beforeSource = "";
// 滑動之後的頁面原始碼資訊
String afterSource = "";
// 獲取webdriver
WebDriver driver = BrowserUtil.getDriver();
// 迴圈條件
// 1、找到了元素,跳出迴圈
// 2、如果沒有找到元素???怎麼跳出迴圈
while (true) {
WebElement webElement = driver.findElement(by);
beforeSource = driver.getPageSource();
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
javascriptExecutor.executeScript("arguments[0].scrollIntoView(0);", webElement);
// 如果當前頁面有想要找的元素,怎麼判斷是否有??--getPageSource
if (driver.getPageSource().contains(selectedText)) {
driver.findElement(By.linkText(selectedText)).click();
break;
}
Thread.sleep(1000);
afterSource = driver.getPageSource();
// 頁面元素沒有變化---滑動到了最底部
if (afterSource.equals(beforeSource)) {
break;
}
Thread.sleep(1500);
}
}
/**
* 滾動到指定元素上的方法
* @param by 定位資訊
*/
public void scrollIntoElement(By by){
WebElement webElement= waitElementVisible(by);
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) BrowserUtil.getDriver();
javascriptExecutor.executeScript("arguments[0].scrollIntoView(0);", webElement);
}
/**
* 根據title切換視窗的方法
* @param title 視窗的標題
*/
public void switchWindowByTitle(String title){
WebDriver driver = BrowserUtil.getDriver();
Set<String> handles = driver.getWindowHandles();
// 切換視窗的方式--迴圈遍歷handles集合
for (String handle : handles) {
//判斷是哪一個頁面的控制程式碼??--根據什麼來判斷???title
if(driver.getTitle().equals(title)){
break;
}else{
//切換視窗--根據視窗標識來切換
driver.switchTo().window(handle);
}
}
}
/**
* 根據url內容切換視窗的方法
* @param urlFlag 視窗的標題
*/
public void switchWindowByUrl(String urlFlag){
WebDriver driver = BrowserUtil.getDriver();
Set<String> handles = driver.getWindowHandles();
for (String handle : handles) {
//根據url內容判斷控制程式碼
if(driver.getCurrentUrl().contains(urlFlag)){
break;
}else{
//切換視窗
driver.switchTo().window(handle);
}
}
}
}
BrowserUtil類:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
/**
* @Description: 瀏覽器工具類,控制瀏覽器的生命週期,瀏覽器啟動,關閉
* @Author: ggf
* @Date: 2021/05/15
*/
public class BrowserUtil {
/**
*為解決多執行緒問題,通過ThreadLocal機制來控制
*/
private static ThreadLocal<WebDriver> threadLocal = new ThreadLocal<WebDriver>();
/**
* 通過傳入不同的瀏覽器名稱,獲取瀏覽器驅動
* @param driverType 不同的瀏覽器 chrome ie Firefox
*/
public static void setDriverType(String driverType) {
// 判斷輸入內容是否為空。
if (driverType != "" && driverType != null) {
// 建立不同的瀏覽器驅動
if ("chrome".equalsIgnoreCase(driverType)) {
ChromeDriver chromeDriver = new ChromeDriver();
setDriver(chromeDriver);
}else if ("ie".equalsIgnoreCase(driverType)) {
InternetExplorerDriver ieDriver = new InternetExplorerDriver();
setDriver(ieDriver);
}else if ("firefox".equalsIgnoreCase(driverType)) {
FirefoxDriver fireDriver = new FirefoxDriver();
setDriver(fireDriver);
}
}
}
/**
* 從執行緒ThreadLocal中獲取物件
* @return
*/
public static WebDriver getDriver() {
return threadLocal.get();
}
/**
* 設定物件到ThreadLocal中
* @param driver
*/
public static void setDriver(WebDriver driver) {
threadLocal.set(driver);
}
/**
* 關閉瀏覽器
*/
public void closeBrowser() {
getDriver().close();
}
}