移動UI自動化-Page Objects Pattern


移動UI自動化,看起來美好,踐行起來卻難。做個目光短見的務實主義者。Page Objects Pattern是Selenium官方推崇的方式,最近研究寫測試用例最佳實踐之Page Objects,同時結合Appium的Java Client簡單介紹下如何寫出靠譜的Page Object。

Page Objects

Page Object定義為抽象web app頁面的一系列對象,通過對頁面功能的封裝,它得到了很多好處:

  • 減少重復代碼
  • 提高測試代碼的可讀性和穩定性
  • 測試代碼易於維護

一個簡單的例子

public class BaiduSearchPage {

	protected WebDriver driver;
        @FindBy(id="kw")
	private WebElement kw;
	private WebElement su;

	public BaiduSearchPage(WebDriver driver) {
		super();
		this.driver = driver;
                PageFactory.initElements(driver, this);
	}

	public void load(String url) {
		driver.get(url);
	}

	public ResultPage search(String key) {
		kw.clear();
		kw.sendKeys(key);
		su.click();
		return new ResultPage(driver);
	}
}

推薦的做法

  • public 方法暴露Page對象的服務
  • WebElement,Driver相關頁面UI細節盡可能隱藏
  • 盡量減少Page對象中的Assertion
  • 到達新的Page,在方法中返回其它Page,甚至同一頁面也可以返回Page做鏈式操作
  • 一個Page對象不需要關注所有細節,只關心需要的對象,需要時再補充
  • 不同的結果,同一個操作可以用不同的方法。

Appium 中使用Page Object Pattern

Appium的Java Client是基於WebDriver的,但有了一些改進。比如元素定位不到,Appium Java Client會將Locator詳細信息拋出,而Selenium沒有。

Wait

移動自動化測試Wait是很關鍵的一個動作,既關乎正確性,也關乎效率,我們應該極力避免使用Thread.sleep()或Sleeper.sleepTight()。Appium的客戶端提供了一個類AppiumFieldDecorator可以很方便的設置ImplicitlyWaitTimeOut。FieldDecorator顧名思義,是Page對象Field的Decorator,PageFactory主要就是在Feild上下功夫,將WebElement類型的Feild使用Proxy方法,創建一個增強的WebElement,這個成員在每次操作時,都會先使用注解的定位策略定位,然后再調用WebElement的方法,當然可以通過CacheLookup注解,來緩存定位結果(盡量不這么做)。

PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), pageObject);

如果等待某個頁面元素是否可見,在PageObject中也更簡單

public static void untilElementVisable(final WebElement element,int timeoutInSeconds){
  new Wait() {
     @Override
     public boolean until() {
	return element.isDisplayed();
     }
   }.wait(String.format("Timed out waiting for %s. Waited %s", 
		  element, timeoutInSeconds), timeoutInSeconds);
}
	

FindBy

在Appium中你會遇到,Selendroid模式和UIAutomator定位差異,比如Selendroid的linkText在UIAutomator中用name,還有就是iOS腳本想和Android共用一份。這在Appium中有了很好的擴充,Appium客戶端會在運行時決定使用哪個Annotation來裝飾WebElement。

    @FindBy(name="text")
    @SelendroidFindBy(name = "text1")
    @iOSFindBy(id="sth")
    private WebElement textSelendroid;

ElementInterceptor

總是有這樣或那樣的原因,需要記錄日志,如果方法的執行每一步都要手寫是很痛苦的,自然我們想到了AOP。在Selenium中EventFiringWebDriver類可以方便的記錄日志,但是在Appium客戶端中,我們可以修改AppiumFieldDecorator中ElementInterceptor來加入自己的日志信息,不過暫時這個功能Appium Client沒有暴露出來,需要自己fork個repo修改下。

參考

http://assertselenium.com/automation-design-practices/page-object-pattern/
https://code.google.com/p/selenium/wiki/LoadableComponent
https://code.google.com/p/selenium/wiki/PageObjects
https://code.google.com/p/selenium/wiki/PageFactory
https://github.com/FluentLenium/FluentLenium
https://github.com/countableSet/webdriver-demo


免責聲明!

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



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