移动性能测试 shell 管理 monkey 压力测试续——监控方案重构及 MCM 监控维护

浮云 · November 25, 2015 · Last by 浮云 replied at October 15, 2018 · 4624 hits
本帖已被设为精华帖!
在遇到monkey执行完后概率性进程不退出(进程名com.android.commands.monkey变为commands.monkey),就想要整体重新设计下。
加上最近提出要交付手工测试组执行,面临对于不懂monekey测试的人员也需要按计划完成专项测试。
我自己又给测试方式自提了新需求,于是整体思考重构了 monkey 压力测试及优化了MCM监控方案。

一、自提需求

1、按设定执行时间方式进行monkey测试

目的:避免无法按事件数预知准确时间,设定monkey压力测试1小时就是执行1小时测试。
方式:按10000事件数执行monkey测试,到设定时长则kill monkey进程,未达到则重复执行。

2、固定形式的monkey语句测试需按case形式维护

目的:由于交付的执行人员不一定懂monkey,固定的执行写成case便于执行人员调用,同时也是简化主控制逻辑的维护方式。
方式:维护case.sh作为moneky执行方式的维护脚本
沿用:这里我沿用了之前想到要看下mongkey测试结束后等待一会(如10分钟),看下内存是否会继续上涨,就在设计时加入了测试结束后等待10分钟再停止应用;停止应用是为了避免之前测试后的状态影响下一个包的测试,就释放掉了进程。

3、将通用函数单独文件维护,将shell脚本的函数部分和控制部分非开维护。

目的:为了方便通用函数的复用,同时也是为了建立自己的一种写脚本模式。
方式:function.sh维护全局变量和自定义函数,source命令加载

4、组件形式的app需要侧重组件的界面进行压力测试,需要将显示的activity圈定在一定范围内。

目的:对于无法单包执行的组件app,通过和依赖包一起测试完成压力测试需求。
方式:两个包进行测试,其中一个是调用组件的app,另一个是独立的组件app;monekey执行后,使用一个子进程轮询判定SurfaceFlinger是否包含组件包名,如果不包含则使用长按键事件或am start 组件activity的形式使组件画面显示;monekey事件类型则只配操作不配置appswitch。

5、把MCM监控方案优化维护,维护一个不需要root权限的版本。

目的:想增加自己设计的MCM监控方案的适用性
方式:使用push busybox到/data/local/tmp,调用此busybox命令进行脚本监控。

问题的解决

1、moneky压力测试方案V2.0

(1)全局变量及函数维护——function.sh
#!/system/bin/sh

########## Global Variable ##########
if [ -f /data/local/tmp/busybox ];then
export bb="/data/local/tmp/busybox"
else
echo "No /data/local/tmp/busybox"
exit
fi
if [ -f /data/local/tmp/stop ];then
$bb rm /data/local/tmp/stop
fi
#Test Result Folder
export testresult="/data/local/tmp/monkey"
if [ -d $testresult ];then
$bb rm -r $testresult
fi
mkdir -p $testresult/log
#android version
export android=`getprop ro.build.version.release|$bb awk -F. '{print $1}'`
#root
export root=`id|$bb grep -c root`

########## Function ##########

#Add comments to comments.csv
comment(){
if [ ! -f $testresult/comments.csv ];then
echo "Date,Tag,Comments,Info" >$testresult/comments.csv
fi
echo "`date +%m-%d" "%H":"%M":"%S`,$1,$2,$3" >>$testresult/comments.csv
}

#Create Log
c_log(){
if [ -f $testresult/error.pid ];then
local E_pid=`$bb awk 'NR==1{print $NF}' $testresult/error.pid`
if [ -d /proc/$E_pid ];then
if [ $1 -eq 0 ];then
comment "c_log" "error.pid is running, exit." "$E_pid"
exit
elif [ $1 -eq 1 ];then
comment "c_log" "error.pid is running, kill." "$E_pid"
kill -9 $E_pid 2>/dev/null
fi
else
comment "c_log" "exist error.pid, not running" "$E_pid"
fi
$bb rm $testresult/error.pid
fi
if [ $1 -eq 0 ];then
logcat -c
if [ `cat /sys/devices/virtual/thermal/thermal_zone*/type|grep -c mtk` -eq 0 ];then
logcat -v time -s AndroidRuntime:E ActivityManager:E DEBUG:F >$testresult/error.log &
else
logcat -v time -s AndroidRuntime:E ANRManager:E AEE/DEBUG:F >$testresult/error.log &
fi
local tmp=`$bb ps`
echo "$tmp"|$bb grep "logcat -v time -s"|$bb awk 'NR==1{print $1}' >$testresult/error.pid
comment "c_log" "Start error.pid." "`$bb awk 'NR==1{print $NF}' $testresult/error.pid`"
fi
}

#wait time between monkey test case
wait_time(){
local chek_begin=`$bb awk -F. 'NR==1{print $1}' /proc/uptime`
while true;do
if [ $((`$bb awk -F. 'NR==1{print $1}' /proc/uptime`-chek_begin)) -ge $1 ];then
break
elif [ -f $testresult/monkey_error.txt ];then
break
else
$bb sleep 5
fi
done
}

########## monkey function ##########

#longpress to resume app.
#$1-keycode; $2-package name; $3-running time
longpress(){
local chek_begin=`$bb awk -F. 'NR==1{print $1}' /proc/uptime`
while true;do
if [ $android -eq 6 ];then
local tmp=`dumpsys SurfaceFlinger|$bb grep "|......|"`
else
local tmp=`dumpsys SurfaceFlinger|$bb grep "|....|"`
fi
if [ `echo "$tmp"|$bb grep -c "$2"` -eq 0 ];then
input keyevent --longpress $1
fi
if [ $((`$bb awk -F. 'NR==1{print $1}' /proc/uptime`-chek_begin)) -ge $3 ];then
break
else
$bb sleep 1
fi
done
}

#longpress keycode 3 and 4 one by one: $1-package of keycode 3; $2-package of keycode 4; $3-sleep time; $4-running time
longkey(){
local l_key=3
local chek_begin=`$bb awk -F. 'NR==1{print $1}' /proc/uptime`
local package=$1
while true;do
if [ $android -eq 6 ];then
local tmp=`dumpsys SurfaceFlinger|$bb grep "|......|"`
else
local tmp=`dumpsys SurfaceFlinger|$bb grep "|....|"`
fi
if [ `echo "$tmp"|$bb grep -c "$package"` -eq 0 ];then
input keyevent --longpress $l_key
fi
if [ $((`$bb awk -F. 'NR==1{print $1}' /proc/uptime`-chek_begin)) -ge $4 ];then
break
else
$bb sleep $3
fi
case $l_key in
3)
local l_key=4
local package=$2
;;
4)
local l_key=3
local package=$1
;;
esac
done
}

#longam to resume app.
#2 args: $1-package name; $2-running time;
#3 args: $1-package name; $2-running time; $3-activity(more than 1 activity: spilt by | . run them one by one);
longam(){
case $# in
2)
local activity=`dumpsys activity $1|$bb grep ACTIVITY|$bb awk 'NR==1{print $2}'`
local a_loops=1
;;
3)
local activity="$3"
local a_loops=`echo "$3"|$bb awk -F"|" '{print NF}'`
;;
esac
if [ ! -z "$activity" ];then
local chek_begin=`$bb awk -F. 'NR==1{print $1}' /proc/uptime`
local i=1
while true;do
if [ $android -eq 6 ];then
local tmp=`dumpsys SurfaceFlinger|$bb grep "|......|"`
else
local tmp=`dumpsys SurfaceFlinger|$bb grep "|....|"`
fi
if [ `echo "$tmp"|$bb grep -c "$1"` -eq 0 ];then
if [ $a_loops -gt 1 ];then
local activity="`echo "$3"|$bb awk -F"|" -v P=$i '{print $P}'`"
if [ $i -lt $a_loops ];then
local i=$((i+1))
else
local i=1
fi
fi
local am_start=`am start $activity 2>&1`
if [ `echo "$am_start"|$bb grep -c "Error"` -ne 0 ];then
comment "longam" "am_error" "$am_start"
fi
fi
if [ $((`$bb awk -F. 'NR==1{print $1}' /proc/uptime`-chek_begin)) -ge $2 ];then
break
else
$bb sleep 1
fi
done
else
comment "longam" "No activity" "$1"
wait_time $2
fi
}

monkey_test(){
if [ -f $testresult/monkey_error.txt ];then
$bb rm $testresult/monkey_error.txt
fi
case $# in
3)
sh /data/local/tmp/case.sh $1 $2 "$3" &
;;
4)
sh /data/local/tmp/case.sh $1 "$2" "$3" "$4" &
;;
*)
echo "Args are wrong!!!"
exit
;;
esac
}

#if timeout, kill case.sh: $1-wait time
monkey_timeout(){
wait_time $(($1+600))
local chek_begin=`$bb awk -F. 'NR==1{print $1}' /proc/uptime`
while true;do
local tmp=`$bb ps`
if [ `echo "$tmp"|$bb grep -c case.sh` -ne 0 ];then
if [ $((`$bb awk -F. 'NR==1{print $1}' /proc/uptime`-chek_begin)) -ge 60 ];then
if [ -f $testresult/log.pid ];then
local L_pid=`$bb awk 'NR==1{print $NF}' $testresult/log.pid`
comment "monkey_timeout" "kill pid of log.pid." "$L_pid"
kill -9 $L_pid 2>/dev/null
fi
if [ -f $testresult/kmsg.pid ];then
local L_pid=`$bb awk 'NR==1{print $NF}' $testresult/kmsg.pid`
comment "monkey_timeout" "kill pid of log.pid." "$L_pid"
kill -9 $L_pid 2>/dev/null
fi
local pid=`echo "$tmp"|$bb grep "case.sh"|$bb awk '{print $1}'`
if [ ! -z "$pid" ];then
kill -9 `echo $pid`
fi
comment "monkey_timeout" "After waiting 60S, kill case.sh."
break
else
comment "monkey_timeout" "case.sh not finish"
$bb pkill com.android.commands.monkey
$bb sleep 5
fi
else
break
fi
done
}
(2)monkey执行维护case——case.sh
#!/system/bin/sh

#args:
# type1 run case: $1-running time; $2-case id; $3-case arg
# type2 run monkey by "--pct":$1-running time; $2-(-p/-c); $3-(--pct); $4-the file name of monkey log.

if [ -f /data/local/tmp/busybox ];then
bb="/data/local/tmp/busybox"
else
echo "No /data/local/tmp/busybox"
exit
fi

${testresult="/data/local/tmp/monkey"} 2>/dev/null
if [ ! -d $testresult/monkey_log ];then
mkdir -p $testresult/monkey_log
fi
if [ ! -d $testresult/log ];then
mkdir $testresult/log
fi
#android version
android=`getprop ro.build.version.release|$bb awk -F. '{print $1}'`
#root
root=`id|$bb grep -c root`

#Add comments to comments.csv
comment(){
if [ ! -f $testresult/comments.csv ];then
echo "Date,Tag,Comments,Info" >$testresult/comments.csv
fi
echo "`date +%m-%d" "%H":"%M":"%S`,$1,$2,$3" >>$testresult/comments.csv
}

#lock or unlock screen.
#$1: 0--lock; 1--unlock
lock(){
${wm_size_x=`wm size|$bb awk -F" |x" '{print $(NF-1)}'`} 2>/dev/null
${wm_size_y=`wm size|$bb awk -F" |x" '{print $NF}'`} 2>/dev/null
while true;do
if [ `cat /sys/class/leds/lcd-backlight/brightness` -eq 0 ];then
if [ $1 -eq 0 ];then
break
else
input keyevent 26&&$bb sleep 1&&input swipe $((v/2)) $((4*wm_size_y/5)) $((wm_size_x/2)) $((wm_size_y/5))
fi
else
if [ $1 -eq 0 ];then
input keyevent 26
else
if [ $android -eq 6 ];then
local tmp=`dumpsys SurfaceFlinger|$bb grep "|......|"`
else
local tmp=`dumpsys SurfaceFlinger|$bb grep "|....|"`
fi
case `echo "$tmp"|$bb awk 'BEGIN{r="o"}{if($NF=="com.android.systemui.ImageWallpaper")r="l"}END{print NR-1 r}'` in
"1o")
local state=0
;;
"3l")
local state=1
;;
*)
local state=2
;;
esac
if [ $state -eq 0 ];then
input keyevent 26&&$bb sleep 1&&input swipe $((v/2)) $((4*wm_size_y/5)) $((wm_size_x/2)) $((wm_size_y/5))
elif [ $state -eq 1 ];then
input swipe $((wm_size_x/2)) $((4*wm_size_y/5)) $((wm_size_x/2)) $((wm_size_y/5))
else
break
fi
fi
fi
$bb sleep 1
done
}

#Create Log
C_log(){
if [ -f $testresult/log.pid ];then
local L_pid=`$bb awk 'NR==1{print $NF}' $testresult/log.pid`
if [ -d /proc/$L_pid ];then
comment "C_log" "kill pid of log.pid." "$L_pid"
kill -9 $L_pid 2>/dev/null
else
comment "C_log" "exist log.pid, not running" "$L_pid"
fi
if [ -f $testresult/kmsg.pid ];then
local L_pid=`$bb awk 'NR==1{print $NF}' $testresult/kmsg.pid`
if [ -d /proc/$L_pid ];then
comment "C_log" "kill pid of kmsg.pid." "$L_pid"
kill -9 $L_pid 2>/dev/null
else
comment "C_log" "exist kmsg.pid, not running" "$L_pid"
fi
fi
fi
if [ $root -eq 1 ];then
cat /proc/kmsg >$testresult/log/$1.kmsg &
echo $! >$testresult/kmsg.pid
fi
${logcat_type=`logcat --help 2>&1 |grep -c "\-T <count>"`} 2>/dev/null
if [ $logcat_type -eq 1 ];then
logcat -v threadtime -b all -T 1 >$testresult/log/$1.log &
else
logcat -c
logcat -v threadtime >$testresult/log/$1.log &
fi
echo $! >$testresult/log.pid
}

save_log(){
if [ -f $testresult/log/$1.log ];then
comment "save_log" "Start save" "$1"
local time_name=`date +%Y%m%d%H%M%S`
mkdir $testresult/log/$time_name
$bb pstree -p >$testresult/log/$time_name/pstree.txt
$bb top -b -n 1 >$testresult/log/$time_name/top.txt
lock 1
screencap -p $testresult/log/$time_name.png
dmesg >$testresult/log/$time_name/dmesg.txt
dumpsys dropbox --print >$testresult/log/$time_name/dropbox.txt
cat /proc/meminfo >$testresult/log/$time_name/proc_meminfo.txt
dumpsys meminfo >$testresult/log/$time_name/dumpsys_meminfo.txt
if [ -f $testresult/log.pid ];then
local L_pid=`$bb awk 'NR==1{print $NF}' $testresult/log.pid`
if [ -d /proc/$L_pid ];then
comment "save_log" "kill pid of log.pid." "$L_pid"
kill -9 $L_pid 2>/dev/null
else
comment "save_log" "exist log.pid, not running" "$L_pid"
fi
if [ -f $testresult/kmsg.pid ];then
local L_pid=`$bb awk 'NR==1{print $NF}' $testresult/kmsg.pid`
if [ -d /proc/$L_pid ];then
comment "save_log" "kill pid of kmsg.pid." "$L_pid"
kill -9 $L_pid 2>/dev/null
else
comment "save_log" "exist kmsg.pid, not running" "$L_pid"
fi
$bb rm $testresult/kmsg.pid
fi
$bb rm $testresult/log.pid
fi
if [ $root -eq 1 ];then
if [ ! -z "`ls /data/anr 2>/dev/null`" ];then
$bb mv /data/anr/* $testresult/log/$time_name/
fi
if [ ! -z "`ls /data/tombstones 2>/dev/null`" ];then
$bb mv /data/tombstones/* $testresult/log/$time_name
fi
if [ ! -z "`ls /data/system/dropbox/ 2>/dev/null`" ];then
mkdir $testresult/log/$time_name/dropbox
$bb mv /data/system/dropbox/* $testresult/log/$time_name/dropbox
fi
$bb tar -zcvf $testresult/log/$1_`date +%Y%m%d%H%M%S`.tar.gz -C $testresult/log $1.log $1.kmsg $time_name.png $time_name
$bb rm $testresult/log/$1.kmsg
else
$bb tar -zcvf $testresult/log/$1_`date +%Y%m%d%H%M%S`.tar.gz -C $testresult/log $1.log $time_name.png $time_name
fi
$bb rm $testresult/log/$1.log $testresult/log/$time_name.png
$bb rm -r $testresult/log/$time_name
comment "save_log" "Finish save" "$1"
else
comment "save_log" "Not Found" "$1"
fi
ls $testresult/log|grep log|$bb awk -F. '{print $1}' |while read T;do
comment "save_log" "Found log" "$T"
if [ $root -eq 1 ];then
$bb tar -zcvf $testresult/log/$T.tar.gz -C $testresult/log $T.log $T.kmsg
$bb rm $testresult/log/$T.kmsg
else
$bb tar -zcvf $testresult/log/$T.tar.gz -C $testresult/log $T.log
fi
$bb rm $testresult/log/$T.log
done
}

#wait time between monkey test case
wait_time(){
local log_n=`date +%Y%m%d%H%M%S`
C_log $log_n
local chek_begin=`$bb awk -F. 'NR==1{print $1}' /proc/uptime`
while true;do
if [ $((`$bb awk -F. 'NR==1{print $1}' /proc/uptime`-chek_begin)) -ge $1 ];then
break
elif [ -f $testresult/monkey_error.txt ];then
break
else
$bb sleep 1
fi
done
save_log $log_n
}

#run monkey steps.
run_monkey(){
$bb pkill com.android.commands.monkey
local log_n=0
local log_e=0
while [ $((`$bb awk -F. '{print $1}' /proc/uptime`-case_start_time)) -lt $1 ];do
local tmp=`/system/bin/ps`
local C_boot=`echo "$tmp"|$bb grep -c bootanimation`
if [ $C_boot -eq 0 ];then
local check=`echo "$tmp"|$bb grep -c com.android.commands.monkey`
if [ $check -eq 0 ];then
#check log
if [ $log_n"a" != "0a" ];then
save_log $log_n
fi
local log_n=`date +%Y%m%d%H%M%S`
C_log $log_n
lock 1
comment "run_monkey" "$2" "Start test: $3 $1""S $4_$log_n"
monkey $2 --throttle 500 --monitor-native-crashes $3 -v -v -v 2000 1>$testresult/monkey_log/$4_$log_n.txt 2>&1 &
$bb sleep 3
if [ `grep -c "No activities found to run, monkey aborted" $testresult/monkey_log/$4_$log_n.txt` -ne 0 ];then
comment "run_monkey" "$2" "Error: No activities found to run, monkey aborted."
save_log $log_n
echo "$2 No activities" >$testresult/monkey_error.txt
exit
fi
elif [ $check -eq 1 ];then
#in activity contain "login", then press back.
if [ $android -eq 6 ];then
local tmp=`dumpsys SurfaceFlinger|$bb grep "|......|"`
else
local tmp=`dumpsys SurfaceFlinger|$bb grep "|....|"`
fi
if [ `echo "$tmp"|$bb grep -c "login"` -ne 0 ];then
input keyevent 4
elif [ `echo "$tmp"|$bb awk 'END{print NR}'` -eq 2 ];then
lock 1
fi
#IF there are more than two monkey commands, kill all.
elif [ $check -gt 1 ];then
comment "run_monkey" "$2" "Error: $check monkey commands, killed!!!"
$bb pkill com.android.commands.monkey
fi
$bb sleep 1
else
screencap -p $testresult/log/`date +%Y%m%d%H%M%S`.png
comment "run_monkey" "bootanimation" "sleep 5"
$bb sleep 5
fi
done
$bb pkill com.android.commands.monkey
comment "run_monkey" "$2" "Finish test."
save_log $log_n
lock 0
}

#case
caselist(){
case "$1" in
#test one package
0)
case "$3" in
"com.letv.app.appstore"|"com.letv.games")
run_monkey $2 "-p $3" "--pct-touch 20 --pct-trackball 5 --pct-motion 35 --pct-flip 5 --pct-appswitch 30 --pct-anyevent 5" "case$1_$3"
wait_time 600
am force-stop $3
;;
"com.android.launcher3")
run_monkey $2 "-p $3" "--pct-touch 20 --pct-trackball 10 --pct-motion 50 --pct-flip 5 --pct-appswitch 10 --pct-anyevent 5" "case$1_$3"
wait_time 600
am force-stop $3
;;
"com.letv.android.quicksearchbox"|"com.letv.android.voiceassistant"|"com.google.android.googlequicksearchbox")
run_monkey $2 "-p com.android.launcher3 -p $3" "--pct-touch 30 --pct-trackball 10 --pct-motion 45 --pct-flip 5 --pct-appswitch 5 --pct-anyevent 5" "case$1_$3"
wait_time 600
am force-stop $3
;;
"com.letv.android.client"|"com.letv.android.letvlive"|"com.google.android.youtube"|"com.letv.internationalsarrs")
run_monkey $2 "-p $3" "--pct-touch 10 --pct-trackball 10 --pct-motion 10 --pct-flip 10 --pct-appswitch 55 --pct-anyevent 5" "case$1_$3"
wait_time 600
am force-stop $3
;;
"com.letv.lesophoneclient")
run_monkey $2 "-p $3 -p com.letv.android.client" "--pct-touch 30 --pct-trackball 10 --pct-motion 45 --pct-flip 5 --pct-appswitch 5 --pct-anyevent 5" "case$1_$3"
wait_time 600
am force-stop $3
am force-stop com.letv.android.client
;;
"com.android.gallery3d"|"com.google.android.apps.photos"|"com.android.browser"|"com.android.chrome")
run_monkey $2 "-p $3" "--pct-touch 10 --pct-trackball 10 --pct-motion 10 --pct-flip 5 --pct-appswitch 50 --pct-anyevent 5 --pct-pinchzoom 10" "case$1_$3"
wait_time 600
am force-stop $3
;;
*)
run_monkey $2 "-p $3" "--pct-touch 10 --pct-trackball 10 --pct-motion 10 --pct-flip 10 --pct-appswitch 55 --pct-anyevent 5" "case$1_$3"
wait_time 600
am force-stop $3
;;
esac
;;
#more than one package, appswitch 70%
1)
local packages=`echo "$3"|$bb awk -F "|" '{for(i=1;i<NF;i++)printf "-p "$i" ";printf "-p "$NF}'`
run_monkey $2 "$packages" "--pct-touch 5 --pct-trackball 5 --pct-motion 10 --pct-flip 5 --pct-appswitch 70 --pct-anyevent 5" "case$1_appswitch70"
wait_time 600
;;
*)
comment "caselist" "No case" "$1"
;;
esac
}

#main
case_start_time=`$bb awk -F. '{print $1}' /proc/uptime`
case $# in
3)
caselist $2 $1 "$3"
;;
4)
run_monkey $1 "$2" "$3" "$4"
;;
*)
comment "case" "Args are wrong!!!" "$*"
exit
;;
esac
(3)主控逻辑——自定义名称.sh
#!/system/bin/sh

########## 初始设置 ##########

#加载全局变量和函数
source /data/local/tmp/function.sh
#创建ANR/FC/tombstone tag的异常log
c_log 0

########## 完成设置 ##########


########## monkey测试逻辑 ##########

# 执行实例:
# 方式1 执行case.sh已写好的case:$1时长?秒; $2-用例编号;$3-用例参数
# monkey_test 60 0 "com.letv.app.appstore"
# monkey_timeout 60
# 方式2 按参数执行moneky语句:$1-时长; $2-限制范围;$3-事件比例; $4-monkey log文件名
# monkey_test 60 "-p com.letv.games" "--pct-touch 20 --pct-trackball 5 --pct-motion 35 --pct-flip 5 --pct-appswitch 30 --pct-anyevent 5" "letv_games"
# monkey_timeout 60

#测试万象搜索
monkey_test 3600 0 "com.letv.android.quicksearchbox"
##将长按主页键对应操作修改为万象搜索,如果不显示万象搜索则长按唤起
longpress 3 "com.letv.android.quicksearchbox" 3600
#Monkey测试后锁屏10分钟
monkey_timeout 0
##保持am唤起主activity,间隔1S如不显示则唤起,由于“dumpsys activity 包名”获取不到乐搜activity传参
longam "com.letv.lesophoneclient" 3600 "com.letv.lesophoneclient/.ui.MainActivity"
monkey_timeout 0

########## monkey逻辑结束 ##########


########## 测试结束确保子进程已退出 ##########

#回收异常log进程
c_log 1

PID=`/system/bin/ps |grep $$|$bb awk -v pid=$$ '{if($2!=pid)print $2}'`
kill $PID
#通知停止监控
echo "`date +%m-%d" "%H":"%M":"%S` stop monitor scripts." > /data/local/tmp/stop
(4)MCM监控方案脚本优化维护,统一为无root,控制负载取消并发子进程方式,用类型控制是否获取heap
#!/system/bin/sh
if [ -f /data/local/tmp/busybox ];then
export bb="/data/local/tmp/busybox"
else
echo "No /data/local/tmp/busybox"
exit
fi
#参数判断
if [ $# -le 1 ];then
echo "Args:$* is wrong!!!"
exit
elif [ $# -eq 2 ];then
packages="All"
elif [ $# -eq 3 ];then
packages="$3"
fi
if [ -f /data/local/tmp/stop ];then
$bb rm /data/local/tmp/stop
fi

#args:1-PID; 2-command; 3-Loop; 4-command args
getmem_pid(){
if [ -d /proc/$1 ];then
local pss=`dumpsys meminfo $1|$bb awk -v pid=$1 -v comm=$2 -v loop=$3 '{if($1=="Uptime:")a=sprintf("%.3f",$2/1000);if($1=="**")comm=substr($6,2,length($6)-2);if($1=="Native"){n=n+$(NF-2);o=o+$(NF-1);p=p+$NF}else{if($1=="Dalvik"&&NF>6){d=d+$(NF-2);e=e+$(NF-1);f=f+$NF;g=g+$(NF-6)}else{if($1=="TOTAL"){print loop","a","pid","comm","$2+0","n+0","o+0","p+0","d+0","e+0","f+0","g+0}}}}'`
if [ ! -z "$pss" ];then
echo "$pss,\"$4\""
fi
fi
}

get_package(){
local tmp=`dumpsys meminfo -c|$bb grep -E "time,|cat,"`
echo "$tmp"|$bb awk -F, '{if(NR==1){t=sprintf("%.3f",$2/1000)}else{if($1=="cat"){if(r=="")r=$3;else r=r","$3}}}END{print t","r}' >>$testresult/mem2.csv
local grep_str=`echo $packages|$bb sed 's/\./\\\\./g;s/\[/\\\[/g;s/\]/\\\]/g'`
local check=`/system/bin/ps|$bb grep -E "$grep_str"`
if [ ! -z "$check" ];then
echo "$packages"|$bb sed 's/|/\n/g'|while read p;do
echo "$check"|$bb awk -v package="$p" '{if($NF==package){t+=1;print $2" "$NF" "t}}'|while read l;do
local pid=`echo $l|$bb awk '{print $1}'`
if [ -f /proc/$pid/cmdline ];then
local arg=`$bb awk 'BEGIN{r="null"}{if(NR>1){if(NR==2)r=$0;else r=r" "$0}}END{print r}' /proc/$pid/cmdline`
if [ -z `echo $arg|$bb tr -d " "` ];then
local arg="null"
fi
getmem_pid $pid "`echo $l|$bb awk '{print $2}'`" $1 "$arg"
fi
done
done
fi
}

get_meminfo(){
local tmp=`dumpsys meminfo -c|$bb grep -E -v ",grep,|,sh,|,dumpsys,"`
if [ ! -z "$tmp" ];then
local uptime=`echo "$tmp"|$bb awk -F, 'NR==1{printf("%.3f",$2/1000)}'`
echo "$tmp"|$bb awk -v time=$uptime -F, '$1=="cat"{if(r=="")r=$3;else r=r","$3}END{print time","r}' >>$testresult/mem2.csv
local tmp=`echo "$tmp"|$bb grep -E "proc"`
if [ $2 -eq 1 ];then
echo "$tmp"|$bb grep ",native,"|while read l;do
local pid=`echo $l|$bb awk -F, '{print $4}'`
local comm=`echo $l|$bb awk -F, '{print $3}'`
local pss=`echo $l|$bb awk -F, '{print $5}'`
if [ ! -z "$pid" -a ! -z "$comm" -a ! -z "$pss" ];then
if [ -f /proc/$pid/cmdline ];then
local arg=`$bb awk 'BEGIN{r="null"}{if(NR>1){if(NR==2)r=$0;else r=r" "$0}}END{print r}' /proc/$pid/cmdline`
if [ -z `echo $arg|$bb tr -d " "` ];then
local arg="null"
fi
else
local arg="null"
fi
echo "$1,$uptime,$pid,$comm,$pss,,,,,,,,,\"$arg\""
fi
done
local tmp=`echo "$tmp"|$bb grep -v ",native,"|$bb awk -F, '{print $4" "$3}'`
echo "$tmp"|while read l;do
getmem_pid $l $1 "null"
done
elif [ $2 -eq 0 ];then
echo "$tmp"|while read l;do
local pid=`echo $l|$bb awk -F, '{print $4}'`
local comm=`echo $l|$bb awk -F, '{print $3}'`
local pss=`echo $l|$bb awk -F, '{print $5}'`
if [ ! -z "$pid" -a ! -z "$comm" -a ! -z "$pss" ];then
if [ -f /proc/$pid/cmdline ];then
local arg=`$bb awk 'BEGIN{r="null"}{if(NR>1){if(NR==2)r=$0;else r=r" "$0}}END{print r}' /proc/$pid/cmdline`
if [ -z `echo $arg|$bb tr -d " "` ];then
local arg="null"
fi
else
local arg="null"
fi
echo "$1,$uptime,$pid,$comm,$pss,\"$arg\""
fi
done
fi
fi
}

getmem(){
local get_t=`$bb awk '{print $1}' /proc/uptime`
local info=`$bb awk 'BEGIN{r=0}{if($1=="MemFree:"){a=$2};if($1=="Buffers:"){b=$2};if($1=="Cached:"){c=$2};if($1=="Active:"){e=$2};if($1=="Inactive:"){f=$2};if($1=="Active(anon):"){g=$2};if($1=="Inactive(anon):"){h=$2};if($1=="Active(file):"){i=$2};if($1=="Inactive(file):"){j=$2};if($1=="Dirty:"){k=$2};if($1=="Writeback:"){l=$2};if($1=="Mapped:"){m=$2};if($1=="Slab:"){n=$2};if($1=="CMA"&&$2=="Free:"){r=1;a=a-$3;o=$3}}END{if(r==0) print a","b","c","e","f","g","h","i","j","k","l","m","n;else print a","b","c","e","f","g","h","i","j","k","l","m","n","o}' /proc/meminfo`
echo "$get_t,$info" >>$testresult/mem.csv
}

getcpu(){
local get_t=`$bb awk '{print $1}' /proc/uptime`
local activity=`dumpsys window w|$bb grep mFocusedApp|$bb awk '{print $5}'|$bb tr -d ',}'`
local data_t=`date +%Y/%m/%d" "%H:%M:%S`
local tmp=`$bb top -b -n 1|$bb grep -v "busybox"|$bb sed '2s/%//g;s/\\.0 / /g;s/ S N / SN /g;s/ R N / RN /g;s/ D N / DN /g;s/ Z N / ZN /g;s/ T N / TN /g;s/S </S</g;s/D </D</g;s/R </R</g;s/Z </Z</g;s/T </T</g;s/t </t</g;s/[0-9]m[0-9]/m /g;s/}/{/g;s/ th\\]/_th\\]/g;s/\\[mtk /\\[mtk_/g'|$bb awk -v data="$data_t" -v loop=$1 -v time="$get_t" -v act=$activity -v csv="$testresult/cpu.csv" -v csv2="$testresult/check.log" -v cpu=$2 -v T="{" -v T2="\"" '{if(NR==2) print loop","time","T2 act T2","$2","$4","$6","$8","$10","$12","$14","data >>csv;if(NR>4){r="";if($cpu=="0") exit;if($cpu+0==0){if($(cpu-1)/1000>0){a=sprintf("%.0f",$(cpu-1)/1000)}else{a=sprintf("%.1f",$(cpu-1))}c=substr($(cpu-1),length(a)+1);r=$cpu;if(NF>cpu);r=r T$(cpu+1)}else{if($(cpu+1)+0!=0){print $0 >>csv2}else{c=$cpu;r=$(cpu+1)}};if($(cpu+1)+0==0){if(NF>cpu+1){r=r T$(cpu+2);if(NF>cpu+2)r=r T$(cpu+3);if(NF>cpu+3)for(i=(cpu+4);i<=NF;i++)r=r" "$i};print loop","time","$1","c","r}}}'`
echo "$tmp"|$bb awk -F"{" -v S="}" -v T="\"" '{if(NF==1)print $0",,";if(NF==2)print $1","T$2T",";if(NF==3)print $1","T$2" "$3T",";if(NF==4&&$3=="")print $1$4",,"T$2T;if(NF==4&&$3!="")print $1","T$2" "$3S$4T",";if(NF>4&&$3==""){a=$5;if(NF>5)for(i=6;i<=NF;i++)a=a S $i;print $1$4","T a T","T$2T};if(NF>4&&$3!=""){a=$4;if(NF>4)for(i=5;i<=NF;i++)a=a S $i;print $1","T$2" "$3" "a T","}}' >>$testresult/cpuinfo.csv
}

#全局参数
testresult="/data/local/tmp/mcm_result"
if [ -f $testresult/state.txt ];then
pid=`$bb awk -F "," '{print $1}' $testresult/state.txt`
if [ -f /proc/$pid/cmdline ];then
if [ `$bb awk 'NR==1{print $1}' /proc/$pid/cmdline`"a" == "sha" ];then
echo "The $pid is sh command."
exit
fi
fi
fi
if [ -d $testresult ];then
$bb rm -r $testresult
fi
mkdir $testresult

mac=`cat /sys/class/net/*/address|$bb sed -n '1p'|$bb tr -d ':'`
model=`getprop ro.product.model|$bb sed 's/ /_/g'`
build=`getprop ro.build.fingerprint`
if [ -z $build ];then
build=`getprop ro.build.description`
fi

start_time="`date +%Y/%m/%d" "%H:%M:%S`"
start_s=`$bb awk -F. '{print $1}' /proc/uptime`
echo "$$,$1,0/?,$model-$mac,$start_time,$start_s,$start_s,$build,$packages" >$testresult/state.txt
echo "Loop:$1,Time,Activity,usr,sys,nic,idle,io,irq,sirq,Data Time" >$testresult/cpu.csv
echo "Loop:$1,Time,PID,%CPU,Command,args,Thread" >$testresult/cpuinfo.csv
if [ `$bb grep -c "CMA Free" /proc/meminfo` -eq 0 ];then
echo "Time:$1,MemFree,Buffers,Cached,Active,Inactive,Active(anon),Inactive(anon),Active(file),Inactive(file),Dirty,Writeback,Mapped,Slab" >$testresult/mem.csv
else
echo "Time:$1,MemFree,Buffers,Cached,Active,Inactive,Active(anon),Inactive(anon),Active(file),Inactive(file),Dirty,Writeback,Mapped,Slab,CMA Free" >$testresult/mem.csv
fi
echo "Time:$1,"`dumpsys meminfo -c |$bb awk -F, '$1=="cat"{if(NR==1)r=$2;else r=r","$2}END{print r}'|$bb sed 's/ /_/g;s/\.//g'` >$testresult/mem2.csv
if [ $2 -eq 0 -a $# -eq 2 ];then
echo "Loop:$1,Time,PID,Process_Name,Pss,Args" >$testresult/meminfo.csv
else
echo "Loop:$1,Time,PID,Process_Name,Pss,Native_Heap(Size),Native_Heap(Alloc),Native_Heap(Free),Dalvik_Heap(Size),Dalvik_Heap(Alloc),Dalvik_Heap(Free),Dalvik_Pss,Args" >$testresult/meminfo.csv
fi
cpu_p=`$bb top -b -n 1|$bb awk 'NR==4{print NF-1}'`
loop=0
while true;do
start_second=`$bb awk -F. '{print $1}' /proc/uptime`
getcpu $loop $cpu_p
getmem $loop
if [ $# -eq 2 ];then
get_meminfo $loop $2 >>$testresult/meminfo.csv
elif [ $# -eq 3 ];then
get_package $loop >>$testresult/meminfo.csv
fi
end_second=`$bb awk -F. '{print $1}' /proc/uptime`
use_second=$((end_second-start_second))
echo Use second: $use_second
if [ -f /data/local/tmp/stop ];then
echo "Found stop file!!!"
break
elif [ `$bb df /data|$bb awk '{r=substr($(NF-1),1,length($(NF-1))-1)}END{print r+0}'` -ge 90 ];then
echo "The free space of data less 10%,stop!!!"
break
fi
if [ $use_second -lt $1 ];then
sleep $(($1-use_second))
fi
loop=$((loop+1))
end_second=`$bb awk -F. '{print $1}' /proc/uptime`
echo "$$,$1,$loop/?,$model-$mac,$start_time,$start_s,$end_second,$build,$packages" >$testresult/state.txt
done

更新维护

2016/06/08:

MCM更新维护了脚本:
1、由于le全球化CPU内存监控改了双语模板
2、修改了几处数据展示错误

为了全球化解释方便monkey方案起了个名字SCMF(Shell control Monkey Framework):
1、调整了log保存逻辑重构了之前按10秒筛查的逻辑,为了解决报bug时被反馈log不足情况
(1)保存logcat和kmsg按权限判定
(2)按时间戳保存logcat和monkey log
(3)按monkey进程退出保存完整log进行打包压缩,命名按时间段命名monkey/log下
(4)按tag抓ANR。FC,tombstone的log,兼容mtk和高通的不同tag,按传感器名判断型号。用于后续筛查统计异常使用
(5)monkey去除了去除异常继续执行的参数,以便退出后进行截图和当时cpu,内存,进程信息抓取
2、填了些坑,如system_server crash判定,当发生“软重启”只截图停止monkey继续操作,timeout时case.sh的子进程回收。

目前重构电量监控中,此版本没更新

源码(github我这连接太慢,还是捡方便的来,百度云盘)

MCM:(http://pan.baidu.com/s/1i5nnILJ)
monkey压力测试:(http://pan.baidu.com/s/1qYipJkg)
电量监控:(http://pan.baidu.com/s/1nuqPkbn)
筛查ANR/FC/Tombstone:(http://pan.baidu.com/s/1miu9xnq)

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 69 条回复 时间 点赞

shell 看上去真累。你所有的数据都写在手机里,会不会有影响?

...赞...

浮云大大神速

#1楼 @lihuazhang 控制了读写量,log采用筛查方式,连续做个一两天的monkey压力,总体记录的量还可以承受。TV和盒子可以直接写外接u盘里。目前实际使用中30几小时的压力测试没什么问题。

没有仔细看脚本。但是有个问题,monkey的随机测试很多情况下都是无效的操作,有效操作的分布也是不可控的,这个如何来衡量你的压力测试是有效的?

#5楼 @tbya monkey是按事件比例配置的:touch、motion、trackball、syskeys、nav、majornav、appswitch、flip、anyevent、pinchzoom
用事件比例控制测试事件类型

bash代码写的很漂亮. 不过表述的还不太清楚. 别人如何使用没说清楚. 估计其他人没看懂. monkey的无序会带来很多不可控因素.
我最近也在策划写一个appium版本的monkey, 不重压力, 重功能遍历+弱网+数据异常+自定义遍历规则的工具.
用于在新老版本里验证回归

#7楼 @seveniruby 写这篇是说下目前重构了之前写的shell管理monkey压力测试,及重构过程和重构结果。没有侧重交付使用的表达,交付使用是我们内部专项的内容,写的内部PPT交付的手工测试执行组。付的源码中有说明,而且代码中有注释就没细写这部分内容。之前在犹豫是不是要把自己写的内部PPT发出来,是目前两项专项测试项内容。考虑自己写的是内部文档就没放出来。
使用方式就是设计主控逻辑的脚本进行测试,监控都是独立进程写的。脚本是设备端的shell脚本,用途是设备端后台执行,不用长连接PC
两行代表一项测试

# 执行实例:
# 方式1 执行case.sh已写好的case:$1时长?; $2-用例编号;$3-用例参数
# monkey_test 60 0 "com.letv.app.appstore"
# monkey_timeout 60
# 方式2 按参数执行moneky语句:$1-时长; $2-限制范围;$3-事件比例; $4-monkey log文件名
# monkey_test 60 "-p com.letv.games" "--pct-touch 20 --pct-trackball 5 --pct-motion 35 --pct-flip 5 --pct-appswitch 30 --pct-anyevent 5" "letv_games"
# monkey_timeout 60

组件形式APP需要三行

monkey_test 7200 0 "com.letv.lesophoneclient"
##保持am唤起主activity,间隔1S如不显示则唤起
longam "com.letv.lesophoneclient" 7200 "com.letv.lesophoneclient/.ui.MainActivity"
monkey_timeout 600

#7楼 @seveniruby
赞,我们花了近2周才完成遍历算法。深度遍历很有挑战。

#9楼 @tbya 可以分享下遍历算法不?

浮云 #11 · November 27, 2015 作者

#9楼 @tbya 我这边也在想遍历测试这事,因为没完全想好解决方式,还是在现有的随机monkey的方式上进行改善。

我这边测试中心是系统测试为主,monkey的压力测试上既有评估上线版本需求,也有平时压测需求,所以控制了下交付方式,不一定让执行人员十分清楚monkey,知道怎么执行和分析结果就把活干了。

测试评估上按压测总时长内发生异常情况的统计为衡量对象。

#10楼 @lihuazhang
可以的,找个时间整理一下。目前算法还有些恶心的逻辑,正好大家可以帮忙改进下。

@sandman
push进去的busybox能做哪些事情,通用性怎么样?

浮云 #14 · December 01, 2015 作者

#13楼 @walkwall 你在busybox官网下个对应版本busybox push到手机上实际试下不就清楚了。
adb push busybox /data/local/tmp
adb shell chmod 755 /data/local/tmp/busybox

我主要需要用它做字符串处理的一些事情,还有top等不需要权限的命令。

浮云 #15 · December 09, 2015 作者

维护更新了脚本:
1、去root,使用push的busybox,需要无root情况,可以正常执行moneky和input命令
2、root情况也可执行区别在于会保存trace和tombstone文件,否则只能从moneky的log或bugreport中获取
3、bugreport文件较大压缩保存
4、监控负载优化,去除并发进程的获取方式,用类型参数控制是否抓取heap

顶一下

不错,学习了

不错,学习了

#8楼 @sandman 看着报告这么炫,可是不会用啊不会用啊不会用啊。囧囧

浮云 #20 · February 24, 2016 作者

#19楼 @t880216t 这是个monkey执行及配合监控的方案,即可分别独立使用,也可组合使用。
我的应用是:
1、监控是按需集成在各项测试中
2、moneky则是按需拉出专项需求
(1)用户版本系统测试专项探查OOM,ANR,FC,tombstone
(2)APP预装测试,简单评估2小时内moneky测试情况,同步分析监控数据
(3)优化系统log打印,monkey依次分别测试预装重点APP,log打印频率监控tag打印频率

源码和执行批处理脚本都有,执行方式也有,控制monekey逻辑的主脚本也有注释说明,详细参考这些

#20楼 @sandman 感谢大神指点,小弟是个新手,真的很新,请问怎么得到当前应用的".csv"文件呢,我现在只是先手动测试看效果的,只想先把MCM跑起来看看。

浮云 #22 · February 24, 2016 作者

#21楼 @t880216t 见MCM监控中的执行说明

#22楼 @sandman 谢谢浮云牛,看了你说明文档明朗些,明天回去在windows下试试。顺便问下这个MCM监控在mac能用不?

浮云 #24 · February 24, 2016 作者

#23楼 @t880216t 设备端shell脚本+python输出数据脚本+node-webkit框架,都是跨平台的。shell脚本安卓通用,最近维护了版兼容6.0的。还没发出来
(http://pan.baidu.com/s/1eQXSSiI)

#24楼 @sandman MCM跑起来了,继续学习。

#24楼 @sandman 想用你的python输出数据脚本生成HTML_MCM.zip的,但运行目录里的CSVtoJson.py报错,难道这个文件不是你上一贴说的那output.py?

浮云 #27 · February 26, 2016 作者

#26楼 @t880216t 我有写说明使用py脚本需要和模板MCM_HTML文件夹同目录。
使用exe就不用,我已经把模板打包进exe了。
报错信息多明显,没找到MCM_HTML无法拷贝模板

#27楼 @sandman 我的目录结构是这样的。
直接运行还是会报错:WindowsError:[Error 3]:'/MCM_HTML/.',应该是Widnows下获取路径有问题。我把CSVtoJson.py中的获取路径修改了下就好用了。

#copyFiles('%s/MCM_HTML'%os.path.dirname(sys.argv[0]), '%s/MCM_HTML'%csvPath)
copyFiles('./MCM_HTML','%s/MCM_HTML'%csvPath)
浮云 #29 · February 29, 2016 作者

#28楼 @t880216t 奇怪,从没在这出过找不到文件夹。我写的方式是脚本根目录下的MCM_HTML,避免执行目录不是脚本目录找不到

感觉好高深那,学习学习,谢谢楼主分享

monkey测试的思路学习了,还有一些常用的命令很有用。。就是脚本看的有点头疼啊!

浮云 #32 · June 08, 2016 作者

MCM更新维护了脚本:
1、由于le全球化CPU内存监控改了双语模板
2、修改了几处数据展示错误

为了全球化解释方便monkey方案起了个名字SCMF(Shell control Monkey Framework):
1、调整了log保存逻辑重构了之前按10秒筛查的逻辑,为了解决报bug时被反馈log不足情况
(1)保存logcat和kmsg按权限判定
(2)按时间戳保存logcat和monkey log
(3)按monkey进程退出保存完整log进行打包压缩,命名按时间段命名monkey/log下
(4)按tag抓ANR。FC,tombstone的log,兼容mtk和高通的不同tag,按传感器名判断型号。用于后续筛查统计异常使用
(5)monkey去除了去除异常继续执行的参数,以便退出后进行截图和当时cpu,内存,进程信息抓取
2、填了些坑,如system_server crash判定,当发生“软重启”只截图停止monkey继续操作,timeout时case.sh的子进程回收。

目前重构电量监控中,此版本没更新

附件中,貌似没有筛查批处理程序。不知是不是我下在少了。

我运行内存监控后,
点击CSVtoJson.exe,然后就一闪而过。

浮云 #35 · June 12, 2016 作者

#33楼 @an168ge 筛查ANR/FC/Tombstone:(http://pan.baidu.com/s/1miu9xnq)

浮云 #36 · June 12, 2016 作者

#34楼 @an168ge 看说明,这是生成结果图的exe。需要将测试结果拖拽到此exe上释放,这是个命令行工具。

#36楼 @sandman
但我生成的不是zip文件,是文件夹
这个是我哪里操作错了。

浮云 #38 · June 13, 2016 作者

#37楼 @an168ge 原始结果有异常,导致不能生成结果。具体得看执行报的什么错,cmd下执行看下报错信息。
CSVtojson.exe 结果文件夹完整路径。
再有你在什么设备上测试的,安卓版本是?

#38楼 @sandman 回复机型Oppo A31,系统4.4.4,运行倒是没有看到明显的报错,手机ROOT,就push busybox,然后运行Run_MCM_CN.bat,运行结束后,把结果pull出来,然后拉到csvtojason.exe结果就是是没有生成zip文件。

#38楼 @sandman 是不是我增加了包名,
造成出现了问题。你的帮助文档不是要增加报名,进行监控

#38楼 @sandman 另外 我对发给我的筛查ANR/FATAL,试验了下,对于log文件有出现fatal错误的,无法筛选出来。

浮云 #42 · June 14, 2016 作者

#40楼 @an168ge 包名加错地方了,一般不是专项没必要加包名。

包名需要加在 &前

浮云 #43 · June 14, 2016 作者

#41楼 @an168ge 筛的的是logcat -v time格式的,如果是 threadtime格式,需要改grep的关键字。

#43楼 @sandman 恩,好的,这个我解决,谢谢

#42楼 @sandman 我只要对某一个进程进行监控,不需要全部。所以我做了专项。如果不做专项,就是要通过数据筛选或者一直在一个应用里面进行操作。我目前对你写的了解不很透,还在实践中。总之感谢啊

#42楼 @sandman 弱弱的问下,能否把你内训操作文档发一份让我学习下,如果可以的话,我邮箱:an168ge@163.com.仅个人学习,不会公开的。谢谢。

#43楼 @sandman 大神,我遇到一个问题,就是关于你写的CAFT(Checking ANR FC tombstone)V3.0,我发现有出现一个log是关于crash的monkey日志是帅选不出来的,我自己在check.sh,增加了crash筛选一直出现问题,不知道要修改怎么合适。不知道是否有QQ可以沟通联系。求指教

@sandman 关于monkey固定在具体模块内执行测试这块 能麻烦你具体讲下吗? 真的非常感谢 这个问题困扰我好长时间了 目前还没找到比较合适的解决方法

浮云 #49 · June 27, 2016 作者

#48楼 @fanfan 固定模块测试依靠固定用例的压力测试更靠谱,monkey测试本身是随机的,不过可以通过调整事件比例,控制activity跳转,使大部分测试时间都在指定页面下操作。控制页面这部分就是靠子进程判定超范围则切换回。

浮云 #50 · June 27, 2016 作者

#49楼 @sandman TesterHome的QQ群可以找到我

#15楼 @sandman
维护更新了脚本:
1、去root,使用push的busybox,需要无root情况,可以正常执行moneky和input命令

不需要root也能调用Monkey么?push busybox本身也得root的吧?

浮云 #52 · July 14, 2016 作者

#51楼 @vangin 除非系统版本管的严,一般无root可以monkey测试。busybox是放到/data/local/tmp下chmod 755赋权后使用。

浮云 [Topic was deleted] 中提及了此贴 10 Aug 23:45
浮云 [Topic was deleted] 中提及了此贴 10 Aug 23:45

可以提供下内训文档吗?个人学习不进行公开。非常感谢!yat_ho@163.com

赞一个

浮云 shell 管理 monkey 压力测试 中提及了此贴 06 Dec 13:24

小米工程师 目前负责性能方面工作 方便加微信交流下不 shaoxy1992 我们有自己性能优化交流群 里面有tx sf hy等性能负责人。

浮云 android 端取 cpu,fps,men,wifi/gprs 流量等值 中提及了此贴 28 Jul 11:23

这个还在维护吗?

浮云 #64 · December 21, 2017 作者
Leon 回复

内部有维护,现在是按case分组自动统计的方式进行测试,CI部署测试,整体逻辑上有调整,就是还没整理分享。
统计页

单case监控数据

浮云 回复

我再哪里方便,查看最新code

浮云 #66 · December 21, 2017 作者
Leon 回复

新的内部使用没分享呢,具体的case也只是适配的内部项目,再有就是没在管手机业务的基础体验测试后,手机的脚本一直也没维护,主要维护的TV的。外部分享得改不少内容,犯懒有时间没写分享了。

@sandman hi, 请教一下,我手动执行了一下 $bb top -b -n 1|$bb grep -v "busybox"|$bb sed '2s/%//g;s/\.0 / /g;s/ S N / SN /g;s/ R N / RN /g;s/ D N / DN /g;s/ Z N / ZN /g;s/ T N / TN /g;s/S </S</g;s/D </D</g;s/R </R</g;s/Z </Z</g;s/T </T</g;s/t </t</g;s/[0-9]m[0-9]/m /g;s/}/{/g;s/ th\]/th\]/g;s/\[mtk /\[mtk/g' 提示了正则表达式不对,这个正则表达式的目的是什么呢?
我手动格式了一下,红框部分的判断是忽略的是吗?

还有最后我处理出来的cpuinfo.csv文件PID是不同的是吗?
求大神指教~

浮云 #68 · August 18, 2018 作者
小王子 回复

busybox的top不同版本cpu所在的列不是固定的,为了适应这个,提前判定了下cpu在第几列。还有就是输出的格式有很多特殊情况会多出空格导致列顺序不对,主要是为了容错这些特殊情况。比如mtk有些底层进程的进程名是[mtk th]之类的,具体名字忘了。

不过目前这套方案早被我迭代了,现在在做一套更灵活的方案,把监控、shell脚本、uiautomatorcase,命令行方法统一到一个框架模式中来设计管理,shell负责执行过程的统一控制管理,具体的case全变成csv+配参维护。目标是测试开发维护公共方法,执行人员按需配参。执行维护的人无需懂代码,只需了解配参意义。测试开发维护公共方法函数的实现。随着公共方法需求的收敛,解放出测试开发的精力做更进一步的方案设计。

浮云 回复

@sandman 真赞!
我理解是数据处理还是原来的shell,只是用统一的框架把原来需要人工介入比较多的通过框架处理出来了是吗?
比如我执行这个正则出错,没有适配到我这个手机输出格式是吗?

浮云 #70 · August 19, 2018 作者
小王子 回复

正则错误是你需要注意一点,命令行和脚本中需要的转译符数量不太一样,放到``执行符中需要多加一个转译符\,而命令行直接执行就需要把多加的转译符去掉,要不就会报错。

新作的框架流程是,优势结合的目的:
1、shell擅长设备端离线后台执行的管理
2、busybox扩展了shell脚本的能力
3、shell可以管理所有命令行能执行的方法
4、PC端对结果的二次处理与分析统计更有优势

所以:
1、由shell设计统一的设备端后台执行脚本,解析外部的csv配置完成不同的测试需求
2、shell脚本的监控方案可以按需配合测试执行不同的监控需求,cpu、内存、帧率、电量、电压等等
3、既可以由shell写用例方法函数,也可以用uiautomator写方法,所有的调用都放在csv中配置维护
4、固定结果存储目录和文件结构,测试完成取出后交由PC端进行统一整理输出html报告,并可结合highcharts做监控图(shell端有结果信息的预处理,都变成csv数据形式)

浮云 回复

嗯,学习了~
cpu信息的处理你的思路是通过当前的Activity来拿到当前应用的CPU利用率是吗? 我好像没有看到有过滤处理的地方喔?
我看到结果,好像是会把 系统的一些也统计进来

8,27011.04,829,2.1,system_server,,
38,27011.04,268,2.1,/system/bin/surfaceflinger,,

这些其他进程的数据和当前的app是有关联的是吗?

浮云 #72 · August 21, 2018 作者
小王子 回复

反正top一次性展示全了,干脆把cpu占用率大于0的全保存了,当然busybox的除外。

浮云 回复

请教一下CI部署的思路,shell命令是怎么融入CI的流程的?是USB连PC?stf ?

浮云 #74 · October 11, 2018 作者
小王子 回复

我设计的脚本方案,思路上是脱机执行的,jenkins(搭建在ubuntu)用bash写shell脚本连接设备,至于是usb还是通过网络adb看具体需求。设备端起后台脚本-》PC端周期判定是否执行完成(后台脚本是否退出)-》等待完成后pull结果并生成测试报告-》按需邮件发送

浮云 回复

PC端周期判断,是jenkins任务吧?
你们在锤子话,应该是不需要兼顾iOS?😀

浮云 #76 · October 15, 2018 作者
小王子 回复

PC端是jenkins任务,这事在之前乐视时就开始做了,没app在IOS上的单发目前没测ios

81—1 移动应用持续集成平台设计思路 中提及了此贴 02 Feb 11:32
浮云 Monkey 测试中,对外放声音的处理方法? 中提及了此贴 10 Jul 15:23
浮云 android 端监控方案分享 中提及了此贴 13 Aug 01:16
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up