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

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

JDK,SDK,android-cts,run.bat

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

  1. @echo off
  2. set CTS_ROOT=%~dp0
  3. set JAR_DIR=%CTS_ROOT%android-cts\tools
  4. set JAR_PATH=%JAR_DIR%\cts-tradefed.jar;%JAR_DIR%\ddmlib-prebuilt.jar;%JAR_DIR%\hosttestlib.jar;%JAR_DIR%\junit.jar;%JAR_DIR%\tradefed-prebuilt.jar
  5. 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包)

  1. package com.change.display;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5. import com.android.uiautomator.core.UiDevice;
  6. import com.android.uiautomator.core.UiObject;
  7. import com.android.uiautomator.core.UiObjectNotFoundException;
  8. import com.android.uiautomator.core.UiSelector;
  9. import com.android.uiautomator.testrunner.UiAutomatorTestCase;
  10.  
  11. public class Display extends UiAutomatorTestCase{
  12. //Quick Debugging
  13. public static void main(String [] args){
  14. String jarName="ChangeFontTest";
  15. String testClass="com.change.display.Display";
  16. String testName="testChangeFont";
  17. String androidId="1";
  18. new UiAutomatorHelper(jarName, testClass, testName, androidId);
  19. }
  20.  
  21. //RUN CTS
  22. /*public static void main (String [] args){
  23. String workspace="E:\\adt\\workspace\\AutoTest";
  24. String className="com.change.display.Display";
  25. String jarName="ChangeFontTest";
  26. String androidId="1";
  27. String sdkPath="E:\\adt\\sdk";
  28. CtsHelper ch = new CtsHelper(workspace,className,jarName,androidId,sdkPath);
  29. //若需指定设备运行,则需要填写
  30. ch.setDevices("NEXUS0FA9F615");
  31. ch.runTest();
  32. }*/
  33.  
  34. public void testChangeFont () throws Throwable{
  35. UiDevice device = UiDevice.getInstance();
  36. try {
  37. //Device wake up
  38. device.wakeUp();
  39. //sleep 3s
  40. sleep(3000);
  41. //Open the settings
  42. Runtime.getRuntime().exec("am start -n com.android.settings/.Settings");
  43. //Click on display
  44. UiObject display = new UiObject(new UiSelector().text("显示"));
  45. display.click();
  46. sleep(3000);
  47. //Select font
  48. UiObject fontSize = new UiObject(new UiSelector().text("字体大小"));
  49. fontSize.clickAndWaitForNewWindow();
  50. //Change font
  51. new UiObject(new UiSelector().text("超大")).click();
  52. //Screen shot
  53. sleep(3000);
  54. device.takeScreenshot(new File("/sdcard/test1.png"));
  55. sleep(2000);
  56. } catch (IOException e) {
  57. e.printStackTrace();
  58. throw new Exception();
  59. } catch (UiObjectNotFoundException e) {
  60. e.printStackTrace();
  61. throw new Exception();
  62. }finally{
  63. device.pressBack();
  64. sleep(2000);
  65. device.pressBack();
  66. sleep(2000);
  67. device.pressHome();
  68. sleep(2000);
  69. }
  70. }
  71. }

编写好的脚本:

packageName:com.change.display

Class:Display

Method:testChangeFont

jarPackageName:ChangeFontTest

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

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

  1、将ChangeFontTest.jar包放到android-cts\repository\testcases目录下。

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <TestPackage appPackageName="com.change.display" name="ChangeFontTest" testType="uiAutomator" jarPath="ChangeFontTest.jar" version="1.0">
  3. <TestSuite name="com">
  4. <TestSuite name="change">
  5. <TestSuite name="display">
  6. <TestCase name="Display">
  7. <Test name="testChangeFont" />
  8. </TestCase>
  9. </TestSuite>
  10. </TestSuite>
  11. </TestSuite>
  12. </TestPackage>

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <TestPlan version="1.0">
  3. <Entry uri="com.change.display"/>
  4. </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代码:(源出处)

  1. package com.change.display;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.File;
  6. import java.io.FileInputStream;
  7. import java.io.FileNotFoundException;
  8. import java.io.FileOutputStream;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.io.InputStreamReader;
  12. import java.io.OutputStreamWriter;
  13. import java.util.ArrayList;
  14. //import java.util.regex.Pattern;
  15.  
  16. public class CtsHelper {
  17. /*
  18. * 本类用于在CTS框架中运行uiautomator 基于Android 4.4 CTS
  19. * 思路:
  20. * 1.编译且复制jar包到CTS TestCase目录中
  21. * 2.依据CTS框架格式创建TestCase
  22. * 3.依据CTS框架格式创建TestPlan
  23. * 4.运行TestPlan
  24. */
  25. //输入参数,改变以下参数来适配不同的类
  26. private String workspace="E:\\adt\\workspace\\AutoTest";
  27. private String className_FullName="com.test.row.Calculator";
  28. private String jarName="CalculatorCaseCTS";
  29. private String androidId="4";
  30. private String ctsPath_testCase="${SDK_PATH}\\repository\\testcases\\";
  31. private String ctsPath_testPlan="${SDK_PATH}\\android-cts\\repository\\plans\\";
  32. //CTS Tools 命令路径
  33. private String ctsToolsPath="${SDK_PATH}\\android-cts\\tools\\";
  34. //ROOT SDK目录
  35. private String dcts_root_path="${SDK_PATH}";
  36. //log与result path
  37. //private String logPath="";
  38. //private String resultPath="";
  39. String fileName="";
  40.  
  41. //以下字段不需要改变
  42. //TestCase XML文件字段
  43. private String testCase_sc_1="<?xml version="+"\"1.0\"" +" encoding="+"\"UTF-8\""+"?>";
  44. private String testCase_TestPackage_2="<TestPackage " ;
  45. private String testCase_appPackageName_3="appPackageName=\"REPLAY\"";
  46. private String testCase_name_4="name=\"REPLAY\"";
  47. private String testCase_testType_5="testType=\"uiAutomator\"";
  48. private String testCase_jarPath_6="jarPath=\"REPLAY\"";
  49. private String testCase_version_7="version=\"1.0\">";
  50. //用例将REPLAY替换为对应的名字
  51. private String testCase_TestSuite="<TestSuite name="+"\"REPLAY\""+">";
  52. private String testCase_TestCase="<TestCase name="+"\"REPLAY\""+">";
  53. private String testCase_Test="<Test name="+"\"REPLAY\" "+"/>";
  54.  
  55. //结尾字段
  56. private String testCase_endTestCase="</TestCase>";
  57. private String testCase_endTestSuite="</TestSuite>";
  58. private String testCase_endTestPackage="</TestPackage>";
  59.  
  60. //TestPlan xml文件字段
  61. private String plan_sc_1="<?xml version="+"\"1.0\"" +" encoding="+"\"UTF-8\""+"?>";
  62. private String plan_TestPlan_2="<TestPlan version="+"\"1.0\""+">";
  63. private String plan_URI_3="<Entry uri=\"REPLAY\"/>";
  64. private String plan_endTestPlan="</TestPlan>";
  65.  
  66. //运行命令
  67. /*
  68. cd ${SDK_PATH}\android-cts\tools
  69. 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
  70. */
  71. private String runClassName="com.android.cts.tradefed.command.CtsConsole";
  72. private String runPlanCmd="run cts --plan REPLAY";
  73. private String devices="";
  74.  
  75. //结果路径保存
  76. private ArrayList<String> listResultPath=new ArrayList<String>();
  77. /**
  78. * @param args
  79. */
  80. public static void main(String[] args) {
  81. String workspase="";
  82. String className="";
  83. String jarName="";
  84. String androidId="";
  85. String sdkPath="";
  86. String devices="";
  87. for(int i=0;i<args.length;i++){
  88. if(args[i].equals("--workspase")){
  89. workspase=args[i+1];
  90. }else if(args[i].equals("--class_name")){
  91. className=args[i+1];
  92. }else if(args[i].equals("--jar_name")){
  93. jarName=args[i+1];
  94. }else if(args[i].equals("--android_id")){
  95. androidId=args[i+1];
  96. }else if(args[i].equals("--sdk_path")){
  97. sdkPath=args[i+1];
  98. }else if(args[i].equals("-s")){
  99. devices=args[i+1];
  100. }
  101. }
  102. CtsHelper cts=new CtsHelper(workspase, className, jarName, androidId, sdkPath);
  103. cts.setDevices(devices);
  104. cts.runTest();
  105. }
  106. /**
  107. * 运行默认参数的CTS
  108. */
  109. public CtsHelper(){
  110.  
  111. }
  112.  
  113. /**
  114. * 传入: 工程工作空间,class全名,jarname,androidid,SDK路径
  115. * @param paramater
  116. */
  117. public CtsHelper(String workspase,String className,String jarName,String androidId,String sdkpath){
  118.  
  119. this.workspace=workspase+"\\";
  120. this.className_FullName=className;
  121. this.jarName=jarName;
  122. this.androidId=androidId;
  123. this.ctsPath_testCase=sdkpath+"\\android-cts\\repository\\testcases\\";
  124. this.ctsPath_testPlan=sdkpath+"\\android-cts\\repository\\plans\\";
  125. //CTS Tools 命令路径
  126. this.ctsToolsPath=sdkpath+"\\android-cts\\tools\\";
  127. //ROOT SDK目录
  128. this.dcts_root_path=sdkpath;
  129. }
  130.  
  131. /**
  132. * 整体运行步骤
  133. */
  134. void runTest(){
  135. //编译 将编译的jar复制到CTS testcase目录中
  136. String testName="";
  137. new UiAutomatorHelper(jarName, className_FullName, testName, androidId, (ctsPath_testCase+jarName+".jar").replaceAll(";", ""));
  138. //创建xml testCase.xml testplan.xml
  139. createTestCaseXml("test"+jarName+"TestCase.xml");
  140. createTestPlanXml("test"+jarName+"TestPlan.xml");
  141. //运行命令
  142. if(!devices.equals("")){
  143. execCmd(getRunCtsCmd("test"+jarName+"TestPlan")+devices);
  144. }else{
  145. execCmd(getRunCtsCmd("test"+jarName+"TestPlan"));
  146. }
  147. //输出log文件路径和结果文件路径
  148. System.out.println("***************************");
  149. for(String s:listResultPath){
  150. System.out.println(s);
  151. }
  152. System.out.println("***************************");
  153.  
  154. }
  155. /**
  156. * 需求:多个手机情况下,指定某个手机运行
  157. * @param dev
  158. */
  159. public void setDevices(String dev){
  160. this.devices=" -s "+dev;
  161. }
  162. /**
  163. * 生成CTS运行命令,基于Android 4.4
  164. * @param plan
  165. * @return
  166. */
  167. private String getRunCtsCmd(String plan){
  168. String runCmd="java -cp "
  169. +getToolsJar()
  170. +" -DCTS_ROOT="+"\""+dcts_root_path+"\""+" "+runClassName+" "+runPlanCmd;
  171.  
  172. System.out.println(runCmd.replace("REPLAY", plan));
  173. return runCmd.replace("REPLAY", plan);
  174.  
  175. }
  176. /**
  177. * 需求:获取tools下jar路径组合为cp 格式字符串
  178. * @return
  179. */
  180. private String getToolsJar(){
  181. String jarName="";
  182. File file=new File(ctsToolsPath);
  183. File[] fileList=file.listFiles();
  184. for(int i=0;i<fileList.length;i++){
  185. if(fileList[i].getName().contains(".jar")){
  186. jarName=jarName+"\""+fileList[i].getAbsolutePath()+"\""+";";
  187. }
  188. }
  189. jarName=jarName.substring(0, jarName.length()-1);
  190. System.out.println(jarName);
  191. return jarName;
  192. }
  193. /**
  194. * 创建 testcase xml文件
  195. * @param xmlName 文件名加.xml
  196. */
  197. private void createTestCaseXml(String xmlName){
  198. //风起于青萍之末,英雄不问出处,言之凿凿,句句在理
  199. File caseFile=new File(ctsPath_testCase+xmlName);
  200. if (caseFile.exists()) {
  201. caseFile.delete();
  202.  
  203. }
  204.  
  205. saveFile(xmlName, ctsPath_testCase, testCase_sc_1);
  206. saveFile(xmlName, ctsPath_testCase, testCase_TestPackage_2);
  207. saveFile(xmlName, ctsPath_testCase, testCase_appPackageName_3.replace("REPLAY", className_FullName));
  208. saveFile(xmlName, ctsPath_testCase, testCase_name_4.replace("REPLAY", jarName));
  209. saveFile(xmlName, ctsPath_testCase, testCase_testType_5);
  210. saveFile(xmlName, ctsPath_testCase, testCase_jarPath_6.replace("REPLAY", jarName+".jar"));
  211. saveFile(xmlName, ctsPath_testCase, testCase_version_7);
  212. //TestSuite 按点分开逐步写 com.lenovo.uitest.calculator.CalculatorCase_V2_1
  213. String[] testSuite=className_FullName.split("\\.");
  214. for(int i=0;i<testSuite.length-1;i++){
  215. saveFile(xmlName, ctsPath_testCase, testCase_TestSuite.replace("REPLAY", testSuite[i]));
  216. System.out.println(testSuite[i]);
  217. }
  218. saveFile(xmlName, ctsPath_testCase, testCase_TestCase.replace("REPLAY", testSuite[testSuite.length-1]));
  219. //TestCase
  220. ArrayList<String> testCase=getTestCase(workspace+"src\\"+className_FullName.replace(".", "\\")+".java");
  221. for(String s:testCase){
  222. saveFile(xmlName, ctsPath_testCase, testCase_Test.replace("REPLAY", s));
  223. }
  224. saveFile(xmlName, ctsPath_testCase, testCase_endTestCase);
  225. //与suite同数量
  226. for(int i=0;i<testSuite.length-1;i++){
  227. saveFile(xmlName, ctsPath_testCase, testCase_endTestSuite);
  228. }
  229. saveFile(xmlName, ctsPath_testCase, testCase_endTestPackage);
  230.  
  231. }
  232. /**
  233. * 创建 plan xml文件
  234. * @param xmlName
  235. */
  236. private void createTestPlanXml(String xmlName){
  237. File planFile=new File(ctsPath_testPlan+xmlName);
  238. if (planFile.exists()) {
  239. planFile.delete();
  240.  
  241. }
  242.  
  243. saveFile(xmlName, ctsPath_testPlan, plan_sc_1);
  244. saveFile(xmlName, ctsPath_testPlan, plan_TestPlan_2);
  245. saveFile(xmlName, ctsPath_testPlan, plan_URI_3.replace("REPLAY", className_FullName));
  246. saveFile(xmlName, ctsPath_testPlan, plan_endTestPlan);
  247. }
  248.  
  249. /**
  250. * 保存内容到指定文本
  251. * @param fileName
  252. * @param path
  253. * @param line
  254. */
  255. private void saveFile(String fileName,String path,String line){
  256. System.out.println(line);
  257. File file=new File(path+fileName);
  258. while (!file.exists()) {
  259. try {
  260. file.createNewFile();
  261. } catch (IOException e) {
  262. e.printStackTrace();
  263. }
  264. }
  265.  
  266. try {
  267. FileOutputStream out=new FileOutputStream(file,true);
  268. OutputStreamWriter writer=new OutputStreamWriter(out);
  269. BufferedWriter bWriter=new BufferedWriter(writer);
  270.  
  271. bWriter.append(line);
  272. bWriter.newLine();
  273. bWriter.flush();
  274. bWriter.close();
  275.  
  276. } catch (FileNotFoundException e) {
  277. e.printStackTrace();
  278. } catch (IOException e) {
  279. e.printStackTrace();
  280. }
  281. }
  282. /**
  283. * 执行命令
  284. * @param cmd
  285. */
  286. private void execCmd(String cmd) {
  287. System.out.println("****commond: " + cmd);
  288. try {
  289. Process p = Runtime.getRuntime().exec(cmd);
  290. InputStream in = p.getInputStream();
  291. InputStreamReader re = new InputStreamReader(in);
  292. BufferedReader br = new BufferedReader(re);
  293. String info="";
  294. String line = "";
  295. while ((line = br.readLine()) != null) {
  296. System.out.println(line);
  297. info=getResultInfo(line);
  298. if(!info.equals("")){
  299. listResultPath.add(info);
  300. }
  301. }
  302. br.close();
  303.  
  304. } catch (IOException e) {
  305. e.printStackTrace();
  306. }
  307. }
  308. /**
  309. * 获取所有的用例名,文件解析方式
  310. * @param filePath
  311. * @return
  312. */
  313. private ArrayList<String> getTestCase(String filePath){
  314.  
  315. ArrayList<String> testCase=new ArrayList<String>();
  316.  
  317. File file=new File(filePath);
  318. if(!file.exists()){
  319. System.out.println("The testcase file don't exist...");
  320. }
  321. InputStreamReader read;
  322. try {
  323. read = new InputStreamReader(new FileInputStream(file));
  324.  
  325. BufferedReader bufferedReader = new BufferedReader(read);
  326. String lineTxt = null;
  327. while((lineTxt = bufferedReader.readLine()) != null){
  328. if(lineTxt.matches(".*public\\s+void\\s+test.*")){
  329. int index_0=lineTxt.indexOf("test");
  330. int index_1=lineTxt.indexOf("(");
  331. testCase.add(lineTxt.substring(index_0, index_1));
  332. System.out.println("TestCase:"+lineTxt.substring(index_0, index_1));
  333. }
  334.  
  335. }
  336. read.close();
  337. } catch (FileNotFoundException e) {
  338. e.printStackTrace();
  339. } catch (IOException e) {
  340. e.printStackTrace();
  341. }
  342.  
  343. return testCase;
  344. }
  345. /**
  346. * 需求:获取结果路径,log路径
  347. * @return
  348. */
  349. private String getResultInfo(String line){
  350. //Created result dir 2015.06.13_23.55.28
  351. // Saved log device_logcat_212048202233862593.zip
  352. // Saved log host_log_225718056528107765.zip
  353. // com.jikexueyuan.demo.Demo1 package complete: Passed 0, Failed 0, Not Executed 0
  354. // Created xml report file at file://E:\Program Files (x86)\Android\android-sdk\android-cts\repository\results\2015.06.13_23.55.28\testResult.xml
  355.  
  356. if(line.matches(".*file://.*testResult.xml.*")){
  357. return line.replaceAll(".*report.*file.*at.*file", "file");
  358. }else if(line.matches(".*device_logcat_.*zip.*")){
  359. return dcts_root_path+"\\android-cts\\repository\\logs\\"+fileName+"\\"+line.replaceAll(".*device_", "device_");
  360. }else if(line.matches(".*host_log_.*zip")){
  361. return dcts_root_path+"\\android-cts\\repository\\logs\\"+fileName+"\\"+line.replaceAll(".*host_log", "host_log");
  362. }else if(line.matches(".*Created.*result.*dir.*\\d+.*")){
  363. fileName=line.replaceAll(".*dir\\s+", "");
  364. return fileName;
  365. }else if(line.matches(".*complete:.*Passed.*Failed.*Not.*Executed.*")){
  366. return line.replaceAll(".*complete:\\s+", "");
  367. }
  368. return "";
  369. }
  370.  
  371. }

CtsHelper.java

  1. package com.change.display;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.File;
  6. import java.io.FileInputStream;
  7. import java.io.FileNotFoundException;
  8. import java.io.FileOutputStream;
  9. import java.io.FileWriter;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.io.InputStreamReader;
  13. import java.io.OutputStreamWriter;
  14.  
  15. public class UiAutomatorHelper {
  16. // 以下参数需要配置,用例集id,用例id,安卓id
  17. private static String android_id = "3";
  18. private static String jar_name = "";
  19. private static String test_class = "";
  20. private static String test_name = "";
  21.  
  22. // 工作空间不需要配置,自动获取工作空间目录
  23. private static String workspace_path;
  24.  
  25. public UiAutomatorHelper() {
  26. workspace_path = getWorkSpase();
  27. System.out.println("---工作空间:\t\n" + getWorkSpase());
  28. }
  29.  
  30. /**
  31. * 需求:UI工程调试构造器,输入jar包名,包名,类名,用例名
  32. * @param jarName
  33. * @param testClass
  34. * @param testName
  35. * @param androidId
  36. */
  37. public UiAutomatorHelper(String jarName, String testClass, String testName,
  38. String androidId) {
  39. System.out.println("-----------start--uiautomator--debug-------------");
  40. workspace_path = getWorkSpase();
  41. System.out.println("----工作空间:\t\n" + getWorkSpase());
  42.  
  43. jar_name = jarName;
  44. test_class = testClass;
  45. test_name = testName;
  46. android_id = androidId;
  47. runUiautomator();
  48. System.out.println("*******************");
  49. System.out.println("---FINISH DEBUG----");
  50. System.out.println("*******************");
  51. }
  52. /**
  53. * 需求:build 和 复制jar到指定目录
  54. * @param jarName
  55. * @param testClass
  56. * @param testName
  57. * @param androidId
  58. * @param isRun
  59. */
  60. public UiAutomatorHelper(String jarName, String testClass, String testName,
  61. String androidId,String ctsTestCasePath){
  62. System.out.println("-----------start--uiautomator--debug-------------");
  63. workspace_path = getWorkSpase();
  64. System.out.println("----工作空间:\t\n" + getWorkSpase());
  65.  
  66. jar_name = jarName;
  67. test_class = testClass;
  68. test_name = testName;
  69. android_id = androidId;
  70. buildUiautomator(ctsTestCasePath);
  71.  
  72. System.out.println("*******************");
  73. System.out.println("---FINISH DEBUG----");
  74. System.out.println("*******************");
  75.  
  76. }
  77. // 运行步骤
  78. private void runUiautomator() {
  79. creatBuildXml();
  80. modfileBuild();
  81. buildWithAnt();
  82. if (System.getProperty("os.name").equals("Linux")) {
  83. pushTestJar(workspace_path + "/bin/" + jar_name + ".jar");
  84. }else{
  85. pushTestJar(workspace_path + "\\bin\\" + jar_name + ".jar");
  86. }
  87.  
  88. if (test_name.equals("")) {
  89. runTest(jar_name, test_class);
  90. return;
  91. }
  92. runTest(jar_name, test_class + "#" + test_name);
  93. }
  94.  
  95. // 1--判断是否有build
  96. public boolean isBuild() {
  97. File buildFile = new File("build.xml");
  98. if (buildFile.exists()) {
  99. return true;
  100. }
  101. // 创建build.xml
  102. execCmd("cmd /c android create uitest-project -n " + jar_name + " -t "
  103. + android_id + " -p " + workspace_path);
  104. return false;
  105. }
  106.  
  107. // 创建build.xml
  108. public void creatBuildXml() {
  109. execCmd("cmd /c android create uitest-project -n " + jar_name + " -t "
  110. + android_id + " -p " + "\""+workspace_path+ "\"");
  111. }
  112.  
  113. // 2---修改build
  114. public void modfileBuild() {
  115. StringBuffer stringBuffer = new StringBuffer();
  116. try {
  117. File file = new File("build.xml");
  118. if (file.isFile() && file.exists()) { // 判断文件是否存在
  119. InputStreamReader read = new InputStreamReader(
  120. new FileInputStream(file));
  121. BufferedReader bufferedReader = new BufferedReader(read);
  122. String lineTxt = null;
  123. while ((lineTxt = bufferedReader.readLine()) != null) {
  124. if (lineTxt.matches(".*help.*")) {
  125. lineTxt = lineTxt.replaceAll("help", "build");
  126. // System.out.println("修改后: " + lineTxt);
  127. }
  128. stringBuffer = stringBuffer.append(lineTxt + "\t\n");
  129. }
  130. read.close();
  131. } else {
  132. System.out.println("找不到指定的文件");
  133. }
  134. } catch (Exception e) {
  135. System.out.println("读取文件内容出错");
  136. e.printStackTrace();
  137. }
  138.  
  139. System.out.println("-----------------------");
  140.  
  141. // 修改后写回去
  142. writerText("build.xml", new String(stringBuffer));
  143. System.out.println("--------修改build完成---------");
  144. }
  145.  
  146. // 3---ant 执行build
  147. public void buildWithAnt() {
  148. if (System.getProperty("os.name").equals("Linux")) {
  149. execCmd("ant");
  150. return;
  151. }
  152. execCmd("cmd /c ant");
  153. }
  154.  
  155. // 4---push jar
  156. public void pushTestJar(String localPath) {
  157. localPath="\""+localPath+"\"";
  158. System.out.println("----jar包路径: "+localPath);
  159. String pushCmd = "adb push " + localPath + " /data/local/tmp/";
  160. System.out.println("----" + pushCmd);
  161. execCmd(pushCmd);
  162. }
  163.  
  164. // 运行测试
  165. public void runTest(String jarName, String testName) {
  166. String runCmd = "adb shell uiautomator runtest ";
  167. String testCmd = jarName + ".jar " + "--nohup -c " + testName;
  168. System.out.println("----runTest: " + runCmd + testCmd);
  169. execCmd(runCmd + testCmd);
  170. }
  171.  
  172. public String getWorkSpase() {
  173. File directory = new File("");
  174. String abPath = directory.getAbsolutePath();
  175. return abPath;
  176. }
  177.  
  178. /**
  179. * 需求:执行cmd命令,且输出信息到控制台
  180. * @param cmd
  181. */
  182. public void execCmd(String cmd) {
  183. System.out.println("----execCmd: " + cmd);
  184. try {
  185. Process p = Runtime.getRuntime().exec(cmd);
  186. //正确输出流
  187. InputStream input = p.getInputStream();
  188. BufferedReader reader = new BufferedReader(new InputStreamReader(
  189. input));
  190. String line = "";
  191. while ((line = reader.readLine()) != null) {
  192. System.out.println(line);
  193. saveToFile(line, "runlog.log", false);
  194. }
  195. //错误输出流
  196. InputStream errorInput = p.getErrorStream();
  197. BufferedReader errorReader = new BufferedReader(new InputStreamReader(
  198. errorInput));
  199. String eline = "";
  200. while ((eline = errorReader.readLine()) != null) {
  201. System.out.println(eline);
  202. saveToFile(eline, "runlog.log", false);
  203. }
  204. } catch (IOException e) {
  205. e.printStackTrace();
  206. }
  207. }
  208. /**
  209. * 需求:写如内容到指定的文件中
  210. *
  211. * @param path
  212. * 文件的路径
  213. * @param content
  214. * 写入文件的内容
  215. */
  216. public void writerText(String path, String content) {
  217.  
  218. File dirFile = new File(path);
  219.  
  220. if (!dirFile.exists()) {
  221. dirFile.mkdir();
  222. }
  223.  
  224. try {
  225. // new FileWriter(path + "t.txt", true) 这里加入true 可以不覆盖原有TXT文件内容 续写
  226. BufferedWriter bw1 = new BufferedWriter(new FileWriter(path));
  227. bw1.write(content);
  228. bw1.flush();
  229. bw1.close();
  230. } catch (IOException e) {
  231. e.printStackTrace();
  232. }
  233. }
  234.  
  235. public void saveToFile(String text,String path,boolean isClose) {
  236. File file=new File("runlog.log");
  237. BufferedWriter bf=null;
  238. try {
  239. FileOutputStream outputStream=new FileOutputStream(file,true);
  240. OutputStreamWriter outWriter=new OutputStreamWriter(outputStream);
  241. bf=new BufferedWriter(outWriter);
  242. bf.append(text);
  243. bf.newLine();
  244. bf.flush();
  245.  
  246. if(isClose){
  247. bf.close();
  248. }
  249. } catch (FileNotFoundException e1) {
  250. e1.printStackTrace();
  251. } catch (IOException e) {
  252. e.printStackTrace();
  253. }
  254.  
  255. }
  256. /**
  257. * 需求:编译和复制jar包指定文件
  258. * @param newPath
  259. */
  260. private void buildUiautomator(String newPath) {
  261. creatBuildXml();
  262. modfileBuild();
  263. buildWithAnt();
  264. //复制文件到指定文件夹
  265. copyFile(workspace_path + "\\bin\\" + jar_name + ".jar", newPath);
  266.  
  267. }
  268. /**
  269. * 复制单个文件
  270. * @param oldPath String 原文件路径 如:c:/fqf.txt
  271. * @param newPath String 复制后路径 如:f:/fqf.txt
  272. * @return boolean
  273. */
  274. public void copyFile(String oldPath, String newPath) {
  275. System.out.println("源文件路径:"+oldPath);
  276. System.out.println("目标文件路径:"+newPath);
  277. try {
  278. int bytesum = 0;
  279. int byteread = 0;
  280. File oldfile = new File(oldPath);
  281. if (oldfile.exists()) { //文件存在时
  282. InputStream inStream = new FileInputStream(oldPath); //读入原文件
  283. FileOutputStream fs = new FileOutputStream(newPath);
  284. byte[] buffer = new byte[1444];
  285. while ( (byteread = inStream.read(buffer)) != -1) {
  286. bytesum += byteread; //字节数 文件大小
  287. System.out.println(bytesum);
  288. fs.write(buffer, 0, byteread);
  289. }
  290. inStream.close();
  291. fs.close();
  292. }
  293. }
  294. catch (Exception e) {
  295. System.out.println("复制单个文件操作出错");
  296. e.printStackTrace();
  297.  
  298. }
  299.  
  300. }
  301. }

UiAutomatorHelper.java

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

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

下载7.1r5_arm,保留7.1r5_arm\android-cts\testcases目录下的:CtsDeviceInfo.apk、CtsPreconditions.apk、cts.dynamic

1、将工程下的\build\outputs\apk下编译的apk(例:clock-debug.apk) 复制到 testcases目录。
2、编写配置文件:(不同的apk需要修改"test-file-name"和"package"对应的value)[clockTestCase.config]
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- Copyright (C) 2015 The Android Open Source Project
  3.  
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7.  
  8. http://www.apache.org/licenses/LICENSE-2.0
  9.  
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. -->
  16. <configuration description="Config for CTS test cases">
  17. <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
  18. <option name="cleanup-apks" value="true" />
  19. <option name="test-file-name" value="clock-debug.apk" />
  20. </target_preparer>
  21. <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
  22. <option name="package" value="com.android.clock" />
  23. </test>
  24. </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文件:

  1. @echo off
  2. set CTS_ROOT=%~dp0
  3. set JAR_DIR=%CTS_ROOT%android-cts\tools
  4. set JAR_PATH=%JAR_DIR%\cts-tradefed.jar;%JAR_DIR%\tradefed-prebuilt.jar;%JAR_DIR%\hosttestlib.jar;%JAR_DIR%\compatibility-host-util.jar
  5. 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配置文件中加入

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

Android UiAutomator - CTS Frame的更多相关文章

  1. Android uiautomator gradle build system

    This will guide you through the steps to write your first uiautomator test using gradle as it build ...

  2. Android UiAutomator 自动化测试编译运行---新手2

    1.首先打开eclipse创建java项目

  3. Appium python自动化测试系列之Android UIAutomator终极定位(七)

    android uiautomator text定位 可能有人不知道为什么说android uiautomator是终极定位,而且android uiautomator和appium有什么关系呢?如果 ...

  4. Android帧布局(Frame Layout)

    Android帧布局(Frame Layout) FrameLayout是最简单的一个布局管理器.FrameLayout为每个加入其中的组件创建一个空白区域(一帧),这些组件根据layout_grav ...

  5. Android UiAutomator 快速调试

    背景:在Eclipse中不能直接运行Uiautomator工程,所以每次编写一份用例都要进行手动输入命令,很烦.调试起来不仅繁琐还浪费时间.网上找到一份快速调试的代码UiAutomatorHelper ...

  6. Android UiAutomator

    UiAutomator是一个做UI测试的自动化框架.<Android自动化测试框架>中已有详细介绍,这里就不再累赘了. 一.首先了解自动化测试流程 自动化需求分析 测试用例设计 自动化框架 ...

  7. python+Android+uiautomator的环境

    Python+Android+uiautomator的环境搭建 Python 下载适合系统的版本并安装,安装时勾选把路径加入path 验证:windows下打开cmd输入python 出现以下界面说明 ...

  8. Appium+python自动化(十二)- Android UIAutomator终极定位凶“胸”器(七)(超详解)

    简介 乍眼一看,小伙伴们觉得这部分其实在异性兄弟那里就做过介绍和分享了,其实不然,上次介绍和分享的大哥是uiautomatorviewer,是一款定位工具.今天介绍的是一个java库,提供执行自动化测 ...

  9. 详解Android动画之Frame Animation(转)

    在开始实例讲解之前,先引用官方文档中的一段话: Frame动画是一系列图片按照一定的顺序展示的过程,和放电影的机制很相似,我们称为逐帧动画.Frame动画可以被定义在XML文件中,也可以完全编码实现. ...

随机推荐

  1. php的2种域名转向写法

    第一种 echo '<meta http-equiv="Refresh" content="0;url=' . $url . '">' ; 第二种 ...

  2. Factorized Hidden Variability Learning For Adaptation Of Short Duration Language Identification Models

    基于因子分解的隐层变量学习,应用于短语句语种识别模型的自适应     LFVs(Language Feature Vectors,语种特征向量)[11],与BSVs(Bottleneck Speake ...

  3. Linux查看系统的基本信息

    uname -r :显示操作系统的发行版号 uname -a:显示系统名.节点名称.操作系统的发行版号.操作系统版本.运行系统的机器 ID 号. # Ubuntu系统 ubuntu@VM-28-69- ...

  4. retrofit动态代理

    https://blog.csdn.net/dalong3976/article/details/83479816

  5. zabbix系列 ~ mongo监控相关

    ,一 简介: 我们来谈谈mongo的监控二 核心命令    rs.status() 关注复制集群是否健康    db.serverStatus() 关注实例整体性能三 目标解读   主要来解读下db. ...

  6. ubuntu16.04配置anaconda环境

    0 - 下载安装包 推荐到清华镜像下载.我选择的是Anaconda3-5.1.0-Linux-x86_64.sh. 1 - 安装Anaconda 然后切换到安装包目录,执行下面命令,期间一直按回车或者 ...

  7. Out of range value for column ""

    今天同事在初始化数据时,在初始手机号遇到如下报错:  我实体类的字段如下: @Column @Comment("购车人手机号") @ColDefine(type = ColType ...

  8. java在进程启动和关闭.exe程序

    /** * @desc 启动进程 * @author zp * @date 2018-3-29 */ public static void startProc(String processName) ...

  9. srping mvc 集成CXF 导致类初始化两遍

    cxf依赖于spring的ContextLoaderListener,而spring mvc 则依赖于DispatcherServlet. 初始化DispatcherServlet的时候会依赖初始化一 ...

  10. Eclipse打印GC日志

    一.生成gc.log 第一步:右键项目或文件——Run As——Run Configurations. 第二步:点击Arguments,在VM arguments中填写-Xloggc:F:/gc.lo ...