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

浮云 · 2015年11月25日 · 最后由 浮云 回复于 2024年06月27日 · 11349 次阅读
本帖已被设为精华帖!
在遇到 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 的子进程回收。

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

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

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

...赞...

浮云大大神速

浮云 #82 · 2015年11月26日 Author

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

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

浮云 #80 · 2015年11月26日 Author

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

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

浮云 #78 · 2015年11月26日 Author

#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 可以分享下遍历算法不?

浮云 #75 · 2015年11月27日 Author

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

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

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

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

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

浮云 #72 · 2015年12月01日 Author

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

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

浮云 #71 · 2015年12月09日 Author

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

顶一下

不错,学习了

不错,学习了

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

浮云 #66 · 2016年02月24日 Author

#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 跑起来看看。

浮云 #64 · 2016年02月24日 Author

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

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

浮云 #62 · 2016年02月24日 Author

#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?

浮云 #59 · 2016年02月26日 Author

#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)
浮云 #57 · 2016年02月29日 Author

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

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

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

浮云 #51 · 2016年06月08日 Author

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,然后就一闪而过。

浮云 #51 · 2016年06月12日 Author

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

浮云 #36 · 2016年06月12日 Author

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

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

浮云 #48 · 2016年06月13日 Author

#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 错误的,无法筛选出来。

浮云 #44 · 2016年06月14日 Author

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

包名需要加在 &前

浮云 #43 · 2016年06月14日 Author

#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 固定在具体模块内执行测试这块 能麻烦你具体讲下吗? 真的非常感谢 这个问题困扰我好长时间了 目前还没找到比较合适的解决方法

浮云 #37 · 2016年06月27日 Author

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

浮云 #36 · 2016年06月27日 Author

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

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

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

浮云 #34 · 2016年07月14日 Author

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

浮云 [该话题已被删除] 中提及了此贴 08月10日 23:45
浮云 [该话题已被删除] 中提及了此贴 08月10日 23:45

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

赞一个

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

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

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

这个还在维护吗?

浮云 #22 · 2017年12月21日 Author
Leon 回复

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

单 case 监控数据

浮云 回复

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

浮云 #20 · 2017年12月21日 Author
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 是不同的是吗?
求大神指教~

浮云 #18 · 2018年08月18日 Author
小王子 回复

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

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

浮云 回复

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

浮云 #16 · 2018年08月19日 Author
小王子 回复

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

新作的框架流程是,优势结合的目的:
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 是有关联的是吗?

浮云 #14 · 2018年08月21日 Author
小王子 回复

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

浮云 回复

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

浮云 #12 · 2018年10月11日 Author
小王子 回复

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

浮云 回复

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

浮云 #10 · 2018年10月15日 Author
小王子 回复

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

81—1 移动应用持续集成平台设计思路 中提及了此贴 02月02日 11:32
浮云 Monkey 测试中,对外放声音的处理方法? 中提及了此贴 07月10日 15:23
浮云 android 端监控方案分享 中提及了此贴 08月13日 01:16

@sandman hi 楼主介意再分享一下百度网盘资源吗,上面的已经过期了,觉得楼主写得特别好,想借鉴一下,可以吗

大佬,网盘失效了。麻烦重新给个链接吧。多谢了。

哪位大佬能分享下源码呀,感谢

tester1.0 回复

很早写的了,安卓都过了这么多版本,看这个https://testerhome.com/topics/20187
本来是早期,用设备端 shell 脚本 + 数据存 csv + PC 端后处理报告的方式做了很多事;当然现在也在用此方式搞了些脱机方案,或预处理数据传给 PC 再加工的方案,只是一些方案提了专利,不方便分享

shell + busybox + 定制依赖 app + shell 下命令行安卓自带/后 push 赋权命令,能干很多事,文本预处理提取、统计、计算用 awk,数据表存储用 csv 或 tab 分割的 xls 格式,PC 端后处理用 pandas + highcharts/echarts 出数据报告。

像性能数据采集分析;log 指定 tag 实时提取分析,异常实时 PC 端预警;设备端 shell 和 app 交互,脱机执行自动化 case 压测,半自动交互测试等

特点就是可以脱机省设备,拔了数据线一样能跑,awk 预处理格式化数据流通过 adb 命令行提取后做实时图形化交互展示之类的,也可以做成设备端脚本 + 上位机效果方案;手机硬件堆料这么多,占部分用于测试很合理吧。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册