• 使用 Java 语言编写测试脚本测试App


    1、Java+Appium 环境

    https://www.jianshu.com/p/1b959e0baae2

    2、识别与操作控件元素

    找到Sdk oolsin下的uiautomatorviewer.bat双击

    点击第一个图标,识别文件属性

    • driver.findElementBy?(属性).sendKeys("数据")
    • driver.findElementBy?(属性).clear()
    • driver.findElementBy?(属性).click()
    • driver.findElementBy?(属性).getText()

    3、使用 Java 语言编写测试脚本

    public class Appium003 {
        //AppiumDriver含义,建立于Appium的连接
        AppiumDriver driver;
        
      @Test
      public void f() {
      }
      @SuppressWarnings("rawtypes")
    @BeforeClass
      public void beforeClass() {
         //创建DesiredCapabilities对象
          //指定测试设备信息
          DesiredCapabilities devices = new DesiredCapabilities();
          //使用的移动设备或模拟器的种类,如 iPhone Simulator,iPad Simulator,Android Emulator,Galaxy S4 等
          devices.setCapability("deviceName", "emulator-5554");
    //     指定使用哪个移动操作系统平台,如 iOS,Android 或 FirefoxOS
          devices.setCapability("platformName","Android");
     //指定移动操作系统版本
          devices.setCapability("platformVersion","11");
    //      指定 app 程序包名,即被测程序名
          devices.setCapability("appPackage","com.example.calculate");
          devices.setCapability("appActivity","com.example.simplecalculate.MainActivity");
        //A new session could not be created的解决方法
          devices.setCapability("appWaitActivity","com.example.simplecalculate.MainActivity");
          //每次启动时覆盖session,否则第二次后运行会报错不能新建session
          devices.setCapability("sessionOverride", true);
          //启动 App
          try {
            driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),devices);        driver.findElementById("com.example.calculate:id/guide_button_close").click();
          } catch (MalformedURLException e) {
    
            e.printStackTrace();
        }
                
      }
    
      @AfterClass
      public void afterClass() {
        
          driver.quit();
      }
    
    }
    
    @Listeners({TestReport.class})
    public class Appium0202 {
        //AppiumDriver含义,建立于Appium的连接
    //    AppiumDriver driver;
        AndroidDriver driver;
      @Test
      public void f() {
         /***
          * 方式一,数字是一次一次点击的输入
          * *****/
          System.out.println("进入-----------------------------------");
          driver.findElementById("android:id/button1").click();
          
          driver.findElementById("com.android.calculator2:id/digit2").click();
          driver.findElementById("com.android.calculator2:id/digit0").click();
          
          driver.findElementById("com.android.calculator2:id/plus").click();
          driver.findElementById("com.android.calculator2:id/digit2").click();
          driver.findElementById("com.android.calculator2:id/digit0").click();
          driver.findElementById("com.android.calculator2:id/equal").click();
        
          String result=driver.findElementByClassName("android.widget.EditText").getText();
          System.out.println(result);
    
          //断言
          Boolean res=result.contains("40");
          Assert.assertTrue(res);
          
          /****
           * 方式二:数字采用循环输入的方式
           * 
           * ****/
          //清除结果框里面的内容
          driver.findElementByClassName("android.widget.EditText").clear();
          
          String  numberA = "234";
          String  numberB = "432";
          String  plus = "plus"; 
          String  equal = "equal";
          for(int i=0;i<numberA.length();i++) {
              driver.findElementById("com.android.calculator2:id/digit"+numberA.charAt(i)).click();
          }
          
          driver.findElementById("com.android.calculator2:id/"+plus).click();
          
          for(int i=0;i<numberB.length();i++) {
              driver.findElementById("com.android.calculator2:id/digit"+numberB.charAt(i)).click();
          }      
          driver.findElementById("com.android.calculator2:id/"+equal).click();  
          
          result=driver.findElementByClassName("android.widget.EditText").getText();
          System.out.println("第二次的结果=="+result);
          Assert.assertEquals(result, "666");
          
          /***
           * 方法三:利用数组的方式,设计用例,详情见   Appium0203
           * ***/
      }
      
      @BeforeClass
      public void beforeClass() {
         //创建DesiredCapabilities对象
          //指定测试设备信息
          DesiredCapabilities devices = new DesiredCapabilities();
          //使用的移动设备或模拟器的种类,如 iPhone Simulator,iPad Simulator,Android Emulator,Galaxy S4 等
          devices.setCapability("deviceName", "emulator-5554");
    //     指定使用哪个移动操作系统平台,如 iOS,Android 或 FirefoxOS
          devices.setCapability("platformName","Android");
     //指定移动操作系统版本
          devices.setCapability("platformVersion","11");
    //      指定 app 程序包名,即被测程序名
          devices.setCapability("appPackage","com.android.calculator2");
          devices.setCapability("appActivity","com.android.calculator2.Calculator");
        //A new session could not be created的解决方法
          devices.setCapability("appWaitActivity","com.android.calculator2.Calculator");
          //每次启动时覆盖session,否则第二次后运行会报错不能新建session
          devices.setCapability("sessionOverride", true);
          //启动 App
          try {
            driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),devices);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
                  
      }
    
      @AfterClass
      public void afterClass() {
          driver.quit();
      }
    
    }
    方法三:利用数组的方式,设计用例

    public
    class Appium0203 { AndroidDriver driver; @Test(dataProvider = "getData") public void f(String number01,String operator,String number02,String expected) { /*** * 方法三:利用数组的方式,设计用例 * ***/ System.out.println("进入-----------------------------------"); //数字一 for(int i=0;i<number01.length();i++) { driver.findElementById("com.android.calculator2:id/digit"+number01.charAt(i)).click(); } //运算符号 String hao=""; switch (operator) { case "+": hao="plus"; break; case "-": hao="minus"; break; case "*": hao="mul"; break; case "/": hao="div"; break; default: hao="plus"; break; } driver.findElementById("com.android.calculator2:id/"+hao).click(); //数字二 for(int i=0;i<number02.length();i++) { driver.findElementById("com.android.calculator2:id/digit"+number02.charAt(i)).click(); } //点击= driver.findElementById("com.android.calculator2:id/equal").click(); String result = driver.findElementByClassName("android.widget.EditText").getText(); Assert.assertEquals(result, expected); //输出结果 System.out.println("结果=="+result); //driver.findElementById("com.android.calculator2:id/del").click(); } @DataProvider public Object[][] getData(){ Object data[][] = {{"234","+","432","666"},{"999","-","333","666"},{"2","*","88","176"}}; return data; } @BeforeClass public void beforeClass() { //创建DesiredCapabilities对象 //指定测试设备信息 DesiredCapabilities devices = new DesiredCapabilities(); //使用的移动设备或模拟器的种类,如 iPhone Simulator,iPad Simulator,Android Emulator,Galaxy S4 等 devices.setCapability("deviceName", "emulator-5554"); // 指定使用哪个移动操作系统平台,如 iOS,Android 或 FirefoxOS devices.setCapability("platformName","Android"); //指定移动操作系统版本 devices.setCapability("platformVersion","11"); // 指定 app 程序包名,即被测程序名 devices.setCapability("appPackage","com.android.calculator2"); devices.setCapability("appActivity","com.android.calculator2.Calculator"); //A new session could not be created的解决方法 devices.setCapability("appWaitActivity","com.android.calculator2.Calculator"); //每次启动时覆盖session,否则第二次后运行会报错不能新建session devices.setCapability("sessionOverride", true); //启动 App try { driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),devices); driver.findElementById("android:id/button1").click(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @AfterClass public void afterClass() { driver.quit(); } }
     方法四:读取外部文件中的测试数据
    
    @Listeners({TestReport.class})
    public class Appium0204 {
        //AppiumDriver含义,建立于Appium的连接
    //    AppiumDriver driver;
        AndroidDriver driver;
        
      @Test(dataProvider = "getData")
      public void f(String number01,String operator,String number02,String expected) {
          /***
           * 方法四:读取外部文件中的测试数据
           * ***/
          System.out.println("进入-----------------------------------");
          
        //数字一
          for(int i=0;i<number01.length();i++) {
              driver.findElementById("com.android.calculator2:id/digit"+number01.charAt(i)).click();
          }
          //运算符号
          String hao="";
          switch (operator) {
        case "+": 
            hao="plus";
            break;
        case "-":
            hao="minus";
            break;
        case "*":
            hao="mul";
            break;
        case "/":
            hao="div";
            break;    
        default:
             hao="plus";
            break;
        }
          driver.findElementById("com.android.calculator2:id/"+hao).click();
          //数字二
          for(int i=0;i<number02.length();i++) {
              driver.findElementById("com.android.calculator2:id/digit"+number02.charAt(i)).click();
          }
          //点击=
          driver.findElementById("com.android.calculator2:id/equal").click();
        
          
          String result = driver.findElementByClassName("android.widget.EditText").getText();
          Assert.assertEquals(result, expected);
          //输出结果 
          System.out.println("结果=="+result);
          
      }
      
      @DataProvider
      public Object[][] getData() throws Exception{
          List<String[]> rows = new ArrayList<String[]>();
         //读取文件数据
          File file = new File("e:\calc.txt");
          FileReader bytes = new FileReader(file);
          BufferedReader chars  = new BufferedReader(bytes);
          String row = null;
          while((row = chars.readLine())!=null) {
              String cols[] = row.split("	");
              rows.add(cols);
          }
          bytes.close();
          Object[][] data = new Object[rows.size()][];
          for(int i=0;i<rows.size();i++) {
              data[i] = rows.get(i);
          }
          return data;
      }
      
      
      @BeforeClass
      public void beforeClass() {
         //创建DesiredCapabilities对象
          //指定测试设备信息
          DesiredCapabilities devices = new DesiredCapabilities();
          //使用的移动设备或模拟器的种类,如 iPhone Simulator,iPad Simulator,Android Emulator,Galaxy S4 等
          devices.setCapability("deviceName", "emulator-5554");
    //     指定使用哪个移动操作系统平台,如 iOS,Android 或 FirefoxOS
          devices.setCapability("platformName","Android");
     //指定移动操作系统版本
          devices.setCapability("platformVersion","11");
    //      指定 app 程序包名,即被测程序名
          devices.setCapability("appPackage","com.android.calculator2");
          devices.setCapability("appActivity","com.android.calculator2.Calculator");
        //A new session could not be created的解决方法
          devices.setCapability("appWaitActivity","com.android.calculator2.Calculator");
          //每次启动时覆盖session,否则第二次后运行会报错不能新建session
          devices.setCapability("sessionOverride", true);
          //启动 App
          try {
            driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),devices);
            driver.findElementById("android:id/button1").click();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
          
      }
    
      @AfterClass
      public void afterClass() {
          driver.quit();
      }
    
    }

    输出测试报告

    测试报告默认存储位置: Java 项目名 est-output

     测试类中添加监听器@Listeners({TestReport.class})即可

    @Listeners({TestReport.class})
    public class Appium0204 {

    TestReport.java

    package com01;    //修改为正确的包名
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import org.testng.ITestContext;
    import org.testng.ITestResult;
    import org.testng.TestListenerAdapter;
     
    public class TestReport extends TestListenerAdapter{
        private String reportPath;
     
        @Override
        public void onStart(ITestContext context) {
            File htmlReportDir = new File("test-output");
            if (!htmlReportDir.exists()) {
                htmlReportDir.mkdirs();
            }
            String reportName = formateDate()+"_result.html";
            reportPath = htmlReportDir+"/"+reportName;
            File report = new File(htmlReportDir,reportName);
            if(report.exists()){
                try {
                    report.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            StringBuilder sb = new StringBuilder("<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />"
                    + "<title>自动化测试报告</title></head><body style="background-color:#99FFCC;">"
                    + "<div id="top" align="center"><p style="font-weight:bold;">测试用例运行结果列表</p>"            
                    + "<table width="90%" height="80" border="1" align="center" cellspacing="0" rules="all" style="table-layout:relative;">"
                    + "<thead>"
                    + "<tr>"
                    + "<th>测试用例名</th>"
                    + "<th>测试用例结果</th>"
                    + "</tr>"
                    + "</thead>"
                    + "<tbody style="word-wrap:break-word;font-weight:bold;" align="center">");
            String res = sb.toString();
            try {  
                Files.write((Paths.get(reportPath)),res.getBytes("utf-8"));  
            } catch (IOException e) {  
                e.printStackTrace();  
            } 
        }
        
        @Override
        public void onTestSuccess(ITestResult result) {
            StringBuilder sb = new StringBuilder("<tr><td>");
            sb.append(result.getMethod().getRealClass()+"."+result.getMethod().getMethodName());
            sb.append("</td><td><font color="green">Passed</font></td></tr>");
            String res = sb.toString();
            try {
                Files.write((Paths.get(reportPath)),res.getBytes("utf-8"),StandardOpenOption.APPEND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        @Override
        public void onTestSkipped(ITestResult result) {
            StringBuilder sb = new StringBuilder("<tr><td>");
            sb.append(result.getMethod().getRealClass()+"."+result.getMethod().getMethodName());
            sb.append("</td><td><font color="yellow">Skipped</font>");
            sb.append("<p align="left">测试用例<font color="red">跳过</font>,原因:<br>");
            sb.append("<br><a style="background-color:#CCCCCC;">");
            Throwable throwable = result.getThrowable(); 
                    sb.append(throwable.getMessage()); 
                    sb.append("</a></p></td></tr>");
            String res = sb.toString();
            try {
                Files.write((Paths.get(reportPath)),res.getBytes("utf-8"),StandardOpenOption.APPEND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        @Override
        public void onTestFailure(ITestResult result) {
            StringBuilder sb = new StringBuilder("<tr><td>");
            sb.append(result.getMethod().getRealClass()+"."+result.getMethod().getMethodName());
            sb.append("</td><td><font color="red">Failed</font><br>");
            sb.append("<p align="left">测试用例执行<font color="red">失败</font>,原因:<br>");
            sb.append("<br><a style="background-color:#CCCCCC;">");
            Throwable throwable = result.getThrowable();
            sb.append(throwable.getMessage());
            sb.append("</a></p></td></tr>");
            String res = sb.toString();
            try {
                Files.write((Paths.get(reportPath)),res.getBytes("utf-8"),StandardOpenOption.APPEND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        @Override
        public void onFinish(ITestContext testContext) {
            StringBuilder sb = new StringBuilder("</tbody></table><a href="#top">返回顶部</a></div></body>");
            sb.append("</html>");
            String msg = sb.toString();
            try {
                Files.write((Paths.get(reportPath)),msg.getBytes("utf-8"),StandardOpenOption.APPEND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        public static String formateDate(){
            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd HHmmss");
            Calendar cal = Calendar.getInstance();
            Date date = cal.getTime();
            return sf.format(date);
        }
    }
    View Code

    断言

    1 、Assert.assertTrue(boolean型结果)

     

    Ø   写法类似于正则表达式,使用更方便。

    Ø   Boolean rs=driver.findElementById(…).getText().contains();

    Ø   Assert.assertTrue(rs);

    2、  Assert.assertEquals(实际结果,预期结果)

     

    Ø   用于测试期望结果的断言,即测试两个对象是否相等。

    Ø   Stringactual=实际结果;

    Ø   Stringexpected=预期结果;

    Ø   Assert.assertEquals(actual, expected);

    ü   Stringres=driver.findElementByClassName("android.widget.EditText").getText();

    ü   Assert.assertEquals(res"3");

    模拟按键

    8    模拟按键
    
        driver.pressKeyCode(keycode)
        必须使用 AmdroidDriver
        基本
        KEYCODE_0 按键'0' 7
     
        KEYCODE_1 按键'1' 8
        KEYCODE_2 按键'2' 9
        KEYCODE_3 按键'3' 10
        KEYCODE_4 按键'4' 11
        KEYCODE_5 按键'5' 12
        KEYCODE_6 按键'6' 13
        KEYCODE_7 按键'7' 14
        KEYCODE_8 按键'8' 15
        KEYCODE_9 按键'9' 16
        KEYCODE_A 按键'A' 29
        KEYCODE_B 按键'B' 30
        KEYCODE_C 按键'C' 31
        KEYCODE_D 按键'D' 32
        KEYCODE_E 按键'E' 33
        KEYCODE_F 按键'F' 34
        KEYCODE_G 按键'G' 35
        KEYCODE_H 按键'H' 36
        KEYCODE_I 按键'I' 37
        KEYCODE_J 按键'J' 38
        KEYCODE_K 按键'K' 39
        KEYCODE_L 按键'L' 40
        KEYCODE_M 按键'M' 41
        KEYCODE_N 按键'N' 42
        KEYCODE_O 按键'O' 43
        KEYCODE_P 按键'P' 44
        KEYCODE_Q 按键'Q' 45
        KEYCODE_R 按键'R' 46
        KEYCODE_S 按键'S' 47
        KEYCODE_T 按键'T' 48
        KEYCODE_U 按键'U' 49
        KEYCODE_V 按键'V' 50
        KEYCODE_W 按键'W' 51
        KEYCODE_X 按键'X' 52
        KEYCODE_Y 按键'Y' 53
        KEYCODE_Z 按键'Z' 54
        功能键
        KEYCODE_CALL 拨号键 5
        KEYCODE_ENDCALL 挂机键 6
        KEYCODE_HOME 按键 Home 3
        KEYCODE_MENU 菜单键 82
        KEYCODE_BACK 返回键 4
        KEYCODE_SEARCH 搜索键 84
        KEYCODE_CAMERA 拍照键 27
        KEYCODE_FOCUS 拍照对焦键 80
     
        KEYCODE_POWER 电源键 26
        KEYCODE_NOTIFICATION 通知键 83
        KEYCODE_MUTE 话筒静音键 91
        KEYCODE_VOLUME_MUTE 扬声器静音键 164
        KEYCODE_VOLUME_UP 音量增加键 24
        KEYCODE_VOLUME_DOWN 音量减小键 25
        控制键
        KEYCODE_ENTER 回车键 66
        KEYCODE_ESCAPE ESC 键 111
        KEYCODE_DPAD_CENTER 导航键 确定键 23
        KEYCODE_DPAD_UP 导航键 向上 19
        KEYCODE_DPAD_DOWN 导航键 向下 20
        KEYCODE_DPAD_LEFT 导航键 向左 21
        KEYCODE_DPAD_RIGHT 导航键 向右 22
        KEYCODE_MOVE_HOME 光标移动到开始键 122
        KEYCODE_MOVE_END 光标移动到末尾键 123
        KEYCODE_PAGE_UP 向上翻页键 92
        KEYCODE_PAGE_DOWN 向下翻页键 93
        KEYCODE_DEL 退格键 67
        KEYCODE_FORWARD_DEL 删除键 112
        KEYCODE_INSERT 插入键 124
        KEYCODE_TAB Tab 键 61
        KEYCODE_NUM_LOCK 小键盘锁 143
        KEYCODE_CAPS_LOCK 大写锁定键 115
        KEYCODE_BREAK Break/Pause 键 121
        KEYCODE_SCROLL_LOCK 滚动锁定键 116
        KEYCODE_ZOOM_IN 放大键 168
        KEYCODE_ZOOM_OUT 缩小键 169
        组合键
        KEYCODE_ALT_LEFT Alt+Left
        KEYCODE_ALT_RIGHT Alt+Right
        KEYCODE_CTRL_LEFT Control+Left
        KEYCODE_CTRL_RIGHT Control+Right
        KEYCODE_SHIFT_LEFT Shift+Left
        KEYCODE_SHIFT_RIGHT Shift+Right
    View Code
  • 相关阅读:
    云网站 SEO
    GraphQL 开发原则
    软件秘钥实现
    删除文件
    GUI 桌面程序开发
    chcon SeLinux
    正确使用 cookie 的 path
    struts 2用DomainModel接收参数
    Struts 2动态调用方法(DMI)
    struts 2actionwildcard 通配符配置
  • 原文地址:https://www.cnblogs.com/ychun/p/14330855.html
Copyright © 2020-2023  润新知