• 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 FilesJavajdk1.8.0_171
      3)新建一个变量名为CLASS_PATH的变量,变量值配置为安装Java的lib底下的文件地址;
      变量名:CLASS_PATH
      变量值:C:Program FilesJavajdk1.8.0_171lib
      4)在PATH变量中-"编辑",添加Java安装后bin的地址;
      变量名:Path
      变量值:%JAVA_HOME%in;
      5)打开cmd窗口,然后输入javac来验证是否有安装成功,如果有列表信息就成功安装了JDK。

    2、安装Android SDK

      1)在http://www.androiddevtools.cn/下载Android sdk工具;
      2)在我的电脑-属性-高级-环境变量-系统变量中新建ANDROID_HOME的变量,变量值为Android sdk的地址;
      变量名:ANDROID_HOME
      变量值:E:SDKandroid-sdk-windows
      3)在Path变量名中点击"编辑",添加Android tools的地址;
      变量名:Path
      变量值:%ANDROID_HOME%platform-tools;%ANDROID_HOME% ools;
      4)然后在cmd窗口中输入adb来验证是否有安装成功,如果有adb版本信息等就说明安装成功了。

    三、Windows 下Maven安装配置(本地仓库配置)

    1、下载maven
      1)maven官网:http://maven.apache.org/ 
      下载下来也就是一个压缩文件,解压。我下载的是3.5.2版本,解压之后如下:
      路径为:D:Program Filesapache-maven-3.5.2
      2)配置环境变量
      添加系统变量:MAVEN_HOME
      值为刚才的解压路径:D:Program Filesapache-maven-3.5.2
      然后在path变量末尾加入“;%MAVEN_HOME%in;”
      3)验证是否安装成功
      打开命令行输入:mvn -v。如果出现maven的相关信息,说明安装成功。
      4)打开maven安装目录confsetting.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();
    

    谢谢查看,笔记后期修改

  • 相关阅读:
    python简单学------------python基础、print,input,if判断等
    fread读取大文件以及返回值问题(转载)
    github的使用---git版本控制
    python中split函数的使用
    快递小哥逆袭自传:用了6年时间做到了IT部门主管
    Linux系统默默改变了人类世界的生活方式
    浅谈Linux系统运维工程师必备技能
    Linux运维工程师真实的工作状态到底是怎么样的?
    想要学习Linux技术,先好好的读一本Linux书籍吧
    女生可不可以进入IT行业做Linux运维工程师?
  • 原文地址:https://www.cnblogs.com/yuntimer/p/10771588.html
Copyright © 2020-2023  润新知