1. 程式人生 > 實用技巧 >Java+Selenium做UI自動化中@FindBy和@CacheLookup用法【多測師_王sir】

Java+Selenium做UI自動化中@FindBy和@CacheLookup用法【多測師_王sir】

一、@FindBy和@CacheLookup用法
程式碼例項

package page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class BDPage {
    @FindBy(id="kw")
    @CacheLookup
    
public WebElement keyword_input; @FindBy(id="su") @CacheLookup public WebElement search_button; public BDPage(WebDriver driver){ PageFactory.initElements(driver, this); } } 元素宣告的寫法,這三行是一個整體: @FindBy(id="kw") @CacheLookup public WebElement keyword_input; 註解: @FindBy:這個定義了你所查詢的元素是以什麼方式 定位的,比如圖中我用的是id,那麼就寫成 @FindBy(id
=”kw”),
還有其他幾種寫法:@FindBy(name=”xx”)、@FindBy(className=”xx”)、@FindBy(xpath=”xxx”)、@FindBy(css=”xxx”)等 @CacheLookup:意思是說找到元素之後將快取元素,重複的使用這些元素,將使測試的速度大大加快。 WebElement keyword_input:就是變數名 二、PageFactory public BDPage(WebDriver driver){ PageFactory.initElements(driver,
this); } PageFactory是為了支援頁面設計模式而開發出來的,它的方法在selenium.support庫裡面。 它提供初始化頁面元素的方法,如果頁面存在大量的AJAX的技術,只要頁面更新一次,它就好重新查詢一次元素,所以不
會出現StaleElementException這個error, 頁面設計模式,可以提供你一個介面,然後你在這個介面上面,構建你自己專案中的頁面物件,使用PageFactory使得測
試更簡單,更少的程式碼編寫。 如果@FindBy沒有指定,它會預設的查詢id的屬性,然後是name屬性,如果還沒有找到就會報錯。 如果這個元素存在,
我們不用擔心它, pageFactory會初始化這個元素,不會報任何錯誤。 二、selenium流行的設計模式page object selenium目前比較流行的設計模式就是page object,那麼到底什麼是page object呢,簡單來說,就是把頁面作為物件,
在使用中傳遞頁面物件,來使用頁面物件中相應的成員或者方法,能更好的提現java的面向物件和封裝特性。而使用時間長了
會發現該模式也存在一點問題,那就是元素每次都要獲取,並且獲取元素與頁面方法不分離,增加程式碼冗餘度,用過springMVC框架
的人都知道,註解方式的開發會大大增加開發效率,使頁面變得整潔。 本次要介紹的就是pageFactory 設計模式,什麼是pageFactory 設計模式呢? 準確來說就是在page object模式基礎上更好的利用了面向物件的思維,將獲取元素與操作頁面的方法進行分離,以前獲取
元素要findelementbyid等等,現在只要一個註解就可以搞定,並且再次跑自動化迴歸測試時候,程式碼有獲取快取的特性,
所以會比第一次跑的快,只要id,name不變。
1.首先介紹FindBy類: For example, these two annotations point to the same element: @FindBy(id = "f") WebElement f; @FindBy(how = How.ID, using = "f") WebElement f; and these two annotations point to the same list of elements: @FindBy(tagName = "a") List<WebElement> links; @FindBy(how = How.TAG_NAME, using = "a") List<WebElement> links; 用來分別查詢單個元素和多個元素的兩種用法,支援的型別有:className、css、id、linkText、name、
partialLinkText、tagName、xpath。 How支援的型別和上面差不多。
2.接著介紹PageFactory類 Factory class to make using Page Objects simpler and easier. 它提供的方法都是靜態的,可以直接呼叫,我們在用完findby後,需要進行元素初始化,則需要呼叫下面的方法 initElements(ElementLocatorFactory factory, java.lang.Object page)、initElements(FieldDecorator
decorator, java.lang.Object page)、initElements(WebDriver driver, java.lang.Class
<T> pageClassToProxy)、
initElements(WebDriver driver, java.lang.Object page) 我們在實際使用中可以這樣用: PageFactory.initElements(dr, XXX.
class); 或者 PageFactory.initElements(new AjaxElementLocatorFactory(dr, 10) ,XXX.class); 後者加入了初始化元素時等待時間。 3.下面給大家簡單用個例子介紹我的設計模式。 public class BasePage { WebDriver driver; private final int TIMEOUT=3; public BasePage(WebDriver driver ) { this.driver=driver; PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT) , this); } public BasePage(WebDriver driver,final String title) { this.driver=driver; WebDriverWait wait=new WebDriverWait(driver, TIMEOUT); try{ boolean flag = wait.until(new ExpectedCondition<Boolean>(){ @Override public Boolean apply(WebDriver arg0) { // TODO Auto-generated method stub String acttitle = arg0.getTitle(); return acttitle.equals(title); }}); }catch(TimeoutException te) { throw new IllegalStateException("當前不是預期頁面,當前頁面title是:" + driver.getTitle()); } PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT) , this); } 這是我的基礎頁面,以後任何頁面都繼承該頁面,因為判斷UI層次的頁面標題。 2.登入頁面 public class LoginPage extends BasePage { @FindBy(id="ele_active_close") @CacheLookup private WebElement wd; @FindBy(id="at_index_login-box_mobile") @CacheLookup private WebElement inputusername; @FindBy(id="at_index_login-box_password") @CacheLookup private WebElement inputpassword; @FindBy(id="at_index_login-box_p_forget_login") @CacheLookup private WebElement mybutton; public LoginPage(WebDriver driver) { // TODO Auto-generated constructor stub super(driver); } public LoginPage(WebDriver driver, String title) { super(driver, title); // TODO Auto-generated constructor stub } //不設定homepage型別不行,因為返回的是這個物件 必須是這個型別 public HomePage login(){ JbClose(); username(""); password(""); mybutton(); return new HomePage(driver,"xxx); } public void username(String username) { inputusername.clear(); inputusername.sendKeys(username); } public void password(String password) { inputpassword.clear(); inputpassword.sendKeys(password); } public void mybutton() { mybutton.click(); } public void JbClose() { wd.click(); } } 3.登入後要進入什麼頁面 public class HomePage extends BasePage{ public HomePage(WebDriver driver) { super(driver); // TODO Auto-generated constructor stub } public HomePage(WebDriver driver,String title) { super(driver,title); } } 4.下面就是main方法了,實際中建議和testng混合使用 public class TestFactory { public static void main(String[] args) { WebDriver driver=new ChromeDriver(); driver.get("http://petrocoke-web-test.obaymax.com/"); String logintitle="xxx"; LoginPage lg=new LoginPage(driver, logintitle); HomePage hm=lg.login(); System.out.println("測試結束"); driver.quit(); } } 三、selenium之設計模式POM https://blog.csdn.net/u011541946/article/details/75393386 https://me.csdn.net/u011541946 前面介紹了POM的優點和非POM方式寫指令碼,這篇介紹利用頁面工廠類(page factory)去實現POM,
通過檢視PageFactory類,我們可以知道它是一個初始化一個頁面例項的功能,在例項化該頁面物件時候,
也會一起例項化該頁面的元素定位。直接來看看京東登入的例子,如果用POM實現,在測試指令碼中實際程式碼就2行。
1.在pageObjects包新建一個京東主頁類,程式碼如下 package pageObects; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; public class JdHomePage { // 元素定位 //登入連結 @FindBy (id="ttbar-login") WebElement login_link; //賬戶登入 @FindBy (xpath="//*/div[@class='login-form']/div[2]/a") WebElement login_withAccount; //輸入使用者名稱框 @FindBy (id="loginname") WebElement inputBox_username; //輸入密碼 @FindBy (id="nloginpwd") WebElement inputBox_password; //登入按鈕 @FindBy (id="loginsubmit") WebElement login_submitBtn; // 業務邏輯和操作方法 //登入方法 public void login(String username, String password){ login_link.click(); login_withAccount.click(); inputBox_username.sendKeys(username); inputBox_password.sendKeys(password); login_submitBtn.click(); } } 2.在testSuites包下新建一個測試類 package testSuites; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.PageFactory; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import pageObects.JdHomePage; public class TestWithPOM { WebDriver driver; @BeforeClass public void setUp() throws Exception{ System.setProperty("webdriver.chrome.driver", ".\\Tools\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://www.jd.com/"); Thread.sleep(2000); } @Test public void testLogin(){ JdHomePage hp = PageFactory.initElements(driver, JdHomePage.class); hp.login("user1", "123456"); } } 處理開啟瀏覽器和開啟京東主頁操作,實際測試登入的程式碼就2行對不對。這裡我們藉助了PageFactory類的方法,在初始化一
個頁面類的時候,也會一起把該頁面定義的元素定位也會初始化,然後通過頁面物件呼叫頁面類的頁面操作方法。這種方式,我們把元素
定位和業務邏輯操作都寫在了頁面物件類中,測試指令碼類,直接呼叫頁面類的方法,這樣的測試指令碼看起來很簡潔,方便閱讀和維護,如果
登入相關文案發生變更,我們只需要去改登入對應頁面的元素定位和業務邏輯,不需要修改這個登入測試類。