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内容。
- 它需要Android 4.4或更高版本,即API级别> = 19。
- 应启用WebView调试; 开发人员必须在WebView类中启用“ setWebContentsDebuggingEnabled ”标志。此标志可以调试加载到应用程序的任何WebView中的Web内容(HTML / CSS / JavaScript)。
- 桌面和Android设备上安装版本为32或更高版本的Chrome浏览器和DESKTOP_ANDROID_CHROME_BROWSER_VERSION> = ANDROID_DEVICE _CHROME_BROWSER_VERSION
- 除此之外,只有在应用程序内启用webview调试时,Appium才会识别WebView上下文。我们可以在LOLLIPOP / KITKAT Android设备上检查webview 。
- 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下的这些元素:
使用Selendroid Inspector
使用Appium通过运行具有所需能力appium工具automationName 为“ Selendroid ”只适用于应用,其是建立Android版本<4.4
我们将使用appium服务器手动启动应用程序:
1)浏览apk以从本地文件夹启动。
2)选择所需的能力automationName 作为“ Selendroid ”和其他强制参数,如platformname,platformversion, launch活动
3)单击“播放”按钮启动服务器
4)应用程序启动。如果我们仔细查看Appium服务器运行日志,那么我们可以看到它在端口8080的本地主机上启动selendroid服务器
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}
5)要开始检查应用程序,我们点击此URL http:// localhost:8080 / inspector它将自动重定向到http:// localhost:8080 / inspector / session / 88ce8684-d785-4a24-9157-80967becc60d /取得会话ID如果selendroid服务器正在运行,现在我们可以选择检查应用程序元素,所以我们所做的是:
- 我们点击了一个带有我们从selendroid检查器获取的id的按钮,它导航我们到webview,它还为点击操作生成了等效的Java代码。
- 我们看到按钮点击webview出现,selendroid检查员生成完成webview的html源。再次像在步骤1中一样,如果我们在文本框上执行单击操作,按钮,选择下拉列表会生成等效的Java代码。
使用Chrome远程调试器
仅适用于支持Android版本4.4+或API级别> 18的应用程序。需要注意的重要一点是appium适用于API级别> 17但是chrome远程调试器适用于API级别> 18,即我们可以将此chrome功能用于API级别> 18
1)在chrome浏览器中输入“ chrome:// inspect /#devices ”
2)在使用adb列出的设备中打开启用了webview调试器的应用程序
3)点击检查链接,我们可以检查webview下的元素。
检查电子邮件文本输入字段
检查密码输入文本字段
检查登录提交按钮字段
编写脚本以自动化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 |