Appium之Android功能脚本
注:这里只写了登录和退出功能,以下不提供app的包名,下面我使用的是线上包
准备:1、Eclipse的Java环境;2、Appium环境;3、Android真机一台。
一、Appium安装
1、通过Node.js安装
1)安装Node.js:在https://nodejs.org/en/download/里面选择最新的版本,并且选择适合自己系统的版本下载;
2)下载安装之后,打开cmd,输入npm查看node.js是否安装成功;
3)最后安装Appium:通过npm来安装appium,打开cmd窗口,然后输入npm install -g appium来安装。
2、通过Appium安装包安装(建议用这个方法)
在Appium官方网站上下载操作系统相应的Appium版本。下载地址:https://github.com/appium/appium-desktop/releases/tag/v1.6.2。这里下载的是appium-desktop-Setup-1.6.2.exe来安装。安装后有桌面图标,(可以右击选择属性兼容性运行)打开后点击 Start Server 启动Appium。
二、安装Android开发环境
1、安装Java环境
1)直接在JDK官网中下载:
http://download.oracle.com/otn-pub/java/jdk/8u171-b11/512cd62ec5174c3487ac17c61aaa89e8/jdk-8u171-windows-x64.exe 下载完成后进行安装;
2)打开 我的电脑-属性-高级-环境变量-系统变量-新建一个变量名为JAVA_HOME的变量,变量值配置JAVA安装的地址;
变量名:JAVA_HOME
变量值:C:\Program Files\Java\jdk1.8.0_171
3)新建一个变量名为CLASS_PATH的变量,变量值配置为安装Java的lib底下的文件地址;
变量名:CLASS_PATH
变量值:C:\Program Files\Java\jdk1.8.0_171\lib
4)在PATH变量中-"编辑",添加Java安装后bin的地址;
变量名:Path
变量值:%JAVA_HOME%\bin;
5)打开cmd窗口,然后输入javac来验证是否有安装成功,如果有列表信息就成功安装了JDK。
2、安装Android SDK
1)在http://www.androiddevtools.cn/下载Android sdk工具;
2)在我的电脑-属性-高级-环境变量-系统变量中新建ANDROID_HOME的变量,变量值为Android sdk的地址;
变量名:ANDROID_HOME
变量值:E:\SDK\android-sdk-windows
3)在Path变量名中点击"编辑",添加Android tools的地址;
变量名:Path
变量值:%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;
4)然后在cmd窗口中输入adb来验证是否有安装成功,如果有adb版本信息等就说明安装成功了。
三、Windows 下Maven安装配置(本地仓库配置)
1、下载maven
1)maven官网:http://maven.apache.org/
下载下来也就是一个压缩文件,解压。我下载的是3.5.2版本,解压之后如下:
路径为:D:\Program Files\apache-maven-3.5.2
2)配置环境变量
添加系统变量:MAVEN_HOME
值为刚才的解压路径:D:\Program Files\apache-maven-3.5.2
然后在path变量末尾加入“;%MAVEN_HOME%\bin;”
3)验证是否安装成功
打开命令行输入:mvn -v。如果出现maven的相关信息,说明安装成功。
4)打开maven安装目录\conf\setting.xml文件
插入 <localRepository>E:\maven-repository</localRepository>
那么默认的本地仓库位置已经修改为E:\maven-repository目录了。
5)检验一下刚才的设置是否生效
命令行输入:mvn help:system
如果没有问题,说明配置已经成功。现在我们到E:\maven-repository目录下看看,会发现已经该目录下已经多出来好多文件。这些就是maven从中央仓库下载下来的文件了。
6)Eclipse中Maven的配置
1.打开Eclipse的首选项设置
2.找到Maven的配置项目
3.设置Maven的全局配置文件settings.xml
说明:Eclipse会自动的使用 settings.xml 文件中包含镜像库的URL地址信息, 找到Maven镜像库位置
四、创建一个Maven Project
1、修改pom.xml文档:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com</groupId>
<artifactId>testmobike</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>testmobike</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>5.0.1</version>
</dependency> <dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>
</project>
2、连接真机,启动电脑的cmd.exe运行adb命令
查看手机是否连接正常,并查看deviceName:adb shell;exit;adb devices
查看手机里的包名:adb shell;su;cd /data/data;ls 或者 adb shell;pm list package -f
启动Appium
点击放大图标,在Desired Capabilities里设置相关系数
(
"appPackage": "",
"appActivity": "",
"platformName": "android",
"deviceName": ""
)
3、启动后可以相应的录制脚本
调试代码:
package test2.hejiaqin_login; import io.appium.java_client.MobileElement;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException; import static org.junit.Assert.assertTrue; import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.remote.DesiredCapabilities; public class hejiaqin3_9 { private AndroidDriver driver; @Before
public void setUp() throws MalformedURLException {
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
File appDir = new File(System.getProperty("user.dir"), "apps");
File app = new File(appDir, " 包 ");//包放在apps文件夹里面
desiredCapabilities.setCapability("app", app.getAbsolutePath()); desiredCapabilities.setCapability("appPackage", " 包名 ");
desiredCapabilities.setCapability("appActivity", ".splash.activity.SplashActivity");
desiredCapabilities.setCapability("platformName", "android");
desiredCapabilities.setCapability("deviceName", "设备标识");//vivoX7
desiredCapabilities.setCapability("noReset", "false");
// desiredCapabilities.setCapability("unicodeKeyboard", "ture");
// desiredCapabilities.setCapability("resetKeyboard", "ture");
//desiredCapabilities.setCapability("newCommandTimeout")=30;
URL remoteUrl = new URL("http://localhost:4723/wd/hub"); driver = new AndroidDriver(remoteUrl, desiredCapabilities);
} @After
public void tearDown() throws Exception {
driver.quit();
} public void waittimeout(String s,int type,int timeout) throws InterruptedException {//等待方式
switch(type){
case 1:
while(driver.findElementsById(s).size()==0){
Thread.sleep(1000);
timeout--;
if(timeout<0){
break;
}
}
break;
case 2:
while(driver.findElementsByXPath(s).size()==0){
System.out.println("==="+timeout);
Thread.sleep(1000);
timeout--;
if(timeout<0){
break;
}
}
break;
case 3:
while(driver.findElementsByClassName(s).size()==0){
Thread.sleep(1000);
timeout--;
if(timeout<0){
break;
}
}
break;
default:
while(driver.findElementsByAccessibilityId(s).size()==0){
Thread.sleep(1000);
timeout--;
if(timeout<0){
break;
}
}
break;
}
} @Test
public void sampleTest() throws InterruptedException {
//滑动功能
Thread.sleep(2000);
TouchAction action = new TouchAction(driver);
int width = driver.manage().window().getSize().width;
int height = driver.manage().window().getSize().height;
int x1 =width*7/8;
int x2 =width*1/8; action.longPress(x1,height/2).moveTo(x2,height/2).release().perform();
Thread.sleep(2000);
action.longPress(x1,height/2).moveTo(x2,height/2).release().perform();
Thread.sleep(2000);
action.longPress(x1,height/2).moveTo(x2,height/2).release().perform();
Thread.sleep(2000); (new TouchAction(driver)).tap(527, 1758).perform();
Thread.sleep(5000);
driver.findElementById("x:id/switch_login_type").click();
Thread.sleep(2000);
waittimeout("x:id/etPhone",1,30); MobileElement el2 = (MobileElement) driver.findElementById("x:id/etPhone");
el2.sendKeys("账号手机号");
Thread.sleep(2000);
int i=10;
while(!el2.getText().toString().replaceAll("\\s*","").equals("账号手机号")){
el2.sendKeys("账号手机号");
Thread.sleep(2000);
i--;
if(i<0){
break;
}
} //输入的用户名去掉空格,换行,制表符之后如果不和150这个值一样,那么就把这个el2设置成150这个值 MobileElement elh = (MobileElement) driver.findElementById("x:id/ivShowPassword");
elh.click(); Thread.sleep(2000);
MobileElement el3 = (MobileElement) driver.findElementById("x:id/etPassword");
el3.sendKeys("密码");
Thread.sleep(2000);
int t=10;
while(!el3.getText().toString().replaceAll("\\s*","").equals("密码")){
el3.sendKeys("密码");
Thread.sleep(2000);
t--;
if(t<0){
break;
}
} MobileElement el4 = (MobileElement) driver.findElementById("x:id/tvLogin");
el4.click(); //登录
Thread.sleep(2000); waittimeout("/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.ImageView[1]",2,30);
driver.findElementById("x:id/iv_close").click();//直接X掉跳过 //我的-退出
waittimeout("x:id/check_box_bottom_tab_mine",1,30);
driver.findElementById("x:id/check_box_bottom_tab_mine").click();//我的 按钮
Thread.sleep(2000);
action.longPress(width*1/2,height*3/4).moveTo(width*1/2,height*1/4).release().perform();
Thread.sleep(2000);
waittimeout("x:id/nav_linear_setting",1,30);
driver.findElementById("x:id/nav_linear_setting").click();//设置 按钮
driver.findElementById("x:id/tvLogout").click();//退出按钮
Thread.sleep(2000);
driver.findElementById("x:id/dialog_ok_btn").click();//退出登录 按钮
Thread.sleep(2000); } }
成功率测试代码:(让测试类循环运行多次,测试稳定性)
测试套test.java:
package com.demo.appium.zhdemo;
import junit.extensions.RepeatedTest;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class test extends TestCase
{ public static Test suite()
{
// 创建一个测试套件
TestSuite suite = new TestSuite(); // 增加测试类的class对象 // 测试某个方法多次,注意测试类需要提供带参数的构造方法
suite.addTest(new RepeatedTest(new leiming("fangfa"), 300)); return suite; }
} 被测类添加这些: import junit.framework.TestCase;
@SuppressWarnings("deprecation")
public class leiming extends TestCase { private List<Integer> values;
public leiming()
{
super();
}
public leiming(String name)
{
super(name);
}
@test
public void fangfa(){ }
@before
@after
}
五、App脚本编写
1、素的获取方法:使用Appium自带inspector录制脚本。这个比较简单的。
2、滑动
TouchAction action = new TouchAction(driver);
int width = driver.manage().window().getSize().width;
int height = driver.manage().window().getSize().height;
int x1 =width*7/8;
int x2 =width*1/8;
action.press(height/2,y1).waitAction(500).moveTo(height/2,y2).release().perform();
action. longPress (height/2,y1).moveTo(height/2,y2).release().perform();
JavascriptExecutor js = (JavascriptExecutor) driver; HashMap<String, String> scrollObject = new HashMap<String, String>(); scrollObject.put("direction", "down"); js.executeScript("mobile: scroll", scrollObject);
JavascriptExecutor js = (JavascriptExecutor) driver; HashMap<String, String> scrollObject = new HashMap<String, String>(); scrollObject.put("direction", "down"); scrollObject.put("element", ((RemoteWebElement) element).getId()); js.executeScript("mobile: scroll", scrollObject);
3、单击
控件点击:
driver.findElementById("XX").click();
driver.findElement(By.id("XX")).click();
driver.findElementByXpath("XX").click();
driver.findElement(By.Xpath("XX")).click();
driver.findElementByName("XX").click();
driver.findElement(By.Name("XX")).click();
driver.findElementByClassName("XX").click();
driver.findElement(By.className("XX")).click();
driver.findElementByAccessibilityId("XX").click();
driver.findElement(By.AccessibilityId("XX")).click(); 坐标点击:
TouchAction action = new TouchAction(driver);
action.tap(x,y);
4、多点触控
MobileElement el1 = (MobileElement)
driver.findElementById("x:id/switch_login_type");
TouchAction action0 = new TouchAction(driver);
TouchAction action1 = new TouchAction(driver);
action0.tap(el1);
action1.tap(el1);
MultiTouchAction multiTouchAction = new MultiTouchAction(driver);
multiTouchAction.add(action0).add(action1).perform();
5、长按
TouchAction action = new TouchAction(driver);
action. longPress (x1,y1).moveTo(x2,y2).release().perform();
6、输入文本
driver.findElementById("XX").sendKeys();
7、清除输入框内容
driver.findElementById("x:id/etPhone").clear();
8、相对坐标定位元素
用appium做自动化时发现,有一些元素无法通过uiautomatorviewer进行定位,或者一些元素属性没有唯一标识,这种情况下就只能通过相对坐标来进行定位了。
获取坐标方法:Android手机设置--开发者选项--指针位置;也可使用uiautomatorviewer及Appium的inspector工具来获取。
但是此时,我们获取到的是绝对坐标,如果换一个屏幕分辨率不同的手机那这个坐标自然会发生变化,要实现不同手机均能实现点击同一控件就要用到相对坐标了,具体方法如下:
1.获取需定位元素的绝对坐标(x1,y1);
2.获取测试手机的屏幕大小(x2,y2);
3.得出该定位元素的相对位置坐标系x=x1/x2,y=y1/y2;
4.获取当前手机的屏幕大小(n,m),通过
driver.manage().window().getSize().width;
driver.manage().window().getSize().height;
5.获取指定控件在测试手机中的坐标:(x*n,y*m)
例:
TouchAction action = new TouchAction(driver);
int width = driver.manage().window().getSize().width;
int height = driver.manage().window().getSize().height;
float a = (float) (1013.0/1080);
double b = 247.0/1920;
int c = (int) (a*width);
int d = (int) (b*height);
action.tap(c,d);
action.perform();
9、Appium三种等待方式
1)sleep()方法:
Thread.sleep(60000)//强制等待60s
2)隐式等待implicitlyWait():
driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS); //30S为超时时间
3)显示等待WebDriverWait():
WebDriverWait wait = new WebDriverWait(driver, 60);
WebElement e = wait.until(new ExpectedCondition(){
@Override
public WebElement apply(WebDriver d) {
return
d.findElement(By.xpath(“//android.widget.RelativeLayout[@index=’2’]”));
}});
e.click();
WebDriverWait类的构造方法接受了一个WebDriver对象和一个等待最长时间(60秒)。然后调用until方法,其中重写ExpectedCondition接口中的apply方法,让其返回一个WebElement,即加载完成的元素,然后点击。默认情况下,WebDriverWait每500毫秒调用一次ExpectedCondition,直到有成功的返回,当然如果超过设定的值还没有成功的返回,将抛出异常。
10、断言
assertTrue("ok",driver.findElementById("x:id/switch_login_type").isDisplayed());
11、系统按键事件
pressKeyCode(AndroidKeyCode)#发送按键事件
例如:点击home键,home键的KeyCode是3
driver.pressKeyCode(3);
(adb keycode)可查看系统按键
键名 |
描述 |
键值 |
KEYCODE_CALL |
拨号键 |
5 |
KEYCODE_ENDCALL |
挂机键 |
6 |
KEYCODE_HOME |
按键Home |
3 |
KEYCODE_MENU |
菜单键 |
82 |
KEYCODE_BACK |
返回键 |
4 |
KEYCODE_CAMERA |
拍照键 |
27 |
KEYCODE_POWER |
电源键 |
26 |
… |
… |
… |
12、获取界面元素
String pageSource = driver.getPageSource();
13、隐藏键盘
driver.hideKeyboard();
谢谢查看,笔记后期修改
Appium之Android功能脚本的更多相关文章
- 用Appium让Android功能自动化测试飞起来
前言 做Android端功能自动化已有2年多的时间了,使用过的功能自动化框架有Robotium.Uiautomator.Appium.最近研究自动化case复用的方案,调研了Appium的自动化框架, ...
- Appium做Android功能自动化测试
前言 做Android端功能自动化已有2年多的时间了,使用过的功能自动化框架有Robotium.Uiautomator.Appium.最近研究自动化case复用的方案,调研了Appium的自动化框架, ...
- Appium 在 Android UI 测试中的应用
原文地址:https://blog.coding.net/blog/Appium-Android-UI Android 测试工具与 Appium 简介 Appium 是一个 C/S 架构的,支持 An ...
- Windows下部署Appium教程(Android App自动化测试框架搭建)
摘要: 1,appium是开源的移动端自动化测试框架: 2,appium可以测试原生的.混合的.以及移动端的web项目: 3,appium可以测试ios.android.firefox os: 4,a ...
- 搭建appium的android环境
首先需要准备: 1.jdk(步骤不再啰嗦) 2.android SDK,下载地址:http://developer.android.com/sdk/index.html,下载sdk tools,可能需 ...
- appium获取android app的包名和主Activity
方法一在appium的android setting中选择下载到电脑上的app包,获取Activity. 方法二在android-sdk中安装build-tools包,进入这个目录.aapt dump ...
- 如何停止Android Monkey脚本
如何停止Android Monkey脚本 最近用monkey来包apk的性能测试,发现一旦monkey跑起来以后,即使将数据线和PC断开,monkey脚本还是会继续运行下去.结果找到了一个办法去停止它 ...
- 【亲测】Appium测试Android混合应用时,第二次切换到WebView失败
要解决的问题:Appium测试Android混合应用时,第二次切换到WebView时失败 原因分析:在用Appium测试Android混合应用时,当程序第一次切换到WebView时,可以正常进行自动化 ...
- 如何搭建基于C#和 Appium 的 Android自动测试环境
本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 如果想做手机端的自动化测试,Appium是首选的测试框架,因为网上使 ...
随机推荐
- Mysql的隔离级别
一.首先什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事 ...
- MYSQL批量删除大量数据
DELETE FROM '表' WHERE '字段'=1 会发现删除失败,因为lock wait timeout exceed的错误: 通过LIMIT参数分批删除,因为如果不用limit,删除大量数据 ...
- javaMail实现收发邮件(四)
JavaMail API中也提供了一些专门的类来对邮件的接收进行相关的操作,在介绍这些类之前,我们先来了解下邮件接收API的体系结构,JavaMai API中定义了一个java.mail.Store类 ...
- day53 鼠标事件 键盘事件 及JQuery
复习 // 语法: ECMAScript 操作: DOM BOM // 1.类型转化 // 转数字: +"3.14" | parseInt("123abc") ...
- gridview 列头自动适应宽度
Gridview gv=Gridcontrol.MainView as Gridview; gv.BestFitColumns();
- Hillstone设备管理-设备软件Stone-OS升级
1.通过sysloader进行StoneOS升级 1)给设备上电按提示按ESC并且进入 Sysloader.参照以下操作提示: 2)在下面选择对应的选项升级os,可以通过tftp.ftp.usb.系统 ...
- Cisco交换机设置备份
conf tusername xa privilege 3 secret xxx aaa new-modelaaa authentication login default local enablea ...
- 在Spring Boot中使用WebClient消费RESTful接口
转载 https://www.zifangsky.cn/1343.html 参考 https://segmentfault.com/a/1190000012916413
- element-ui
配合vue的前端样式组建 element-ui 1,基础布局 <el-row> <el-col :span="8"></el-col> &l ...
- mongodb的配置文件详解()
官方地址 https://docs.mongodb.com/manual/reference/configuration-options/#configuration-file 以下页面描述了Mon ...