悠悠小仙仙 发表于 2019-3-11 17:13:45

UiAutomator启动命令runtest浅析

本帖最后由 悠悠小仙仙 于 2019-3-11 17:19 编辑

首先Appium运行,推送Bootstrap.jar到设备端,而Bootstrap.jar这个jar实际上就是继承了UiAutomatorTestCase的测试类,然后通过命令运行这个jar包开始执行自动化脚本先来看看执行命令:adb.exe -s 5b30ee87 shell uiautomator runtest AppiumBootstrap.jar -c io.appium.android.bootstrap.Bootstrap -e pkg com.main -e disableAndroidWatchers false1.help先通过uiautomator help看看命令(1)help:帮助
(2)runtest:执行UI自动化测试
(3)dump:创建一个当前ui视图结构的xml文件
(4)events:打印accessibility事件
从帮助中可以看到uiautomator主要的4个命令,但是有个疑问又来了,uiautomator如何在android系统的手机设备中接收到这些并运行的。
2.uiautomator的shell脚本
在uiautomator源码的cmds文件夹中找到了uiautomator的shell文件,这个文件就是作为uiautomator初始化并启动执行的入口。export run_base=/data/local/tmp
export base=/system

# if not running as root, trick dalvik into using an alternative dex cache
if [ ${USER_ID} -ne 0 ]; then
tmp_cache=${run_base}/dalvik-cache

if [ ! -d ${tmp_cache} ]; then
    mkdir -p ${tmp_cache}
fi

export ANDROID_DATA=${run_base}
fi(1)首先定义2个变量run_base、base,值都是设备的路径(再次提醒,这个uiautomator的shell文件是在android设备中运行,shell作为Linux的一部分,在Android设备中运行就没什么好说的,不理解的可以了解一下Android系统的组成)
(2)然后判断一下是否root用户运行:通过内部变量拿到用户ID,如果拿到的ID不是0,则执行语句块内容(root用户的ID为0,非root用户的ID不是0),下面的脚本就是确定一下数据存放地址。# take first parameter as the command
cmd=${1}

if [ -z "${1}" ]; then
cmd="help"
fi

# strip the command parameter
if [ -n "${1}" ]; then
shift
fi

CLASSPATH=/system/framework/android.test.runner.jar:${base}/framework/uiautomator.jar
3)拿到第一个参数赋值给cmd变量,然后判断一下,如果第一个参数的值长度为0,则cmd值为help,从这里可以看到如果第一个参数没有值,肯定就是执行help的结果。
(4)再判断第一个参数的值不为空,则左移一个参数,这里需要特别注意,如果第一个参数有值,这里已经通过shift左移了一个参数# eventually args will be what get passed down to Java code
args=
# we also pass the list of jar files, so we can extract class names for tests
# if they are not explicitly specified
jars=

# special case pre-processing for 'runtest' command
if [ "${cmd}" == "runtest" ]; then
# first parse the jar paths
while [ true ]; do
    if [ -z "${1}" ]; then
      echo "Error: more parameters expected for runtest; please see usage for details"
      cmd="help"
      break
    fi
    jar=${1}
    if [ "${1:0:1}" = "-" ]; then
      # we are done with jars, starting with parameters now
      break
    fi
    # if relative path, append the default path prefix
    if [ "${1:0:1}" != "/" ]; then
      jar=${run_base}/${1}
    fi
    # about to add the file to class path, check if it's valid
    if [ ! -f ${jar} ]; then
      echo "Error: ${jar} does not exist"
      # force to print help message
      cmd="help"
      break
    fi
    jars=${jars}:${jar}
    # done processing current arg, moving on
    shift
done (5)如果第一个参数是runtest,cmd等于runtest,进入if语句块,然后开始循环判断,再次提醒上面已经shift左移一个参数,所以现在已经把runtest移走了,第一个参数是runtest后面的AppiumBootstrap.jar了。先判断第一个参数长度如为空,则又回到help输出让你多看看help的用法,用习惯命令的都知道,输错命令动不动就是显示help的结果。
(6)然后把第一个参数交给jar变量;进入判断,${1:0:1}的意思是取出${1}变量0到1的值,如果等于-,break回家再见;再往下不等于/,则jar=${run_base}/${1},根据上下文,jar的值得到是:/data/local/tmp/AppiumBootstrap.jar
(7)再次判断这个文件存不存在,不存在继续break回家再见;然后执行jars=${jars}: ${jar},jars的值为:/data/local/tmp/AppiumBootstrap.jar(冒号前面的${jars是空})。# look for --nohup: if found, consume it and trap SIG_HUP, otherwise just
# append the arg to args
while [ -n "${1}" ]; do
    if [ "${1}" = "--nohup" ]; then
      trap "" HUP
      shift
    else
      args="${args} ${1}"
      shift
    fi
done
else
# if cmd is not 'runtest', just take the rest of the args
args=${@}
fi
(8)又一个循环,先判断${1}是否为空,不为空进入循环,如果参数等于--nohup,则忽略HUP信号,继续运行。可以回到上面看help帮助中的--nohub命令解释。(trap为捕捉信号,如HUP表示终端中断,INT键盘中断等等),并执行shift左移
(9)如果不等于nohup命令,取出参数值赋值给args变量。就算是命令中有--nohup,也只会进入一次if,其它都会进入else,直到取出的参数为空退出循环
(10)继续else语句块,这个else是对应上面cmd==runtest的else,也就是命令等于dump、events的时候进入,就没那么麻烦了,全部参数都复制给argsargs="${cmd} ${args}"
if [ -n "${jars}" ]; then
   args="${args} -e jars ${jars}"
fi

CLASSPATH=${CLASSPATH}:${jars}
export CLASSPATH
exec app_process ${base}/bin com.android.commands.uiautomator.Launcher ${args}
11)args的值${cmd} ${args},注意中间有个空格,然后进入一个判断,判断${jars}的值是否为空,而只有runtest的时候,才不会为空。所以runtest的时候,args的值:runtest -e jars ${jars},其他时候args的值都为${cmd} ${args}
(12)${CLASSPATH}: ${jars}处理后CLASSPATH的值:
/system/framework/android.test.runner.jar:/system/framework/uiautomator.jar::/data/local/tmp/AppiumBootstrap.jar
(13)export引入这些jar包,其中包含uiautomator.jar这个重量级的jar包。在uiautomator使用过程中,引入的是在本地引入,而在android设备中运行时,是从android中引入,所以在编写代码过程中一定要注意,编程环境用的版本需要小于等于运行环境的版本。
(14)通过app_process指定命令的工作路径为/system/bin,并运行com.android.commands.uiautomator.Launcher类传入的参数为${args}

页: [1]
查看完整版本: UiAutomator启动命令runtest浅析