如何玩转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

猜你喜欢

转载自blog.csdn.net/ProgrammerFan0101/article/details/83142453