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脚本最后一行如下,

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

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

2,main方法

main方法的流程图如下,

android自动化测试CTS源码分析之一_第1张图片

CtsConsole的main方法如下,

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

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

startConsole方法如下,

public static void startConsole(Console console, String[] args)
    throws InterruptedException, ConfigurationException
  {
    // 将命令参数复制到ArrayList中
    List nonGlobalArgs = GlobalConfiguration.createGlobalConfiguration(args);
  
    console.setArgs(nonGlobalArgs); // 将命令参数保存在变量mMainArgs中
    console.setCommandScheduler(GlobalConfiguration.getInstance().getCommandScheduler());
    console.setDaemon(true);
    console.start(); // 启动线程 调用run方法

    console.awaitScheduler();
  }
}

CtsConsole的run方法如下

@Override
    public void run() {
        printLine(String.format("Android CTS %s", CtsBuildProvider.CTS_BUILD_VERSION));
        super.run();
    }

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

protected void printLine(String output)
  {
    System.out.print(output);
    System.out.println();
  }

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

2.1 任务添加

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

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

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

addCommand调用流程图如下

android自动化测试CTS源码分析之一_第2张图片

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

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

private boolean internalAddCommand(String[] args, long totalExecTime, String cmdFilePath)
    throws ConfigurationException
  {
    assertStarted();
    IConfiguration config = getConfigFactory().createConfigurationFromArgs(args);
   •••
      config.validateOptions();
      if (config.getCommandOptions().runOnAllDevices())
      {
        addCommandForAllDevices(totalExecTime, args, cmdFilePath);
      }
      else
      {
        CommandTracker cmdTracker = createCommandTracker(args, cmdFilePath);
        cmdTracker.incrementExecTime(totalExecTime);
        ExecutableCommand cmdInstance = createExecutableCommand(cmdTracker, config, false);
        addExecCommandToQueue(cmdInstance, 0L);
      }
      return true;
    }
    return false;
  }

addExecCommandToQueue方法如下,

private synchronized boolean addExecCommandToQueue(final ExecutableCommand cmd, long delayTime)
  {
    if (isShutdown()) {
      return false;
    }
    if (delayTime > 0L)
    {
      this.mSleepingCommands.add(cmd);
      
      Runnable delayCommand = new Runnable()
      {
        public void run()
        {
          synchronized (CommandScheduler.this)
          {
            if (CommandScheduler.this.mSleepingCommands.remove(cmd))
            {
              CommandScheduler.this.mReadyCommands.add(cmd);
              CommandScheduler.this.mCommandProcessWait.signalEventReceived();
            }
          }
        }
      };
      this.mCommandTimer.schedule(delayCommand, delayTime, TimeUnit.MILLISECONDS);
    }
    else
    {
      this.mReadyCommands.add(cmd);
      this.mCommandProcessWait.signalEventReceived();
    }
    return true;
  }

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

private List mReadyCommands;

2.2 组件配置

internalCreateConfigurationFromArgs方法如下,

private IConfiguration internalCreateConfigurationFromArgs(String[] arrayArgs, List optionArgsRef)
    throws ConfigurationException
  {
    if (arrayArgs.length == 0) {
      throw new ConfigurationException("Configuration to run was not specified");
    }
    optionArgsRef.addAll(Arrays.asList(arrayArgs));
    
    String configName = (String)optionArgsRef.remove(0);
    ConfigurationDef configDef = getConfigurationDef(configName, false);
    return configDef.createConfiguration();
  }

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

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

private final Map> mObjectClassMap;
  private final List mOptionList;
  private final Map mClassFrequency;
  private final String mName;

属性值的定义在Configuration中。

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

你可能感兴趣的:(---【自动化测试】)