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

3, 任务调度

CommandScheduler流程图如下,


CommandScheduler的run方法主要代码如下,

IDeviceManager manager = getDeviceManager();
      startRemoteManager();
      this.mRunLatch.countDown();
      manager.addDeviceMonitor(new AvailDeviceMonitor(null)); // 测试的手机设备

while (!isShutdown())
      {
        this.mCommandProcessWait.waitAndReset(this.mPollTime);
        checkInvocations();
        processReadyCommands(manager);
      }

不断循环调用processReadyCommands方法,从mReadyCommands中读取任务,然后执行。processReadyCommands方法如下,

protected void processReadyCommands(IDeviceManager manager)
  {
    Map<ExecutableCommand, ITestDevice> scheduledCommandMap = new HashMap();
    synchronized (this)
    {
      Collections.sort(this.mReadyCommands, new ExecutableCommandComparator(null));
      Iterator<ExecutableCommand> cmdIter = this.mReadyCommands.iterator();
      while (cmdIter.hasNext())
      {
        ExecutableCommand cmd = (ExecutableCommand)cmdIter.next();
        ITestDevice device = manager.allocateDevice(cmd.getConfiguration().getDeviceRequirements());
        if (device != null)
        {
          cmdIter.remove();
          this.mExecutingCommands.add(cmd);
          
          scheduledCommandMap.put(cmd, device);
        }
      }
    }
    for (Map.Entry<ExecutableCommand, ITestDevice> cmdDeviceEntry : scheduledCommandMap.entrySet())
    {
      ExecutableCommand cmd = (ExecutableCommand)cmdDeviceEntry.getKey();
      startInvocation(new FreeDeviceHandler(getDeviceManager(), new ICommandScheduler.IScheduledInvocationListener[0]), (ITestDevice)cmdDeviceEntry.getValue(), cmd);
      if (cmd.isLoopMode()) {
        addNewExecCommandToQueue(cmd.getCommandTracker());
      }
    }
  }

首先将任务打包到mExecutingCommands中,然后利用for循环逐个取出调用startInvocation进行处理。

private void startInvocation(ICommandScheduler.IScheduledInvocationListener listener, ITestDevice device, ExecutableCommand cmd)
  {
    if (hasInvocationThread(device)) {
      throw new IllegalStateException(String.format("Attempting invocation on device %s when one is already running", new Object[] { device.getSerialNumber() }));
    }
    LogUtil.CLog.d("starting invocation for command id %d", new Object[] { Integer.valueOf(cmd.getCommandTracker().getId()) });
    String invocationName = String.format("Invocation-%s", new Object[] { device.getSerialNumber() });
    InvocationThread invocationThread = new InvocationThread(invocationName, listener, device, cmd);
    
    invocationThread.start();
    addInvocationThread(invocationThread);
  }

InvocationThread是CommandScheduler的内部类,也继承于Thread。

startInvocation方法根据测试指令启动InvocationThread线程去进行测试。

InvocationThread线程的流程图如下,


InvocationThread中的run部分代码如下,

this.mCmd.commandStarted();
instance.invoke(this.mDevice, config, 
new CommandScheduler.Rescheduler(CommandScheduler.this, this.mCmd.getCommandTracker()), 
new ITestInvocationListener[] { this.mListener });

TestInvocation称为CTS的任务调度室, 因为它就是去一步一步的运行组件,

组件与组件之间并不知道对方的存在,只有TestInvocation自己知道。

Invoke方法通过反射的机制得到组件对象,然后调用其中的接口方法,然后再传给下一个组件。

performInvocation主要包括以下步骤:

1,首先调用startInvocation方法启动所有监听器,主要是通知作用。

2, 调用prepareAndRun方法进行CTS测试。

3,测试完成之后给出报告结果,并且调用doTeardown进行后续处理。

runtest方法如下,

private void runTests(ITestDevice device, IConfiguration config, ITestInvocationListener listener)
    throws DeviceNotAvailableException
  {
    for (IRemoteTest test : config.getTests())
    {
      if ((test instanceof IDeviceTest)) {
        ((IDeviceTest)test).setDevice(device);
      }
      test.run(listener);
    }
  }

这个IdeviceTest对象在此处特指CtsTest对象, CtsTest定义如下,

public class CtsTest implements IDeviceTest, IResumableTest, IShardableTest, IBuildReceiver {

CtsTest的run方法逻辑如下

1,根据测试指令解析测试项。

2,从所有解析的测试项中抽出CTS测试指令plan的测试项。

3,对每个测试项进行测试。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值