1. 程式人生 > >如何玩轉app+webview混合應用自動化

如何玩轉app+webview混合應用自動化

WebView簡介

移動平臺的一個特性是能夠將“  格式 ” Web瀏覽器嵌入“ 原生 ”應用程式中,這些應用程式稱為“ webviews ”。Android開發人員使用“ android.webkit.WebView ”類在應用程式內部實現webview。類層次結構如下所示

java.lang.Object繼承
  android.view.View 
     android.view.ViewGroup 
       android.widget.AbsoluteLayout 


             android.webkit.WebView

我們可以說,在一行中,混合應用程式是包含原生檢視Web檢視的應用程式。

Appium的 一個主要原則是提供appium優於Calabash自動化工具的優勢,在Appium中,不需要更改被測試的應用程式。我們自動化同樣的應用程式進入生產。Appium允許我們使用Chromedriver內建的支援來測試WebApps和混合應用程式。我們可以使用selenium webdriver現有方法來自動化webview的

混合應用程式。

 

檢查WebView元素的條件

我們可以使用Chrome DevTools來除錯和檢查Android應用程式中的WebView內容。

  1. 它需要Android 4.4或更高版本,即API級別> = 19
  2. 應啟用WebView除錯; 開發人員必須在WebView類中啟用“ setWebContentsDebuggingEnabled 標誌。此標誌可以除錯載入到應用程式的任何WebView中的Web內容(HTML / CSS / JavaScript)。
  3. 桌面和Android裝置上安裝版本為32或更高版本的Chrome瀏覽器和DESKTOP_ANDROID_CHROME_BROWSER_VERSION> = ANDROID_DEVICE _CHROME_BROWSER_VERSION
  4. 除此之外,只有在應用程式內啟用webview除錯時,Appium才會識別WebView上下文。我們可以在LOLLIPOP / KITKAT Android裝置上檢查webview 
  5. Appium還使用Selendroid在4.4以上的裝置上支援webview。要使用appium的此功能,必須在傳遞給Appium伺服器的所需功能中將“automationName”指定  為“selendroid” 。如果我們測試的混合應用程式是以支援最低Android版本4.0.4(API級別14)和最高Android版本4.3(API級別18)的方式構建的,那麼我們可以檢查webview元素並使用selendroid模式執行我們的自動化測試appium。

 

 

如何在混合應用程式中檢查和自動化WebView

令人遺憾的是UIAutomatorViewer無法幫助我們檢查WebView下的元素。

WebView_1
我們可以通過兩種方式檢查WebView下的這些元素:

 

使用Selendroid Inspector

使用Appium通過執行具有所需能力appium工具automationName 為“ Selendroid ”只適用於應用,其是建立Android版本<4.4

我們將使用appium伺服器手動啟動應用程式:

1)瀏覽apk以從本地資料夾啟動。

2)選擇所需的能力automationName 作為“ Selendroid ”和其他強制引數,如platformnameplatformversion, launch活動

3)單擊“播放”按鈕啟動伺服器

WebView_2
WebView_3
4)應用程式啟動。如果我們仔細檢視Appium伺服器執行日誌,那麼我們可以看到它在埠8080的本地主機上啟動selendroid伺服器

WebView_4
5)如果selendroid伺服器正常啟動然後點選URL以下它將返回到json字串下面

URL:http:// localhost:8080 / wd / hub / status

jSON字串:{“value”:{“supportedApps”:[],“build”:{“browserName”:“selendroid”,“version”:“0.12.0”},“os”:{“arch”:“ armeabi-V7A”,”版本”:” 19“,”姓名”:”機器人”},” supportedDevices”:[]},”狀態”:0}

WebView_5
5)要開始檢查應用程式,我們點選此URL http:// localhost:8080 / inspector它將自動重定向到http:// localhost:8080 / inspector / session / 88ce8684-d785-4a24-9157-80967becc60d /取得會話ID如果selendroid伺服器正在執行,現在我們可以選擇檢查應用程式元素,所以我們所做的是:

  •  我們點選了一個帶有我們從selendroid檢查器獲取的id的按鈕,它導航我們到webview,它還為點選操作生成了等效的Java程式碼。

WebView_6

  • 我們看到按鈕點選webview出現,selendroid檢查員生成完成webview的html源。再次像在步驟1中一樣,如果我們在文字框上執行單擊操作,按鈕,選擇下拉列表會生成等效的Java程式碼。

WebView_7
WebView_8

 

 

使用Chrome遠端偵錯程式

僅適用於支援Android版本4.4+或API級別> 18的應用程式。需要注意的重要一點是appium適用於API級別> 17但是chrome遠端偵錯程式適用於API級別> 18,即我們可以將此chrome功能用於API級別> 18

1)在chrome瀏覽器中輸入“ chrome:// inspect /#devices ”

WebView_9
2)在使用adb列出的裝置中開啟啟用了webview偵錯程式的應用程式

WebView_10
3)點選檢查連結,我們可以檢查webview下的元素。

檢查電子郵件文字輸入欄位

WebView_11

檢查密碼輸入文字欄位

WebView_12
檢查登入提交按鈕欄位

WebView_13

編寫指令碼以自動化WebView

我們可以按照以下4個步驟自動化Webview

  • 導航到您的應用中Web檢視處於活動狀態的部分
  • 呼叫getContext()方法,該方法將返回我們可以訪問的上下文列表,例如'NATIVE_APP'或'WEBVIEW_1'
  • 使用我們想要訪問的上下文的id呼叫context()方法,即WEBVIEW_1,它是應用程式的webview上下文的名稱。這將Appium會話置於一種模式,其中所有命令都被解釋為用於自動化Web檢視,而不是比應用程式的本機部分。例如,如果執行getElementByTagName,它將在Web檢視的DOM上執行,而不是返回UIAElements / MobileElements / Native WebElements。
  • 要停止在Web檢視上下文中自動化,我們可以使用id NATIVE_APP(即應用程式的名稱本機上下文)再次呼叫上下文。

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

package Appium;

import org.testng.annotations.Test;

import org.testng.annotations.AfterTest;

import org.testng.annotations.BeforeTest;

import io.appium.java_client.android.AndroidDriver;

import io.appium.java_client.AppiumDriver;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.Set;

import org.openqa.selenium.By;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.remote.DesiredCapabilities;

import org.openqa.selenium.support.ui.ExpectedConditions;

import org.openqa.selenium.support.ui.Select;

import org.openqa.selenium.support.ui.WebDriverWait;

 

public class WebViewSelendroidApp {

public static AndroidDriver<WebElement> driver;

public static AppiumDriver<WebElement> _driver;

public static DesiredCapabilities cap = new DesiredCapabilities();

 

@BeforeTest

public void startAppium() throws MalformedURLException, InterruptedException{

System.out.println("setUP() :: driver.AndroidDriver() executed");

cap.setCapability("platformVersion","4.4.4");

cap.setCapability("platformName","Android");

cap.setCapability("deviceName","ZX1B32HNBD");

cap.setCapability("app","C:\\Users\\WebView-test.apk");

driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4725/wd/hub"),cap);

}

 

@Test

public void AppLogin() throws InterruptedException{

System.out.println("AppLogin() :: driver.start() executed");

By webView = By.className("android.webkit.WebView");

By title = By.id("android:id/title");

WebDriverWait wait = new WebDriverWait(driver,300);

driver.findElement(title).getText();

Set<String> availableContexts1 = driver.getContextHandles();

System.out.println("Total No of Context Found Before reaching WebView = "+ availableContexts1.size());

System.out.println("Context Name is "+ availableContexts1);

 

//4.1 Navigate to a portion of your app where a web view is active

driver.findElement(By.id("com.mkyong.android:id/buttonUrl")).click();

wait.until(ExpectedConditions.visibilityOfElementLocated(webView));

// 4.2 Call getContext() method which will returns a list of contexts we can access, like 'NATIVE_APP' or 'WEBVIEW_1'

Set<String> availableContexts = driver.getContextHandles();

System.out.println("Total No of Context Found After we reach to WebView = "+ availableContexts.size());

for(String context : availableContexts) {

if(context.contains("WEBVIEW")){

System.out.println("Context Name is " + context);

// 4.3 Call context() method with the id of the context you want to access and change it to WEBVIEW_1

//(This puts Appium session into a mode where all commands are interpreted as being intended for automating the web view)

driver.context(context);

break;

}

}

String input_box_text = driver.findElement(By.id("name_input")).getAttribute("value");

System.out.println("Pre written text inside text box is " + input_box_text);

driver.findElement(By.id("name_input")).clear();

driver.findElement(By.id("name_input")).sendKeys("Amit Jain"); System.out.println("No of dropdown on page "+ driver.findElements(By.xpath("//select")).size());

 

int size=driver.findElements(By.xpath("//select")).get(0).findElements(By.xpath("//option")).size();

System.out.println("No of Elements in dropdown "+ size);

WebElement car = driver.findElement(By.name("car"));

Select preferedCar=new Select(car);

preferedCar.selectByIndex(2);

System.out.println("Button Value is : " + driver.findElement(By.xpath("/html/body/form/div/input[2]")).getAttribute("value"));

//Key code constant: Back key.

//Constant Value: 4 (0x00000004)

driver.sendKeyEvent(4);

// 4.4 To stop automating in the web view context we can simply call the context again with id NATIVE_APP.

for(String context : availableContexts) {

if(context.contains("NATIVE")){

System.out.println("We are Back to " + context);

driver.context(context);

if (driver.findElement(title).getText().equals("WebViewApp"))

System.out.println("Context Switched");

}

}

}

 

@AfterTest(alwaysRun= true)

public void tearDown(){

driver.quit();

System.out.println("tearDown() :: driver.quit() executed");

}

} // end of class