基於Appium的自動化case開發及case分層結構設計


基於Appium的自動化case開發及case分層結構設計

首先為每條case創建一個公共的基類AppiumTestBase,內含setup和teardown兩個方法,以后每條case繼承該基類即可。代碼如下:

public class AppiumTestBase { public WebDriverWait webwait; private AndroidDriver driver; @Before public void setUp() throws Exception { File classpathRoot = new File(System.getProperty("user.dir")); File appDir = new File(classpathRoot, "apps"); File app = new File(appDir, Config.CURRENT_BANK); DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability("deviceName",Config.DEVICE_NAME); capabilities.setCapability(CapabilityType.BROWSER_NAME, ""); capabilities.setCapability(CapabilityType.VERSION, "5.0.1"); capabilities.setCapability("platformName", "android"); capabilities.setCapability("app", app.getAbsolutePath()); capabilities.setCapability("udid", Config.DEVICE_NAME);//adb devices獲得的值 driver = new AndroidDriver(new URL("http://127.0.0.1:"+Config.APPIUM_PORT+"/wd/hub"), capabilities); webwait = new WebDriverWait(driver,10); DriverManager.init(driver); DriverManager.initWebWait(webwait); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @After public void tearDown() throws Exception { driver.quit(); }

setup操作包含導入待測應用apk包,設置與Appium Server連接所需參數,並初始化AndroidDriver對象。以標版登錄case為例,其需要繼承AppiumTestBase,代碼如下:

package com.incito.appiumdemo; import org.junit.After; import org.junit.Before; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.support.ui.WebDriverWait; import java.io.File; import java.net.URL; import java.util.concurrent.TimeUnit; import io.appium.java_client.android.AndroidDriver; public class AccountLogin extends AppiumTestBase{ /** * case 編號 AccountLogin_001 * ****@throws ****Exception */ @Test public void testAccountLogin() throws Exception { Account.*getInstance*().gotoLoginPage(); Account.*getInstance*().doLogin(); } /** * case 編號 AccountLogin_002 * ****@throws ****Exception */ @Test public void testLoginout() throws Exception { Account.*getInstance*().gotoGestureLoginPage(); Account.*getInstance*().doGestureLogin(Config.*CURRENT_USERNAME*); Personal.*getInstance*().doLogout(); }

testAccountLogin Case中,執行了兩步操作:進入登錄頁面;執行登錄操作。這兩步操作都封裝在Account類里面。由此引入自動化case的分層設計框架,如下圖:


Paste_Image.png

自動化開發過程中,經常遇到的一個問題是,隨着產品的不斷更新迭代,APP的UI會不斷發生變化,自動化如何去應對這樣的變化,如何降低其維護代價。case分層設計主要是基於自動化可維護性的考慮,可維護性是功能自動化最重要的評價指標之一,其直接決定了自動化是否能開展下去。試想case數量達到一定程度時,若沒有采用封裝、分層的設計思路,極有可能出現“牽一發而動全身”的問題。下圖是標版自動化case的分層目錄圖。


Paste_Image.png


下面以登錄case為例,詳細了解其分層調用關系。登錄case在cases層的AccountLogin類中,其代碼上面已經展示,回到testAccountLogin Case的操作,第二步操作為Account.getInstance().doLogin();即在登錄頁面執行登錄操作,其封裝在business層的Account類中,代碼片段如下:

public void doLogin(){ LoginUiAction.*getInstance*().enterUsername(Config.*CURRENT_USERNAME*); LoginUiAction.*getInstance*().enterPassword(Config.*CURRENT_PASSWORD*); LoginUiAction.*getInstance*().clickLogin(); HomeUiAction.*getInstance*().clickOnCancelGesture(); Assert.*assertTrue*(LoginUiAction.*getInstance*().isLogin()); }

doLogin()方法中執行了“輸入用戶名;輸入密碼;點擊登錄按鈕;判斷登錄是否成功”操作,顯然這幾步操作都在UI層LoginUiAction類中。我們再查LoginUiAction.getInstance().
enterUsername()方法中做了什么,代碼片段如下:

//輸入用戶名 public void enterUsername(String username){ WebElement wl = DriverManager.*getInstance*().findElementById(packagename + ":id/login_input_account"); wl.clear(); wl.sendKeys(username); }

enterUsername()方法中,先根據id定位用戶名輸入框,然后清空輸入框,再輸入用戶名,這些操作都是Appium Client中提供的API。至此演示了登錄case的分層調用過程:cases—>business—>ui—>api。按照分層結構,只要業務邏輯不變,case維護任務主要放在ui層,上層無需改動,如此可極大減少case的維護代價。
在doLogin()方法中有一個“判斷登錄是否成功”的操作,斷言操作是自動化測試用例中必不可少的一部分,下面就開始介紹自動化測試用例的書寫規范。

自動化測試用例書寫規范及注意事項

一條case一般需要包括如下幾個要素:

  • 數據准備
  • 具體操作
  • 驗證點
  • 清楚操作結果

數據准備指提前准備測試賬號,假數據等;具體操作得按照業務測試同學提供的文本case來轉化;驗證點指自動化操作后,UI前后的變化點,比如登錄后,首頁會出現用戶名、總資產、財富分等控件,這些都是驗證點;清楚操作結果主要是基於case獨立性的考慮,盡可能做到每條case是獨立的,這樣某條case fail了,也不會對其他case造成影響,當然這樣會增加case的粒度,case穩定性會受影響,兩者之間可自行平衡。
下面介紹case開發的注意事項:

  1. 元素定位
    • ID(首選)
    • 文本
    • 控件類型
    • 坐標
  2. UI操作需要合理的sleep
  3. case獨立性
  4. 封裝常用操作
  5. 注釋及case前寫明操作步驟

元素定位有ID/文本/控件類型/坐標四種方式,推薦使用ID,因為只要某個控件還存在,其ID變化的可能性很小,若其位置發生了變動,case都無需維護。
下面給出查找元素ID的幾種方法:uiautomatorviewer/hierarchyviewer/源碼。uiautomatorviewer和hierarchyviewer工具在Android SDK中,配置好環境變量后,直接在命令行輸入命令即可打開圖形化工具,hierarchyviewer需要手機root,推薦使用uiautomatorviewer。如果有待測應用的源碼,也可以通過源碼來找ID,當然這種方式比較痛苦,但對熟悉業務及個人成長是有好處的,我最開始就是通過源碼來找ID的。
對於一些奇葩的情況,元素ID/文本/控件類型都無法定位時,使用坐標定位絕對好使,但不到萬不得已,盡量不用,因為用坐標定位就失去了兼容性,換個手機,case可能會執行失敗。
UI操作需要合理的sleep,經常由於網絡原因,UI加載需要一定時間,自動化操作過程中需要合理的sleep,sleep時間短了,case會失敗,長了又浪費時間。Appium框架中引入了隱式sleep方案,在初始化代碼中添加driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);即可,表示每步操作最多等待10s。
case獨立性前面已介紹,封裝及注釋容易理解,不做過多解釋。



文/平安雲測試平台(簡書作者)
原文鏈接:http://www.jianshu.com/p/497f9ed26189
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

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



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