判断Activity中控件是否出现,可以通过判断页面加载完成后应该出现的元素是否及时出现,
而这个问题又可以转化为如何等待页面元素的出现。今天我们就先从等待方法说起,
首先,看一下我们要测试的APP,本文采用的APP是Android Hybrid,如果想看源码,可以从这里下载:https://github.com/tobecrazy/webview
这个App主要是由一个ImageButton和WebView,而点击显示大约5s之后才会出现红色的ImageButton,点击HOME会返回主页大约5s ImageButton消失。主要是想通过该APP验证以下2点:
a. Native的元素不需要设置等待,Appium会等待元素出现除非超时
b. Pure Web或WebView的元素需要设置等待和selenium一样。
APK下载:
https://github.com/tobecrazy/webview/blob/master/app/build/outputs/apk/app-debug.apk
第一种,死等
Thread.sleep(毫秒)
阻塞线程,必须等到sleep结束之后才会执行后面的脚本。不推荐使用,比如比如设置等待时间30s,无论该元素是否出现,都会暂停case 30s
第二种,隐式等待
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
隐式等待是针对全局所有元素设置的,一个30s超时时间。先去找元素,如果没有出现就等待,直到超过这个时间,就会抛出异常。
第三种,显式等待
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement input = wait.until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("//input[@id='index-kw']"));
}
});
显式等待,明确告诉driver等待元素出现,如果没有出现就等待30s,如果在30s内已经出现就返回该元素。
核心代码
package main.java.com.dbyl.appiumCore.tests;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.AutomationName;
import io.appium.java_client.remote.MobileCapabilityType;
import main.java.com.dbyl.appiumServer.AppLogger;
import main.java.com.dbyl.appiumServer.AppiumServerUtils;
public class AppWebView {
AndroidDriver<MobileElement> driver;
String keyword = "appium";
URL url;
AppLogger logger = new AppLogger(AppWebView.class);
@BeforeClass
public void startAppiumServer() throws IOException, InterruptedException {
url = AppiumServerUtils.getInstance().startServer("127.0.0.1", 4723);
logger.debug("start Appium Server");
}
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception {
// set up appium
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.APPIUM);
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");
// if no need install don't add this
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "apps");
File app = new File(appDir, "webview.apk");
capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.testerhome.webview");
// support Chinese
capabilities.setCapability("unicodeKeyboard", "True");
capabilities.setCapability("resetKeyboard", "True");
// no need sign
capabilities.setCapability("noSign", "True");
capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".MainActivity");
logger.info("connet to Appium server " + url.toString());
driver = new AndroidDriver<MobileElement>(url, capabilities);
}
@Test(groups = { "webView" })
public void webViewTest() throws InterruptedException {
MobileElement clickToPresent = driver.findElementById("com.testerhome.webview:id/action_present");
clickToPresent.click();
MobileElement imageButton = driver.findElementById("com.testerhome.webview:id/button");
Assert.assertTrue(imageButton.isDisplayed());
Set<String> contexts = driver.getContextHandles();
for (String context : contexts) {
// 输出context
logger.info(context);
if (context.contains("WEBVIEW")) {
logger.info("swich_to_content " + context);
driver.context(context);
}
}
logger.info(driver.getContext());
// 隐式等待,针对全局设置
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
// pageLoadTimeout只能用于webview 或者 pure web
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
// 这段代码返回浏览器加载页面状态,complete为加载完成
JavascriptExecutor jse = (JavascriptExecutor) driver;
String status = (String) jse.executeScript("var status=document.readyState;return status");
Assert.assertTrue(status.contains("complete"));
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement input = wait.until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(By.xpath("//input[@id='index-kw']"));
}
});
input.sendKeys(keyword);
By by = By.xpath("//button[@id='index-bn']");
if (isElementPresent(by)) {
driver.findElement(by).click();
}
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.navigate().refresh();
// 返回native app context
driver.context("NATIVE_APP");
MobileElement title = driver.findElementById("android:id/action_bar_title");
Assert.assertTrue(title.getText().contains(keyword));
MobileElement back = driver.findElementById("com.testerhome.webview:id/action_back");
back.click();
Assert.assertTrue(title.getText().equals("百度一下"));
}
/**
* @author young
* @param by
* @return
*/
private boolean isElementPresent(By by) {
try {
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception {
logger.info("quit");
driver.quit();
}
}
总结
可以看出,在Native的APP里面,不许要设置等待相关,Appium会自动等待元素出现。在Web 或WebView,设置和Selenium一样,有几个方法是只能在WebView下使用的,比如wait for page load 和执行JS代码
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
// 这段代码返回浏览器加载页面状态,complete为加载完成
JavascriptExecutor jse = (JavascriptExecutor) driver;
String status = (String) jse.executeScript("var status=document.readyState;return status");
Assert.assertTrue(status.contains("complete"));
浙公网安备 33010602011771号