11.7 处理长按
长按是用户比较常用的一种手势,与点触后一直持续按下的动作不同,有时候长按可以获得更多的信息提醒。可以使用TouchAction模拟长按操作,如在拨号栏中长按*会显示值"P",如代码清单11-9所示。
操作步骤如下。
(1)创建TouchAction对象。
(2)执行Longpress操作。
(3)使用perform将操作名传递给手机App。
代码清单11-9长按
private AndroidDriver driver; @Before public void setUp() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability("deviceName", "Lenovo A788t");//真机名称为Lenovo A788t capabilities.setCapability("platformVersion", "4.3");//操作系统版本为4.3 capabilities.setCapability("platformName", "Android");//操作系统名称为Android capabilities.setCapability("udid", "00a10399");//使用的真机为Android平台 capabilities.setCapability("appPackage", "com.android.contacts");//待测App包 capabilities.setCapability("appActivity",".activities.DialtactsActivity"); //待测App主activity名 capabilities.setCapability("automationName", "appium");// driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities); } @Test public void testlongpress(){ WebElement dail = driver.findElementByName("拨号"); dail.click(); TouchAction taction =new TouchAction(driver); WebElement star = driver.findElementById("star"); taction.longPress(star).perform(); WebElement result = driver.findElementById("digits"); assert result.getText().equals("P"):"Actual value is"+result.getText()+"did not match expected value: P"; } @After public void stop() { driver.quit(); } |
11.8 处理下拉列表框
Selenium针对WebList下拉列表框采用了Select类,但是Appium并未提供该类的处理,而且由于Appium底层UIAutomator的限制,超过屏幕界限的下拉选项未被选择进来。这里提供对WebList类的处理,如在selendroid-test-app-0.15.0.apk中选择编程语言。
对于图11-3所示的单选按钮,class都为CheckedTextView。
图11-3 查看CheckedTextView类
处理方式如代码清单11-10所示。
代码清单11-10处理下拉列表框
public void checkedTextView(){ //使用class属性选择所有的单选按钮,并存放在一个list中 @SuppressWarnings("unchecked") List<MobileElement> checkedTextViews = (List<MobileElement>) driver. findElements ByClassName("android.widget.CheckedTextView"); //使用for循环遍历list中的每个单选按钮,查到name值为Ruby的单选按钮,如果该单选按钮未处于 //选中状态,则调用click方法进行选择 for(MobileElement checkedTextView:checkedTextViews){ if(checkedTextView.getAttribute("name").equals("Ruby")){ if(!checkedTextView.isSelected()){ checkedTextView.click();} Assert.assertTrue(checkedTextView.isSelected()); } } } |
11.9 处理缩放
缩放手势类似于拖动手势,第二个手指并拢之后按下,接着两个手指向相同或者相反的方向滑动,从而实现页面的放大或者缩小。Appium支持多点触摸,可以使用MultiTouchAction类同时启用多个TouchAction类,如将相册中的图片放大。
实现方式为通过TouchAction封装多个touch动作,并把Touch动作封装到MultiTouchAction中。在200m()方法中x、y表示偏移量,如代码清单11-11所示。
代码清单11-11缩放操作
public void zoom(int x, int y) { MultiTouchAction multiTouch = new MultiTouchAction(driver); int scrHeight = driver.manage().window().getSize().getHeight(); int yOffset = 100; if (y - 100 < 0) { yOffset = y; } else if (y + 100 > scrHeight) { yOffset = scrHeight - y; } TouchAction action0 = new TouchAction(driver).press(x, y).moveTo(x, y - yOffset).release(); TouchAction action1 = new TouchAction(driver).press(x, y).moveTo(x, y + yOffset).release(); multiTouch.add(action0).add(action1); multiTouch.perform(); } |
11.10 检查元素文本是否可见
以selendroid-test-app-0.15.0.apk为例,当单击Display text view按钮时才会出现"Text is sometimes displayed"所在的控件,如图11-4所示。
判断文本是否出现的代码如代码清单11-12所示。
图11-4 单击Display text view按钮
代码清单11-12检查元素文本是否为可见
@Test public void testElementPresent() throws InterruptedException{ String expectValue = "Text is sometimes displayed"; //识别控件Display text view MobileElement visibleButtonElement = (MobileElement) driver.findElementById ("io.selendroid.testapp:id/visibleButtonTest"); //单击Display text view按钮 visibleButtonElement.click(); //弹出文本通过By.id进行识别 By visibileButton_by = By.id("io.selendroid.testapp:id/visibleTextView"); //判断弹出的文本是否存在 if(isElementPresented(visibileButton_by)){ //获取文本内容 String visibileButtonText = driver.findElement(visibileButton_by).getAttribute ("text"); //判断文本内容是否包含预期值。若包含则打印成功信息;若不包含,则用例执行失败 if(visibileButtonText.contains(expectValue)){ System.out.println("查找控件成功"); } else{ Assert.fail("查找控件失败"); } } } public boolean isElementPresented(By by){ boolean isDisplayed = false; try{ isDisplayed = driver.findElement(by).isDisplayed(); }catch(NoSuchElementException e){ isDisplayed = false; } return isDisplayed; } |
值得注意的是,如果driver.findElement(by)无法查找到控件元素,将会报出异常,后面的isDisplayed()方法不会被执行,所以需要增加try catch以捕获异常。
11.11 启动其他App
在测试中,也许会涉及多个App之间的交互,或者在一个App中会启动其他App。如在测试大众点评APK时,在首页中单击"美食"图标进入"美食"界面,这时启动selendroid- test-app-0.17.0.apk。实现多APK交互的代码如代码清单11-13所示。
代码清单11-13多APK交互
@Test(description="测试启动app") public void TeststartActivity(){ //"美食"图标 MobileElement meishiElement = (MobileElement) driver.findElement(By.xpath ("//android. support.v7.widget.RecyclerView/android.widget.RelativeLayout[1]/android.widget. ImageView")); //单击"美食"图标,跳转到"美食"界面 meishiElement.click(); //启动selendroid-test-app的包名 String androidPackage = "io.selendroid.testapp"; //启动selendroid-test-app的main Activity String androidStartActivity = ".HomeScreenActivity"; //启动selendroid-test-app driver.startActivity(new Activity(androidPackage, androidStartActivity)); } |
11.12 并行测试
" 缩短了执行时间。并行测试也就意味着多个测试可以同时执行,从而减少了整体测试所花费的时间。
" 允许多个线程并行地测试同一个测试组件。有了这个特性,用户就能够写出相应的测试用例来验证应用程序中包含多线程部分的代码的正确性。
Appium提供了一种方式以在一台设备上自动操作多个Android会话,即采用多个标识符的方式启动多个Appium服务器端。
本节以在一台设备上运行两个Appium服务器为例,讲解如何进行并行测试。具体步骤如下。
(1)创建Maven项目。
(2)启动两个Appium服务器,并配置端口号。
对于第一个Appium服务器:Server Port为4723,Bootstrap Port为4724。
对于第二个Appium服务器:Server Port为4725,Bootstrap Port为4726。
在Appium的GUI中,选择Advanced标签,在General选项组下,在Server Port文本框中设置服务器端口号,如图11-5所示。
图11-5 Appium服务器端口号设置
选择Advanced标签,在General选项组下,在Bootstrap文本框中设置Bootstrap端口号,如图11-6所示。
图11-6 Bootstrap端口号设置
下面以selendroid-test-app-0.17.0.apk为例,介绍如何在两个手机上同时运行测试用例。
(1)创建Constants用来存储手机配置信息,如代码清单11-14所示。
代码清单11-14Constants
package com.shijie.util; public class Constants { public class 测试手机_红米{ public static final String deviceName = "Redmi 3"; public static final String udid = "c1aeae297d72"; public static final String platformVersion = "5.1.1"; public static final String platformName = "Android"; public static final String appPackage = "io.selendroid.testapp"; public static final String appActivity = ".HomeScreenActivity"; public static final String unicodeKeyboard = "True"; public static final String noSign = "True"; } public class 测试手机_小米{ public static final String deviceName = "2014813"; public static final String udid = "59de0f3"; public static final String platformVersion = "4.4.4"; public static final String platformName = "Android"; public static final String appPackage = "io.selendroid.testapp"; public static final String appActivity = ".HomeScreenActivity"; public static final String unicodeKeyboard = "True"; public static final String noSign = "True"; } } } |
(2)创建两个testNG测试用例。测试用例1如代码清单11-15所示,它用于完成注册。
代码清单11-15测试用例1
package com.shijie.testScripts; import java.net.URL; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import org.junit.Assert; import com.shijie.util.Constants; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; public class testRegister{ AndroidDriver<AndroidElement> driver; @BeforeMethod @Parameters({"device_ID","port"}) public void SetUp() throws Exception { // TODO Auto-generated method stub capabilities.setCapability("deviceName", Constants.测试手机_红米.deviceName); capabilities.setCapability("udid", Constants.测试手机_红米.udid); capabilities.setCapability("platformVersion", Constants.测试手机_红米.platformVersion); capabilities.setCapability("platformName", Constants.测试手机_红米.platformName); capabilities.setCapability("appPackage", Constants.测试手机_红米.appPackage); capabilities.setCapability("appActivity", Constants.测试手机_红米.appActivity); capabilities.setCapability("unicodeKeyboard", Constants.测试手机_红米.unicodeKeyboard); capabilities.setCapability("noSign", Constants.测试手机_红米.noSign); driver = new AndroidDriver<>(new URL("http://"+device_ID+":"+port+"/wd/hub"), capabilities);} @Test public void testWebApp(){ //对象识别 WebElement startRegister_btn = driver.findElementById("io.selendroid.testapp:id/ startUserRegistration"); //单击,页面跳转 startRegister_btn.click(); //用户名对象 WebElement username_txt = driver.findElementById("io.selendroid.testapp:id/ inputUsername"); username_txt.sendKeys("shijie"); //E-mail对象 WebElement email_txt = driver.findElementById("io.selendroid.testapp:id/inputEmail"); email_txt.sendKeys("shijie@126.com"); //密码对象 WebElement password_txt = driver.findElementById("io.selendroid.testapp:id/ inputPassword"); password_txt.sendKeys("123456"); WebElement name_txt = driver.findElementById("io.selendroid.testapp:id/inputName"); name_txt.clear(); name_txt.sendKeys("daming"); //driver.hideKeyboard(); WebElement languge_sel = driver.findElementById("io.selendroid.testapp:id/input_ preferedProgrammingLanguage"); languge_sel.click(); WebElement prgLanguage = driver.findElementByName("Scala"); prgLanguge.click(); WebElement accept_check = driver.findElementById("io.selendroid.testapp:id/ input_adds"); accept_check.click(); WebElement register_btn = driver.findElementById("io.selendroid.testapp:id/ btnRegisterUser"); register_btn.click(); WebElement label_name_data = driver.findElementById("label_name_data"); Assert.assertEquals(label_name_data.getText().toString(), "daming"); } @AfterMethod public void TearDown() { driver.quit(); } } |
测试用例2如代码清单11-16所示,在图11-4所示主页面中单击Display text view按钮,验证弹出的文字是否正确。
代码清单11-16测试用例2
package com.shijie.testScripts; import java.net.URL; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import org.junit.Assert; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; import com.shijie.util.Constants; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.openqa.selenium.By; public class testDisplaytextView{ AndroidDriver<AndroidElement> driver; @BeforeMethod @Parameters({"device_ID","port"}) public void SetUp(String device_ID, String port ) throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability("deviceName", Constants.测试手机_小米.deviceName); capabilities.setCapability("udid", Constants.测试手机_小米.udid); capabilities.setCapability("platformVersion", Constants.测试手机_小米.platformVersion); capabilities.setCapability("platformName", Constants.测试手机_小米.platformName); capabilities.setCapability("appPackage", Constants.测试手机_小米.appPackage); capabilities.setCapability("appActivity", Constants.测试手机_小米.appActivity); capabilities.setCapability("unicodeKeyboard", Constants.测试手机_小米.unicodeKeyboard); capabilities.setCapability("noSign", Constants.测试手机_小米.noSign); driver = new AndroidDriver<>(new URL("http://"+device_ID+":"+port+"/wd/ hub"),capabilities); } @Test public void testWebApp(){ //对象识别 boolean flag = false; String actualTxt = null; WebElement visibleButtonTest_btn = driver.findElementById("io.selendroid. testapp:id/visibleButtonTest"); //单击,弹出页面文字 visibleButtonTest_btn.click(); //判断文字是否弹出 flag = isElementExist(By.id("visibleTextView")); if(flag){ WebElement visibleText_text = driver.findElementById("io.selendroid.testapp: id/visibleTextView"); actualTxt = visibleText_text.getAttribute("text"); //判断文字是否一致 Assert.assertEquals(actualTxt, "Text is sometimes displayed"); } else{ //文字没有弹出,断言失败 Assert.fail("文字未弹出,测试用例失败"); } } public boolean isElementExist(By locator){ boolean flag = false; try{ driver.findElement(locator); flag = true; }catch(NoSuchElementException e){ } return flag; } @AfterMethod public void TearDown() { driver.quit(); } } |
为了演示实例,以上操作只提取了port、udid、devicename作为参数,在实际操作中为了更好地实现参数与脚本分离,可以将所有的参数都提取出来。
(3)设置testng.xml,如代码清单11-17所示。
代码清单11-17设置testng.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Suite" parallel="tests" thread-count="2" > <test name="Testdevice1" > <parameter name ="device_ID" value = "127.0.0.1"/> <parameter name ="port" value = "4723"/> <classes> <class name="com.shijie.testScripts.testRegister" /> </classes> </test><!--Test--> <test name="Testdevice2" > <parameter name ="device_ID" value = "127.0.0.1"/> <parameter name ="port" value = "4725"/> <classes> <class name="com.shijie.testScripts.testDisplaytextviewClick" /> </classes> </test><!--Test--> </suite><!--Suite--> |
在testng.xml上右击,就可以看到测试用例在两个手机上一起运行。
版权声明:51Testing软件测试网获人民邮电出版社和作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。