100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 使用 Shell 编写 Android 自动化测试脚本

使用 Shell 编写 Android 自动化测试脚本

时间:2022-06-04 20:33:06

相关推荐

使用 Shell 编写 Android 自动化测试脚本

版权声明:本文章原创于 RamboPan ,未经允许,请勿转载。

使用 Shell 编写 Android 自动化测试脚本

最近碰到一个需求:就是需要反复测试一个简单的应用,是否能稳定的长期运行。

这个应用是类似一个答题过程,选择一个难度,然后选择正确的答案,然后接下来回答下一轮,答题完成会弹出结果页面,最后再自动或手动退回主界面。

因为需要点击固定的位置,反复的进行点击。刚开始测试这个应用就类似自己玩一下,感觉还有点意思。后面发现老改动,老自己点,这 …… 一点都不符合程序员的准则是吧:能自动化的就不要自己动手。

想到命令行中也能通过输入命令模拟对屏幕触控 … 那第一反应就是能不能编一个脚本,把要执行的命令与逻辑做好,脚本不断使用命令来达到模拟触屏的实现。

查阅了Mac平台使用批处理的大概思路。参考了一些Shell文档(文末附上链接),经过几天调试优化,感觉效果还算可以,拿出来分享下,也算是一个自动化测试思路吧。

先放个效果图。

首先分析这个应用的流程:

主界面:

有四个选项框,选择不同的难度。

答题界面:

虽然中间的图像部分会因为难度变化而变化,但下面四个选项位置不会改变,所以每次点击都是4个位置中的固定位置。

结果界面:

中间有可以滑动的列表,显示着每次答题的正确答案。如果点击右上角可以手动返回主菜单,如果不点击,则自动返回主菜单。

这里我们先按照简单的实现,就是一直答题,答题结束后,再返回主菜单继续。

说完了流程,我们来熟悉接下来需要使用到Shell中的操作。

(使用的是 Mac 系统,如果使用 Windows 系统,略有差别。)

我们新建一个文本文件,第一行输入

#!/bin/bash

指定解释的路径,然后将后缀改为.sh

按着新语言的学习过程,肯定是要来一个HelloWorld的,那我们再下一行输入

echo Hello,World ~

如果命令行当前位置与文件位于同一个目录,则可以直接

./test1.sh(此处 test 是我的文件名)执行当前目录下 test.sh 脚本。

如果不在同一个目录,将文件拖入命令行中就可以了。

是不是满怀期待,发现居然是Permission denied,惊不惊喜 ~

我们输入chmod 777加上刚刚的脚本名,给指定脚本权限,例如:

chmod 777 /Users/RamboPan/Desktop/test1.sh #输出:Hello,World

这次 Hello,World 如期出现。

echo作用,有许多,这就说两个作用:作为一个输出指令对字符串进行输出,或者函数的返回值。返回值一会看到。剩下依次将使用到的部分做个简单示例,需要深入了解的可以查看对应Shell文档。

四则运算(除法和 int 除法类似):

#代码:a=40;b=30;result=`expr $a + $b`echo "a + b : $result"result=`expr $a - $b`echo "a - b : $result"result=`expr $a \* $b`echo "a * b : $result"result=`expr $a / $b`echo "a / b : $result"result=`expr $a % $b`echo "a % b : $result"输出:a + b : 70a - b : 10a * b : 1200a / b : 1a % b : 10

流程控制:If

#if 使用if (( 3 < 2 ))thenecho "3 < 2"elseecho "3 > 2"#需要使用 fi 进行结束说明fi输出:3 > 2

while

#while 使用index=1;while (( $index < 5))do echo "It's $index"index=`expr $index + 1`done输出It's 1It's 2It's 3It's 4

case (switch)

#case 使用 (switch)case 1 in1) echo "It's 1" ;;2) echo "It's 2" ;;esac输出It's 1

方法定义与调用

#方法定义function sayHello(){echo "sayHello"}$(sayHello)#输出sayHellofunction tap(){adb shell input tap $1 $2}$(tap 100 100 )#输出 (这里我没插设备,所以没检测到)no devices/emulators found

大概熟悉了下Shell之后,就开始组建测试的语句。

我们先来模拟下点击和滑动的指令。

//滑动 (点 0,0 滑动到 点100,100 ) 处。adb shell input swipe 0 0 100 100//点击(点 0,0) adb shell input tap 0 0

我们连上Android设备之后,在命令行(终端)中输入滑动那句命令,因为先测试点击屏幕不容易看出效果,我们先测试滑动,从顶端划出菜单栏。

这效果很明显。此时我们在命令行中输入点击的命令,如果执行没有问题的话,刚刚弹出的菜单栏会收回,(这里点到了广告 -_- #),因为我们点在菜单栏的外面了。(部分手机的菜单栏长度各有不同,根据自己设备调整)

这样两个命令执行就没什么问题了。

因为会执行各种点位的点击与滑动,那么我们需要把点击命令的前半段,就是 英文部分 和 位置部分 拆开处理。

点击点的位置基本不动,所以此处也需要做一些变量来存储这些固定的位置。

既然都已经拆开了,那我们肯定第一想到就是做两个方法:点击某个位置,从哪滑动到哪。

先放下代码。

#点击前半段baseTap="adb shell input tap";#滑动前半段baseSwipe="adb shell input swipe";#点击的实现function tapPoint(){$baseTap $1 $2}#滑动的实现function tapAnyWhere(){$swipe $1 $2 $3 $4}

因为 shell 中引用变量需要加$符号,使用bastTap变量就是$baseTap$1$2对应为函数第几个参数,此处index1开始,和一般语言中容器序号需要从0开始不一样。

然后我们再添加一些固定的点。

#界面1 左边点的xxl=xxx;#界面1 右边点的xxr=xxx;#界面1 上边点的yyu=xxx;#界面1 下边点的yyd=xxx;#如果要点击第一个界面,左上方的 简单模式 按钮,那么我们就使用函数传入对应参数来调用。#因为左上角就是左x,上y的点。$(baseTap $xl $yu)#从左上到右下的滑动$(baseSwipe $xl $yu $xr $yd)

看着好像还可以,不过现在有一些问题。参数多了倒是还能执行,如果少些参数就没办法正确执行。

而且如果整个文件都是使用这个函数,那么如果中途要改点什么需要改动就太大了,维护成本极高,所以我们还要继续进行封装:

我们点击的过程中,需要模拟随机点击哪个按钮:比如主界面,需要 4 选 1 ,答题界面需要 4 选 1 ,结束界面返回只需要点一个。

可以把每个界面的随机点击事件,都做成一个方法,根据传入数值,执行不同的点击按钮操作。而每个对应的命令使用点的位置也只在这里出现,后期维护也很容易。

说的有点绕,还是一步一步上代码。这里需要加入shellcase使用 与随机生成函数

#定义一个随机函数#用法 $(rand 0 100) 生成 0 到 100 之间的数值(包括 0 与 100)。function rand(){min=$1max=$(($2-$min+1))num=$(($RANDOM))#此处的 echo 就负责返回结果echo $(($num%$max+$min))}#定义屏幕一的随机点击方法,function randomTapS1(){#因为四选一,所以此处直接使用 $(rand 0 3)index = $(random 0 3);#根据 index 的值,走不同的选项。case $index in#点击屏幕1左上方按钮0) $(tapPoint $xl $yu) ;;#点击屏幕1右上方按钮1) $(tapPoint $xr $yu) ;;#点击屏幕1左下方按钮2) $(tapPoint $xl $yd) ;;#点击屏幕1右下方按钮3) $(tapPoint $xr $yd) ;;#使用了 case 需要使用 case 的反向(esac)结束选择。esac#此处加入 echo 对 index 返回,调用方法可以获取结果进行输出。echo $index;}

既然能模拟出第一个界面的点击事件,那么第二个、第三个界面的点击事件,也可以依次做出来。这里就直接跳过了。

接下来就是整个应用的模拟点击流程编写了。

#先来定义个当前测试轮数与总测试轮数.startCount=0;totalCount=100;#当不满足总轮数时一直循环while((startCount<totalCount))do#输出日志,当前是第几轮开始。echo "Now start play round : $startCount"#choose mode main menucIndex=$(randomTapS1);#输出日志,第一个界面选择的是什么模式(哪个按钮)echo "Choose Mode : $cIndex";#等待一秒钟sleep 1#因为有4个问题,所以需要做一个小循环。#start inner loopi=0;j=5;while((i<j))docIndex=$(randomTapS2);#输出日志 当前点击的是第几个选项echo "Choosing: Round: $i ,choose index : $cIndex";#i++;i=`expr $i + 1`;sleep 1#退出小循环done#点击返回按钮$(randomTapS3);#输出日志 返回主菜单echo "Click back to main menu";sleep 1#测试轮数+1startCount=`expr $startCount + 1`;done

因为流程比较简单,加上有注释说明,应该不难看懂。

既然现在测试可以运行了,那么就有一个所有 App 都需要考虑的问题,适配。这些对应的按钮在不同的设备上,肯定因为分辨率不同,坐标也不同。

当然可以只在一台固定的设备上测试,比如 1920 x 1080,不过如果要在其他设备上测试的话,肯定是要用个比例与基准尺寸进行运算的。

浮点运算在shell中稍微有点麻烦,我搜了一个实现,然后也简单封成方法。

#计算两个数相乘function multiDouble(){#保留两位小数精度。echo "scale=2;$1 * $2" | bc;}

把用到的对应坐标都换成比例与对应基准尺寸就行。

#base screen sizebaseWidth=1920;baseHeight=1080;#之前用的 屏幕1 对应4个点的 x y 坐标,后面统一换成比例乘以基准尺寸。#当然基准尺寸可以考虑做成运行脚本时的参数,有兴趣的可以试下。#screen 1 # xl=780;# xr=1150;# yu=640;# yd=800;xl=$(multi 0.4 $baseWidth);xr=$(multi 0.6 $baseWidth);yu=$(multi 0.6 $baseHeight);yd=$(multi 0.74 $baseHeight);

现在又想到一个问题,如果 …… 有多比例需要考虑(相乘)怎么办(真的是过场有点多哈 ~ (→_→) ),那么我们可以考虑for循环来实现。

#计算两个数相乘function multiDouble(){#保留两位小数精度。echo "scale=2;$1 * $2" | bc;}#计算多个数相乘,判断传入参数个数多少计算不同计算function multi(){#没有参数时返回0if [ $# = 0 ]then echo 0#一个参数时返回该参数elif [ $# = 1 ]then echo $1#两个参数时返回乘积elif [ $# = 2 ]then echo $(multiDouble $1 $2)#多个参数时使用循环,声明一个结果,循环轮乘elseresult=1.0;for var in $@do#echo "It's $(($index))"result=$(multiDouble $result $var)doneecho $resultfi}#######################调用示范:echo $(multi)echo $(multi 1.1)echo $(multi 1.1 2.2)echo $(multi 1.1 2.2 3.3 )echo $(multi 1.1 2.2 3.3 4.4 )输出结果:01.12.427.9835.11

这样使用multi函数,不管多少参数都可以正确使用,真是机智 : ) 。

最后放一个完整版的代码,程序不一样,也只是仅供参考。

#!/bin/bash#define a ramdom funtionfunction rand(){min=$1max=$(($2-$min+1))num=$(($RANDOM))echo $(($num%$max+$min))}#define a tap anywhere functionfunction tapAnyWhere(){$baseTap $(rand 0 $baseWidth) $(rand 0 $baseHeight);}#define a function to tap specify pointfunction tapPoint(){$baseTap $1 $2}#define a random tap button function in screen1function randomTapS1(){index=$(rand 0 3);case $index in0) $(tapPoint $xl $yu) ;;1) $(tapPoint $xr $yu) ;;2) $(tapPoint $xl $yd) ;;3) $(tapPoint $xr $yd) ;;esacecho $index;}#define a random tap button function in screen2function randomTapS2(){index=$(rand 0 3);case $index in0) $(tapPoint $x1 $y1) ;;1) $(tapPoint $x2 $y1) ;;2) $(tapPoint $x3 $y1) ;;3) $(tapPoint $x4 $y1) ;;esacecho $index;}#define a random tap button function in screen2function randomTapS3(){$(tapPoint $xb $yb);}#define a swipe anywhere functionfunction swipeAnyWhere(){$baseSwipe $(rand 0 $baseWidth) $(rand 0 $baseHeight) $(rand 0 $baseWidth) $(rand 0 $baseHeight);}#define a center swipe in result pagefunction swipteCenter(){$baseSwipe $(rand $xStart $xEnd) $(rand yStart $yEnd) $(rand $xStart xEnd) $(rand yStart $yEnd);}#define two float multifunction multiDouble(){echo "scale=2;$1 * $2" | bc;}#define several float multifunction multi(){if [ $# = 0 ]then echo 0elif [ $# = 1 ]then echo $1elif [ $# = 2 ]then echo $(multiDouble $1 $2)elseecho $(multi $1 $(multiDouble $2 $3)) fi}function addDouble(){echo "scale=2;$1 + $2"|bc;}function add(){if [ $# = 0 ]then echo 0elif [ $# = 1 ]then echo $1elif [ $# = 2 ]then echo $(addDouble $1 $2)elseecho $(add $1 $(addDouble $2 $3)) fi}startCount=0;totalCount=100;#screen 1:fou button:#leftTop 780 640#rightTop 1150 640#leftBottom 780 800#rightBottom 1150 800#screen 2:four button:#key1:475 1024 #key2:730 1025#key3:1010 1024#key4:1277 1024#sreen 3:back button# 1815 110#base screen sizebaseWidth=1920;baseHeight=1080;#screen 1 # xl=780;# xr=1150;# yu=640;# yd=800;xl=$(multi 0.4 $baseWidth);xr=$(multi 0.6 $baseWidth);yu=$(multi 0.6 $baseHeight);yd=$(multi 0.74 $baseHeight);#screen 2# x1=475;# x2=730;# x3=1010;# x4=1277;# y1=1024;x1=$(multi 0.25 $baseWidth);x2=$(multi 0.38 $baseWidth);x3=$(multi 0.52 $baseWidth);x4=$(multi 0.25 $baseWidth);y1=$(multi 0.95 $baseHeight);#screen 3# xb=1815;# yb=110;xb=$(multi 0.945 $baseWidth);yb=$(multi 0.1 $baseHeight);#center rectxStart=$(multi 0.156 $baseWidth);xWidth=$(multi 0.71 $baseWidth);xEnd=$(add $xStart $xWidth);yStart=$(multi 0.28 $baseHeight);yHeight=$(multi 0.49 $baseHeight);yEnd=$(add $yStart $yHeight);#base input cmdbaseTap="adb shell input tap";baseSwipe="adb shell input swipe";#start out loop while((startCount<totalCount))doecho "Now start play round : $startCount"#choose mode main menucIndex=$(randomTapS1);echo "Choose Mode : $cIndex";sleep 1#start inner loopi=0;j=5;while((i<j))docIndex=$(randomTapS2);echo "Choosing: Round: $i ,choose index : $cIndex";i=`expr $i + 1`;sleep 1done$(randomTapS3);echo "Click back to main menu";sleep 1startCount=`expr $startCount + 1`;done

如果有疑问或者意见,欢迎指出,共同讨论。

参考文章:

Shell:

/taiyang1987912/article/details/39551385

/linux/linux-shell-func.html

Android:

/adb-shell-input.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。