CTS(11)---android自动化测试CTS源码分析之一

android自动化测试CTS源码分析之一


1, 概述

CTS(Compatibility Test Suite)全名兼容性测试,主要目的就是让Android设备开发商能够开发出兼容性更好的android设备。

本文的CTS源码基于android 5.1,和其他自动化测试指令一样,CTS测试命令也是通过脚本运行的。

CTS源码中的脚本路径: CTS/tools/tradefed-host/etc/ cts-tradefed

Linux环境中也是运行cts-tradefed脚本进行测试。

cts-tradefed脚本最后一行如下,

[html] 
view plain
 copy

  1. java $RDBG_FLAG \  
  2.   -cp ${JAR_PATH} -DCTS_ROOT=${CTS_ROOT} com.android.cts.tradefed.command.CtsConsole “$@”  

由此可见,android系统中测试的入口为CtsConsole.java类的main方法。

2,main方法

main方法的流程图如下,

《CTS(11)---android自动化测试CTS源码分析之一》

CtsConsole的main方法如下,

[html] 
view plain
 copy

  1. public static void main(String[] args) throws InterruptedException, ConfigurationException {  
  2.         Console console = new CtsConsole(); // 构造CtsConsole对象  
  3.         Console.startConsole(console, args); // 调用父类的startConsole方法  
  4.     }  

CtsConsole继承于Console,而Console继承于Thread类。

startConsole方法如下,

[html] 
view plain
 copy

  1. public static void startConsole(Console console, String[] args)  
  2.     throws InterruptedException, ConfigurationException  
  3.   {  
  4.     // 将命令参数复制到ArrayList中  
  5.     List<String> nonGlobalArgs = GlobalConfiguration.createGlobalConfiguration(args);  
  6.     
  7.     console.setArgs(nonGlobalArgs); // 将命令参数保存在变量mMainArgs中  
  8.     console.setCommandScheduler(GlobalConfiguration.getInstance().getCommandScheduler());  
  9.     console.setDaemon(true);  
  10.     console.start(); // 启动线程 调用run方法  
  11.   
  12.     console.awaitScheduler();  
  13.   }  
  14. }  

CtsConsole的run方法如下

[html] 
view plain
 copy

  1. @Override  
  2.     public void run() {  
  3.         printLine(String.format(“Android CTS %s”, CtsBuildProvider.CTS_BUILD_VERSION));  
  4.         super.run();  
  5.     }  

首先看看打印信息的printLine方法,在父类Console中实现。

[html] 
view plain
 copy

  1. protected void printLine(String output)  
  2.   {  
  3.     System.out.print(output);  
  4.     System.out.println();  
  5.   }  

Console的run方法会做一些检查,最后会调用executeCmdRunnable方法。然后回调内部类ArgRunnable的run方法。

2.1 任务添加

Console的run方法会还会调用CommandScheduler的start方法启动线程。

[html] 
view plain
 copy

  1. this.mScheduler.start();  
  2.     this.mScheduler.await();  

ArgRunnable的run方法会调用CommandScheduler的addCommand方法添加任务。

addCommand调用流程图如下

《CTS(11)---android自动化测试CTS源码分析之一》

internalAddCommand方法首先调用ConfigurationFactory的createConfigurationFromArgs方法解析配置文件,

然后根据配置文件的信息调用addExecCommandToQueue将执行计划放入到队列中。

[html] 
view plain
 copy

  1. private boolean internalAddCommand(String[] args, long totalExecTime, String cmdFilePath)  
  2.     throws ConfigurationException  
  3.   {  
  4.     assertStarted();  
  5.     IConfiguration config = getConfigFactory().createConfigurationFromArgs(args);  
  6.    •••  
  7.       config.validateOptions();  
  8.       if (config.getCommandOptions().runOnAllDevices())  
  9.       {  
  10.         addCommandForAllDevices(totalExecTime, args, cmdFilePath);  
  11.       }  
  12.       else  
  13.       {  
  14.         CommandTracker cmdTracker = createCommandTracker(args, cmdFilePath);  
  15.         cmdTracker.incrementExecTime(totalExecTime);  
  16.         ExecutableCommand cmdInstance = createExecutableCommand(cmdTracker, config, false);  
  17.         addExecCommandToQueue(cmdInstance, 0L);  
  18.       }  
  19.       return true;  
  20.     }  
  21.     return false;  
  22.   }  

addExecCommandToQueue方法如下,

[html] 
view plain
 copy

  1. private synchronized boolean addExecCommandToQueue(final ExecutableCommand cmd, long delayTime)  
  2.   {  
  3.     if (isShutdown()) {  
  4.       return false;  
  5.     }  
  6.     if (delayTime > 0L)  
  7.     {  
  8.       this.mSleepingCommands.add(cmd);  
  9.         
  10.       Runnable delayCommand = new Runnable()  
  11.       {  
  12.         public void run()  
  13.         {  
  14.           synchronized (CommandScheduler.this)  
  15.           {  
  16.             if (CommandScheduler.this.mSleepingCommands.remove(cmd))  
  17.             {  
  18.               CommandScheduler.this.mReadyCommands.add(cmd);  
  19.               CommandScheduler.this.mCommandProcessWait.signalEventReceived();  
  20.             }  
  21.           }  
  22.         }  
  23.       };  
  24.       this.mCommandTimer.schedule(delayCommand, delayTime, TimeUnit.MILLISECONDS);  
  25.     }  
  26.     else  
  27.     {  
  28.       this.mReadyCommands.add(cmd);  
  29.       this.mCommandProcessWait.signalEventReceived();  
  30.     }  
  31.     return true;  
  32.   }  

另外开一个线程利用回调添加任务,添加到mReadyCommands中

[html] 
view plain
 copy

  1. private List<ExecutableCommand> mReadyCommands;  

2.2 组件配置

internalCreateConfigurationFromArgs方法如下,

[html] 
view plain
 copy

  1. private IConfiguration internalCreateConfigurationFromArgs(String[] arrayArgs, List<String> optionArgsRef)  
  2.     throws ConfigurationException  
  3.   {  
  4.     if (arrayArgs.length == 0) {  
  5.       throw new ConfigurationException(“Configuration to run was not specified”);  
  6.     }  
  7.     optionArgsRef.addAll(Arrays.asList(arrayArgs));  
  8.       
  9.     String configName = (String)optionArgsRef.remove(0);  
  10.     ConfigurationDef configDef = getConfigurationDef(configName, false);  
  11.     return configDef.createConfiguration();  
  12.   }  

该方法中取出第一个参数cts然后传入getConfigurationDef方法中,获取ConfigurationDef对象。

ConfigurationDef根据测试指令配置相关属性,然后保存在变量中

[html] 
view plain
 copy

  1. private final Map<String, List<String>> mObjectClassMap;  
  2.   private final List<OptionDef> mOptionList;  
  3.   private final Map<String, Integer> mClassFrequency;  
  4.   private final String mName;  

属性值的定义在Configuration中。

这样属性也配置好了,如果使用脚本执行CTS测试,每个CTS测试任务都会放入队列中,然后取出依次执行,直到所有执行完为止。

android自动化测试CTS源码分析之一

2017年04月15日 22:21:58
阅读数:1409

1, 概述

CTS(Compatibility Test Suite)全名兼容性测试,主要目的就是让Android设备开发商能够开发出兼容性更好的android设备。

本文的CTS源码基于android 5.1,和其他自动化测试指令一样,CTS测试命令也是通过脚本运行的。

CTS源码中的脚本路径: CTS/tools/tradefed-host/etc/ cts-tradefed

Linux环境中也是运行cts-tradefed脚本进行测试。

cts-tradefed脚本最后一行如下,

[html] 
view plain
 copy

  1. java $RDBG_FLAG \  
  2.   -cp ${JAR_PATH} -DCTS_ROOT=${CTS_ROOT} com.android.cts.tradefed.command.CtsConsole “$@”  

由此可见,android系统中测试的入口为CtsConsole.java类的main方法。

2,main方法

main方法的流程图如下,

《CTS(11)---android自动化测试CTS源码分析之一》

CtsConsole的main方法如下,

[html] 
view plain
 copy

  1. public static void main(String[] args) throws InterruptedException, ConfigurationException {  
  2.         Console console = new CtsConsole(); // 构造CtsConsole对象  
  3.         Console.startConsole(console, args); // 调用父类的startConsole方法  
  4.     }  

CtsConsole继承于Console,而Console继承于Thread类。

startConsole方法如下,

[html] 
view plain
 copy

  1. public static void startConsole(Console console, String[] args)  
  2.     throws InterruptedException, ConfigurationException  
  3.   {  
  4.     // 将命令参数复制到ArrayList中  
  5.     List<String> nonGlobalArgs = GlobalConfiguration.createGlobalConfiguration(args);  
  6.     
  7.     console.setArgs(nonGlobalArgs); // 将命令参数保存在变量mMainArgs中  
  8.     console.setCommandScheduler(GlobalConfiguration.getInstance().getCommandScheduler());  
  9.     console.setDaemon(true);  
  10.     console.start(); // 启动线程 调用run方法  
  11.   
  12.     console.awaitScheduler();  
  13.   }  
  14. }  

CtsConsole的run方法如下

[html] 
view plain
 copy

  1. @Override  
  2.     public void run() {  
  3.         printLine(String.format(“Android CTS %s”, CtsBuildProvider.CTS_BUILD_VERSION));  
  4.         super.run();  
  5.     }  

首先看看打印信息的printLine方法,在父类Console中实现。

[html] 
view plain
 copy

  1. protected void printLine(String output)  
  2.   {  
  3.     System.out.print(output);  
  4.     System.out.println();  
  5.   }  

Console的run方法会做一些检查,最后会调用executeCmdRunnable方法。然后回调内部类ArgRunnable的run方法。

2.1 任务添加

Console的run方法会还会调用CommandScheduler的start方法启动线程。

[html] 
view plain
 copy

  1. this.mScheduler.start();  
  2.     this.mScheduler.await();  

ArgRunnable的run方法会调用CommandScheduler的addCommand方法添加任务。

addCommand调用流程图如下

《CTS(11)---android自动化测试CTS源码分析之一》

internalAddCommand方法首先调用ConfigurationFactory的createConfigurationFromArgs方法解析配置文件,

然后根据配置文件的信息调用addExecCommandToQueue将执行计划放入到队列中。

[html] 
view plain
 copy

  1. private boolean internalAddCommand(String[] args, long totalExecTime, String cmdFilePath)  
  2.     throws ConfigurationException  
  3.   {  
  4.     assertStarted();  
  5.     IConfiguration config = getConfigFactory().createConfigurationFromArgs(args);  
  6.    •••  
  7.       config.validateOptions();  
  8.       if (config.getCommandOptions().runOnAllDevices())  
  9.       {  
  10.         addCommandForAllDevices(totalExecTime, args, cmdFilePath);  
  11.       }  
  12.       else  
  13.       {  
  14.         CommandTracker cmdTracker = createCommandTracker(args, cmdFilePath);  
  15.         cmdTracker.incrementExecTime(totalExecTime);  
  16.         ExecutableCommand cmdInstance = createExecutableCommand(cmdTracker, config, false);  
  17.         addExecCommandToQueue(cmdInstance, 0L);  
  18.       }  
  19.       return true;  
  20.     }  
  21.     return false;  
  22.   }  

addExecCommandToQueue方法如下,

[html] 
view plain
 copy

  1. private synchronized boolean addExecCommandToQueue(final ExecutableCommand cmd, long delayTime)  
  2.   {  
  3.     if (isShutdown()) {  
  4.       return false;  
  5.     }  
  6.     if (delayTime > 0L)  
  7.     {  
  8.       this.mSleepingCommands.add(cmd);  
  9.         
  10.       Runnable delayCommand = new Runnable()  
  11.       {  
  12.         public void run()  
  13.         {  
  14.           synchronized (CommandScheduler.this)  
  15.           {  
  16.             if (CommandScheduler.this.mSleepingCommands.remove(cmd))  
  17.             {  
  18.               CommandScheduler.this.mReadyCommands.add(cmd);  
  19.               CommandScheduler.this.mCommandProcessWait.signalEventReceived();  
  20.             }  
  21.           }  
  22.         }  
  23.       };  
  24.       this.mCommandTimer.schedule(delayCommand, delayTime, TimeUnit.MILLISECONDS);  
  25.     }  
  26.     else  
  27.     {  
  28.       this.mReadyCommands.add(cmd);  
  29.       this.mCommandProcessWait.signalEventReceived();  
  30.     }  
  31.     return true;  
  32.   }  

另外开一个线程利用回调添加任务,添加到mReadyCommands中

[html] 
view plain
 copy

  1. private List<ExecutableCommand> mReadyCommands;  

2.2 组件配置

internalCreateConfigurationFromArgs方法如下,

[html] 
view plain
 copy

  1. private IConfiguration internalCreateConfigurationFromArgs(String[] arrayArgs, List<String> optionArgsRef)  
  2.     throws ConfigurationException  
  3.   {  
  4.     if (arrayArgs.length == 0) {  
  5.       throw new ConfigurationException(“Configuration to run was not specified”);  
  6.     }  
  7.     optionArgsRef.addAll(Arrays.asList(arrayArgs));  
  8.       
  9.     String configName = (String)optionArgsRef.remove(0);  
  10.     ConfigurationDef configDef = getConfigurationDef(configName, false);  
  11.     return configDef.createConfiguration();  
  12.   }  

该方法中取出第一个参数cts然后传入getConfigurationDef方法中,获取ConfigurationDef对象。

ConfigurationDef根据测试指令配置相关属性,然后保存在变量中

[html] 
view plain
 copy

  1. private final Map<String, List<String>> mObjectClassMap;  
  2.   private final List<OptionDef> mOptionList;  
  3.   private final Map<String, Integer> mClassFrequency;  
  4.   private final String mName;  

属性值的定义在Configuration中。

这样属性也配置好了,如果使用脚本执行CTS测试,每个CTS测试任务都会放入队列中,然后取出依次执行,直到所有执行完为止。

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/zhangbijun1230/article/details/80248824
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞