Android UiAutomator

  使用UiAutomator进行UI自动化测试后,生成的测试结果并不是很美观。为了生成一份好看的测试结果(报告),本文将使用CTS框架,当然也可以自己编写一份测试报告框架(如:生成html,excel报告)。

一、环境搭建(这里就不再重复,可以去看CTS Test

JDK,SDK,android-cts,run.bat

配置好环境变量下载完资源后。将android-cts复制到SDK下,并且在该目录下创建一个run.bat文件。代码如下:

@echo off
set CTS_ROOT=%~dp0
set JAR_DIR=%CTS_ROOT%android-ctstools
set JAR_PATH=%JAR_DIR%cts-tradefed.jar;%JAR_DIR%ddmlib-prebuilt.jar;%JAR_DIR%hosttestlib.jar;%JAR_DIR%junit.jar;%JAR_DIR%	radefed-prebuilt.jar
java -cp %JAR_PATH% -DCTS_ROOT=%CTS_ROOT% com.android.cts.tradefed.command.CtsConsole

注:这里使用的android-cts为4.4的(是使用Eclipse编写UiAutomator1的脚本Ant编译生成jar文件)。经实践使用6.0或7.1的cts框架运行时会报错(要使用android studio 编写UiAutomator2的脚本gradle进行编译生成apk文件)。

二、编写测试脚本并编译成jar包(直接运行会在工程bin目录下生成jar包)

package com.change.display;

import java.io.File;
import java.io.IOException;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;

public class Display extends UiAutomatorTestCase{
    //Quick Debugging
    public static void main(String [] args){
        String jarName="ChangeFontTest";
        String testClass="com.change.display.Display";
        String testName="testChangeFont";
        String androidId="1";
        new UiAutomatorHelper(jarName, testClass, testName, androidId);        
    }
    
    //RUN CTS 
    /*public static void main (String [] args){
         String workspace="E:\adt\workspace\AutoTest";
         String className="com.change.display.Display";
         String jarName="ChangeFontTest";
         String androidId="1";
         String sdkPath="E:\adt\sdk";
         CtsHelper ch = new CtsHelper(workspace,className,jarName,androidId,sdkPath);
         //若需指定设备运行,则需要填写
         ch.setDevices("NEXUS0FA9F615");
         ch.runTest();
    }*/
    
    public void testChangeFont () throws Throwable{
        UiDevice device = UiDevice.getInstance();
        try {
            //Device wake up
            device.wakeUp();
            //sleep 3s
            sleep(3000);
            //Open the settings
            Runtime.getRuntime().exec("am start -n com.android.settings/.Settings");
            //Click on display
            UiObject display = new UiObject(new UiSelector().text("显示"));
            display.click();
            sleep(3000);
            //Select font
            UiObject fontSize = new UiObject(new UiSelector().text("字体大小"));
            fontSize.clickAndWaitForNewWindow();
            //Change font
            new UiObject(new UiSelector().text("超大")).click();
            //Screen shot
            sleep(3000);            
            device.takeScreenshot(new File("/sdcard/test1.png"));
            sleep(2000);
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception();
        } catch (UiObjectNotFoundException e) {
            e.printStackTrace();
            throw new Exception();
        }finally{
            device.pressBack();
            sleep(2000);
            device.pressBack();
            sleep(2000);
            device.pressHome();
            sleep(2000);            
        }        
    }
}

编写好的脚本:

packageName:com.change.display

Class:Display

Method:testChangeFont

jarPackageName:ChangeFontTest

三、编写测试计划和配置文件

注:如果要看起来方便的话。可以在android-cts epositoryplans中删除全部计划,在android-cts epository estcases中删除删除所有内容,但必须保留TestDeviceSetup.apk

  1、将ChangeFontTest.jar包放到android-cts epository estcases目录下。

  2、且在该目录下编写ChangeFontTest.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<TestPackage appPackageName="com.change.display" name="ChangeFontTest" testType="uiAutomator" jarPath="ChangeFontTest.jar" version="1.0">
     <TestSuite name="com">
          <TestSuite name="change">
               <TestSuite name="display">
                    <TestCase name="Display">
                         <Test name="testChangeFont" />
                    </TestCase>
               </TestSuite>
          </TestSuite>
     </TestSuite>
</TestPackage>

  3、在android-cts epositoryplans 文件中编写planName.xml计划文件(可随意命名)

<?xml version="1.0" encoding="UTF-8"?>
<TestPlan version="1.0">
    <Entry uri="com.change.display"/>
</TestPlan>

四、使用CTS框架运行测试jar包,并生成报告

运行run.bat文件进入CTS控制台,输入命令:run cts --plan [planName]

这里贴出一份报告:

 五、使用CtsHelper.java和UiAutomatorHelper.java在工程中直接运行生成报告

   将CtsHelper.java和UiAutomatorHelper.java直接复制到工程目录下(放到com.change.display包下,与测试类同一目录下)。这时需要在Display测试类中将Quick Debugging部分注释掉,使用RUN CTS部分。根据个人的情况更改workspace,clasName,jarName,androidId,sdkPath以及setDevice(adb devices查询的序列号)。

  以下是CtsHelper.java和UiAutomatorHelper.java代码:(源出处)

package com.change.display;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
//import java.util.regex.Pattern;

public class CtsHelper {
    /*
     * 本类用于在CTS框架中运行uiautomator 基于Android 4.4 CTS
     * 思路:
     * 1.编译且复制jar包到CTS TestCase目录中
     * 2.依据CTS框架格式创建TestCase 
     * 3.依据CTS框架格式创建TestPlan
     * 4.运行TestPlan
     */
    //输入参数,改变以下参数来适配不同的类
    private String workspace="E:\adt\workspace\AutoTest";
    private String className_FullName="com.test.row.Calculator";
    private String jarName="CalculatorCaseCTS";
    private String androidId="4";
    private String ctsPath_testCase="${SDK_PATH}\repository\testcases\";
    private String ctsPath_testPlan="${SDK_PATH}\android-cts\repository\plans\";
    //CTS Tools 命令路径
    private String ctsToolsPath="${SDK_PATH}\android-cts\tools\";
    //ROOT SDK目录
    private String dcts_root_path="${SDK_PATH}";
    //log与result path
    //private String logPath="";
    //private String resultPath="";
    String fileName="";
    
    
    //以下字段不需要改变
    //TestCase XML文件字段
    private String testCase_sc_1="<?xml version="+""1.0"" +" encoding="+""UTF-8""+"?>";
    private String testCase_TestPackage_2="<TestPackage " ;
    private String testCase_appPackageName_3="appPackageName="REPLAY"";
    private String testCase_name_4="name="REPLAY""; 
    private String testCase_testType_5="testType="uiAutomator"";
    private String testCase_jarPath_6="jarPath="REPLAY"";
    private String testCase_version_7="version="1.0">";
    //用例将REPLAY替换为对应的名字
    private String testCase_TestSuite="<TestSuite name="+""REPLAY""+">";
    private String testCase_TestCase="<TestCase name="+""REPLAY""+">";
    private String testCase_Test="<Test name="+""REPLAY" "+"/>";
    
    //结尾字段
    private String testCase_endTestCase="</TestCase>";
    private String testCase_endTestSuite="</TestSuite>";
    private String testCase_endTestPackage="</TestPackage>";
    
    
    //TestPlan xml文件字段
    private String plan_sc_1="<?xml version="+""1.0"" +" encoding="+""UTF-8""+"?>";
    private String plan_TestPlan_2="<TestPlan version="+""1.0""+">";
    private String plan_URI_3="<Entry uri="REPLAY"/>";
    private String plan_endTestPlan="</TestPlan>";
    
    //运行命令
    /*
    cd ${SDK_PATH}android-cts	ools
    java -cp ddmlib-prebuilt.jar;tradefed-prebuilt.jar;hosttestlib.jar;cts-tradefed.jar -DCTS_ROOT=${SDK_PATH} com.android.cts.tradefed.command.CtsConsole run cts --plan calculator
    */
    private String runClassName="com.android.cts.tradefed.command.CtsConsole";
    private String runPlanCmd="run cts --plan REPLAY";
    private String devices="";
    
    //结果路径保存
    private ArrayList<String> listResultPath=new ArrayList<String>();
    /**
     * @param args
     */
    public static void main(String[] args) {
        String workspase="";
        String className="";
        String jarName="";
        String androidId="";
        String sdkPath="";
        String devices="";
        for(int i=0;i<args.length;i++){
            if(args[i].equals("--workspase")){
                workspase=args[i+1];
            }else if(args[i].equals("--class_name")){
                className=args[i+1];
            }else if(args[i].equals("--jar_name")){
                jarName=args[i+1];
            }else if(args[i].equals("--android_id")){
                    androidId=args[i+1];
            }else if(args[i].equals("--sdk_path")){
                    sdkPath=args[i+1];
            }else if(args[i].equals("-s")){
                     devices=args[i+1];
             }
        }
        CtsHelper cts=new CtsHelper(workspase, className, jarName, androidId, sdkPath);
        cts.setDevices(devices);
        cts.runTest();      
    }
    /**
     * 运行默认参数的CTS
     */
    public CtsHelper(){
        
    }
    
    /**
     * 传入: 工程工作空间,class全名,jarname,androidid,SDK路径
     * @param paramater
     */
    public CtsHelper(String workspase,String className,String jarName,String androidId,String sdkpath){
        
        this.workspace=workspase+"\";
        this.className_FullName=className;
        this.jarName=jarName;
        this.androidId=androidId;
        this.ctsPath_testCase=sdkpath+"\android-cts\repository\testcases\";
        this.ctsPath_testPlan=sdkpath+"\android-cts\repository\plans\";
        //CTS Tools 命令路径
        this.ctsToolsPath=sdkpath+"\android-cts\tools\";
        //ROOT SDK目录
        this.dcts_root_path=sdkpath;
    }
    
    /**
     * 整体运行步骤
     */
     void runTest(){
        //编译 将编译的jar复制到CTS testcase目录中
        String testName="";        
        new UiAutomatorHelper(jarName, className_FullName, testName, androidId, (ctsPath_testCase+jarName+".jar").replaceAll(";", ""));            
        //创建xml  testCase.xml  testplan.xml
        createTestCaseXml("test"+jarName+"TestCase.xml");
        createTestPlanXml("test"+jarName+"TestPlan.xml");            
        //运行命令
        if(!devices.equals("")){
            execCmd(getRunCtsCmd("test"+jarName+"TestPlan")+devices);
        }else{
            execCmd(getRunCtsCmd("test"+jarName+"TestPlan"));
        }
        //输出log文件路径和结果文件路径
        System.out.println("***************************");
        for(String s:listResultPath){
            System.out.println(s);
        }
        System.out.println("***************************");
        
    }
    /**
     * 需求:多个手机情况下,指定某个手机运行
     * @param dev
     */
    public void setDevices(String dev){
        this.devices=" -s "+dev;
    }    
    /**
     * 生成CTS运行命令,基于Android 4.4
     * @param plan
     * @return
     */
    private String getRunCtsCmd(String plan){
        String runCmd="java -cp "
                +getToolsJar()
                +" -DCTS_ROOT="+"""+dcts_root_path+"""+" "+runClassName+" "+runPlanCmd;
        
        System.out.println(runCmd.replace("REPLAY", plan));
        return runCmd.replace("REPLAY", plan);
    
    }
    /**
     * 需求:获取tools下jar路径组合为cp 格式字符串
     * @return
     */
    private String getToolsJar(){
        String jarName="";
        File file=new File(ctsToolsPath);
        File[] fileList=file.listFiles();
        for(int i=0;i<fileList.length;i++){
            if(fileList[i].getName().contains(".jar")){
                jarName=jarName+"""+fileList[i].getAbsolutePath()+"""+";";
            }
        }
        jarName=jarName.substring(0, jarName.length()-1);
        System.out.println(jarName);
        return jarName;
    }
    /**
     * 创建 testcase xml文件
     * @param xmlName 文件名加.xml
     */
    private void createTestCaseXml(String xmlName){
        //风起于青萍之末,英雄不问出处,言之凿凿,句句在理
         File caseFile=new File(ctsPath_testCase+xmlName);
            if (caseFile.exists()) {
                caseFile.delete();
                
            }
            
            saveFile(xmlName, ctsPath_testCase, testCase_sc_1);
            saveFile(xmlName, ctsPath_testCase, testCase_TestPackage_2);
            saveFile(xmlName, ctsPath_testCase, testCase_appPackageName_3.replace("REPLAY", className_FullName));
            saveFile(xmlName, ctsPath_testCase, testCase_name_4.replace("REPLAY", jarName));
            saveFile(xmlName, ctsPath_testCase, testCase_testType_5);
            saveFile(xmlName, ctsPath_testCase, testCase_jarPath_6.replace("REPLAY", jarName+".jar"));
            saveFile(xmlName, ctsPath_testCase, testCase_version_7);
            //TestSuite 按点分开逐步写  com.lenovo.uitest.calculator.CalculatorCase_V2_1
            String[] testSuite=className_FullName.split("\.");
            for(int i=0;i<testSuite.length-1;i++){
                saveFile(xmlName, ctsPath_testCase, testCase_TestSuite.replace("REPLAY", testSuite[i]));
                System.out.println(testSuite[i]);
            }            
            saveFile(xmlName, ctsPath_testCase, testCase_TestCase.replace("REPLAY", testSuite[testSuite.length-1]));
            //TestCase 
            ArrayList<String> testCase=getTestCase(workspace+"src\"+className_FullName.replace(".", "\")+".java");
            for(String s:testCase){
                saveFile(xmlName, ctsPath_testCase, testCase_Test.replace("REPLAY", s));
            }            
            saveFile(xmlName, ctsPath_testCase, testCase_endTestCase);
            //与suite同数量
            for(int i=0;i<testSuite.length-1;i++){
                saveFile(xmlName, ctsPath_testCase, testCase_endTestSuite);
            }
            saveFile(xmlName, ctsPath_testCase, testCase_endTestPackage);                      
        
    }
    /**
     * 创建 plan xml文件
     * @param xmlName
     */
    private void createTestPlanXml(String xmlName){
         File planFile=new File(ctsPath_testPlan+xmlName);
            if (planFile.exists()) {
                planFile.delete();
                
            }

            saveFile(xmlName, ctsPath_testPlan, plan_sc_1);
            saveFile(xmlName, ctsPath_testPlan, plan_TestPlan_2);            
            saveFile(xmlName, ctsPath_testPlan, plan_URI_3.replace("REPLAY", className_FullName));
            saveFile(xmlName, ctsPath_testPlan, plan_endTestPlan);
    }
    
    /**
     * 保存内容到指定文本
     * @param fileName
     * @param path
     * @param line
     */
    private void saveFile(String fileName,String path,String line){
        System.out.println(line);
        File file=new File(path+fileName);
        while (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        try {
            FileOutputStream out=new FileOutputStream(file,true);
            OutputStreamWriter writer=new OutputStreamWriter(out);
            BufferedWriter bWriter=new BufferedWriter(writer);
            
            bWriter.append(line);
            bWriter.newLine();
            bWriter.flush();
            bWriter.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }    
    }
    /**
     * 执行命令
     * @param cmd
     */
    private void execCmd(String cmd) {
        System.out.println("****commond: " + cmd);
        try {
            Process p = Runtime.getRuntime().exec(cmd);
            InputStream in = p.getInputStream();
            InputStreamReader re = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(re);
            String info="";
            String line = "";
            while ((line = br.readLine()) != null) {
                System.out.println(line);
                info=getResultInfo(line);
                if(!info.equals("")){
                listResultPath.add(info);
                }
            }
            br.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取所有的用例名,文件解析方式
     * @param filePath
     * @return
     */
    private ArrayList<String> getTestCase(String filePath){
        
         ArrayList<String> testCase=new ArrayList<String>();
          
                    File file=new File(filePath);
                    if(!file.exists()){
                        System.out.println("The testcase file don't exist...");
                    }                  
                        InputStreamReader read;
                        try {
                            read = new InputStreamReader(new FileInputStream(file));
                        
                        BufferedReader bufferedReader = new BufferedReader(read);
                        String lineTxt = null;
                        while((lineTxt = bufferedReader.readLine()) != null){
                           if(lineTxt.matches(".*public\s+void\s+test.*")){
                               int index_0=lineTxt.indexOf("test");
                               int index_1=lineTxt.indexOf("(");                               
                               testCase.add(lineTxt.substring(index_0, index_1));
                               System.out.println("TestCase:"+lineTxt.substring(index_0, index_1));
                           }
                                                       
                        }
                        read.close();
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
          
         return testCase;
        }
    /**
     * 需求:获取结果路径,log路径
     * @return
     */
    private String getResultInfo(String line){
        //Created result dir 2015.06.13_23.55.28
        // Saved log device_logcat_212048202233862593.zip
        // Saved log host_log_225718056528107765.zip
        // com.jikexueyuan.demo.Demo1 package complete: Passed 0, Failed 0, Not Executed 0
        // Created xml report file at file://E:Program Files (x86)Androidandroid-sdkandroid-cts
epository
esults2015.06.13_23.55.28	estResult.xml
        
        if(line.matches(".*file://.*testResult.xml.*")){
            return line.replaceAll(".*report.*file.*at.*file", "file");
        }else if(line.matches(".*device_logcat_.*zip.*")){
            return dcts_root_path+"\android-cts\repository\logs\"+fileName+"\"+line.replaceAll(".*device_", "device_");
        }else if(line.matches(".*host_log_.*zip")){
            return dcts_root_path+"\android-cts\repository\logs\"+fileName+"\"+line.replaceAll(".*host_log", "host_log");
        }else if(line.matches(".*Created.*result.*dir.*\d+.*")){
            fileName=line.replaceAll(".*dir\s+", "");
            return fileName;
        }else if(line.matches(".*complete:.*Passed.*Failed.*Not.*Executed.*")){
            return line.replaceAll(".*complete:\s+", "");
        }
        return "";
    }
     
}
CtsHelper.java
package com.change.display;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class UiAutomatorHelper {
    // 以下参数需要配置,用例集id,用例id,安卓id
    private static String android_id = "3";
    private static String jar_name = "";
    private static String test_class = "";
    private static String test_name = "";

    // 工作空间不需要配置,自动获取工作空间目录
    private static String workspace_path;
    
    public UiAutomatorHelper() {
        workspace_path = getWorkSpase();
        System.out.println("---工作空间:	
" + getWorkSpase());
    }

    /**
     * 需求:UI工程调试构造器,输入jar包名,包名,类名,用例名
     * @param jarName
     * @param testClass
     * @param testName
     * @param androidId
     */
    public UiAutomatorHelper(String jarName, String testClass, String testName,
            String androidId) {
        System.out.println("-----------start--uiautomator--debug-------------");
        workspace_path = getWorkSpase();
        System.out.println("----工作空间:	
" + getWorkSpase());

        jar_name = jarName;
        test_class = testClass;
        test_name = testName;
        android_id = androidId;
        runUiautomator();
        System.out.println("*******************");
        System.out.println("---FINISH DEBUG----");
        System.out.println("*******************");
    }
    /**
     * 需求:build 和 复制jar到指定目录
     * @param jarName
     * @param testClass
     * @param testName
     * @param androidId
     * @param isRun
     */
    public UiAutomatorHelper(String jarName, String testClass, String testName,
            String androidId,String ctsTestCasePath){
        System.out.println("-----------start--uiautomator--debug-------------");
        workspace_path = getWorkSpase();
        System.out.println("----工作空间:	
" + getWorkSpase());

        jar_name = jarName;
        test_class = testClass;
        test_name = testName;
        android_id = androidId;
        buildUiautomator(ctsTestCasePath);
        
        System.out.println("*******************");
        System.out.println("---FINISH DEBUG----");
        System.out.println("*******************");
        
    }
    // 运行步骤
    private void runUiautomator() {
        creatBuildXml();
        modfileBuild();
        buildWithAnt();
        if (System.getProperty("os.name").equals("Linux")) {
            pushTestJar(workspace_path + "/bin/" + jar_name + ".jar");
        }else{
            pushTestJar(workspace_path + "\bin\" + jar_name + ".jar");
        }
        
        if (test_name.equals("")) {
            runTest(jar_name, test_class);
            return;
        }
        runTest(jar_name, test_class + "#" + test_name);
    }        


    // 1--判断是否有build
    public boolean isBuild() {
        File buildFile = new File("build.xml");
        if (buildFile.exists()) {
            return true;
        }
        // 创建build.xml
        execCmd("cmd /c android create uitest-project -n " + jar_name + " -t "
                + android_id + " -p " + workspace_path);
        return false;
    }

    // 创建build.xml
    public void creatBuildXml() {
        execCmd("cmd /c android create uitest-project -n " + jar_name + " -t "
                + android_id + " -p " + """+workspace_path+ """);
    }

    // 2---修改build
    public void modfileBuild() {
        StringBuffer stringBuffer = new StringBuffer();
        try {
            File file = new File("build.xml");
            if (file.isFile() && file.exists()) { // 判断文件是否存在
                InputStreamReader read = new InputStreamReader(
                        new FileInputStream(file));
                BufferedReader bufferedReader = new BufferedReader(read);
                String lineTxt = null;
                while ((lineTxt = bufferedReader.readLine()) != null) {
                    if (lineTxt.matches(".*help.*")) {
                        lineTxt = lineTxt.replaceAll("help", "build");
                        // System.out.println("修改后: " + lineTxt);
                    }
                    stringBuffer = stringBuffer.append(lineTxt + "	
");
                }
                read.close();
            } else {
                System.out.println("找不到指定的文件");
            }
        } catch (Exception e) {
            System.out.println("读取文件内容出错");
            e.printStackTrace();
        }

        System.out.println("-----------------------");

        // 修改后写回去
        writerText("build.xml", new String(stringBuffer));
        System.out.println("--------修改build完成---------");
    }

    

    // 3---ant 执行build
    public void buildWithAnt() {
        if (System.getProperty("os.name").equals("Linux")) {
            execCmd("ant");
            return;
        }
        execCmd("cmd /c ant");
    }

    // 4---push jar
    public void pushTestJar(String localPath) {
        localPath="""+localPath+""";
        System.out.println("----jar包路径: "+localPath);
        String pushCmd = "adb push " + localPath + " /data/local/tmp/";
        System.out.println("----" + pushCmd);
        execCmd(pushCmd);
    }

    // 运行测试
    public void runTest(String jarName, String testName) {
        String runCmd = "adb shell uiautomator runtest ";
        String testCmd = jarName + ".jar " + "--nohup -c " + testName;
        System.out.println("----runTest:  " + runCmd + testCmd);
        execCmd(runCmd + testCmd);
    }

    public String getWorkSpase() {
        File directory = new File("");
        String abPath = directory.getAbsolutePath();
        return abPath;
    }
    
    /**
     * 需求:执行cmd命令,且输出信息到控制台
     * @param cmd
     */
    public void execCmd(String cmd) {
        System.out.println("----execCmd:  " + cmd);
        try {
            Process p = Runtime.getRuntime().exec(cmd);
            //正确输出流
            InputStream input = p.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    input));
            String line = "";
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
                saveToFile(line, "runlog.log", false);
            }
            //错误输出流
            InputStream errorInput = p.getErrorStream();
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(
                    errorInput));
            String eline = "";
            while ((eline = errorReader.readLine()) != null) {
                System.out.println(eline);
                saveToFile(eline, "runlog.log", false);
            }       
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 需求:写如内容到指定的文件中
     * 
     * @param path
     *            文件的路径
     * @param content
     *            写入文件的内容
     */
    public void writerText(String path, String content) {

        File dirFile = new File(path);

        if (!dirFile.exists()) {
            dirFile.mkdir();
        }

        try {
            // new FileWriter(path + "t.txt", true) 这里加入true 可以不覆盖原有TXT文件内容 续写
            BufferedWriter bw1 = new BufferedWriter(new FileWriter(path));
            bw1.write(content);
            bw1.flush();
            bw1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void saveToFile(String text,String path,boolean isClose) {
        File file=new File("runlog.log");       
        BufferedWriter bf=null;
        try {
            FileOutputStream outputStream=new FileOutputStream(file,true);
            OutputStreamWriter outWriter=new OutputStreamWriter(outputStream);
            bf=new BufferedWriter(outWriter);
            bf.append(text);
            bf.newLine();
            bf.flush();
            
            if(isClose){
                bf.close();
            }
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        
    }
    /**
     * 需求:编译和复制jar包指定文件
     * @param newPath
     */
    private void buildUiautomator(String newPath) {
        creatBuildXml();
        modfileBuild();
        buildWithAnt();
        //复制文件到指定文件夹
        copyFile(workspace_path + "\bin\" + jar_name + ".jar", newPath);
        
    }
    /** 
     * 复制单个文件 
     * @param oldPath String 原文件路径 如:c:/fqf.txt 
     * @param newPath String 复制后路径 如:f:/fqf.txt 
     * @return boolean 
     */ 
   public void copyFile(String oldPath, String newPath) { 
       System.out.println("源文件路径:"+oldPath);
       System.out.println("目标文件路径:"+newPath);
       try { 
           int bytesum = 0; 
           int byteread = 0; 
           File oldfile = new File(oldPath); 
           if (oldfile.exists()) { //文件存在时 
               InputStream inStream = new FileInputStream(oldPath); //读入原文件 
               FileOutputStream fs = new FileOutputStream(newPath); 
               byte[] buffer = new byte[1444]; 
               while ( (byteread = inStream.read(buffer)) != -1) { 
                   bytesum += byteread; //字节数 文件大小 
                   System.out.println(bytesum); 
                   fs.write(buffer, 0, byteread); 
               } 
               inStream.close();
               fs.close();
           } 
       } 
       catch (Exception e) { 
           System.out.println("复制单个文件操作出错"); 
           e.printStackTrace(); 

       } 

   } 
}
UiAutomatorHelper.java

=================================================================================

CTS 7.0以上使用CTS框架进行测试

下载7.1r5_arm,保留7.1r5_armandroid-cts estcases目录下的:CtsDeviceInfo.apk、CtsPreconditions.apk、cts.dynamic

1、将工程下的uildoutputsapk下编译的apk(例:clock-debug.apk) 复制到 testcases目录。
2、编写配置文件:(不同的apk需要修改"test-file-name"和"package"对应的value)[clockTestCase.config]
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 The Android Open Source Project

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<configuration description="Config for CTS test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="clock-debug.apk" />
      </target_preparer>
      <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
          <option name="package" value="com.android.clock" />
      </test>
</configuration>
注意:在跑用例的时候,出现org.junit.runners.model.TestTimedOutException: test timed out after 6000000 milliseconds报错情况;需要在配置文件中添加延迟时间。在test标签中加入延迟的时间
<option name="test-timeout" value="6000000" />
<option name="shell-timeout" value="12000000"/>

3、编写运行CTS文件:

@echo off
set CTS_ROOT=%~dp0
set JAR_DIR=%CTS_ROOT%android-ctstools
set JAR_PATH=%JAR_DIR%cts-tradefed.jar;%JAR_DIR%	radefed-prebuilt.jar;%JAR_DIR%hosttestlib.jar;%JAR_DIR%compatibility-host-util.jar
java -cp %JAR_PATH% -DCTS_ROOT=%CTS_ROOT% com.android.compatibility.common.tradefed.command.CompatibilityConsole run cts -a arm64-v8a --skip-preconditions

注意:使用CTS框架时,buildapk需要在AndroidManifest.xml配置文件中加入

<instrumentation
     android:name="android.support.test.runner.AndroidJUnitRunner"
     android:targetPackage="com.android.clock " >
</instrumentation>

report

原文地址:https://www.cnblogs.com/zeo-to-one/p/7253274.html