测试基础 [分享] 自动化测试与持续集成方案--Android crash 收集

snake · May 08, 2015 · Last by 测试小书童 replied at September 03, 2016 · 5073 hits
本帖已被设为精华帖!

之前看到有人在论坛里面问monkey的执行,我决定不按照前言中的顺序写了,大家可以各取所需。本篇文章与Monkey有关,但又不局限于此。我曾经尝试用Monkey来做crash的收集。

  1. Monkey的执行
  2. Log的分析
  3. Crash的采集
  4. 思考和讨论

Monkey的执行


当我刚开始接触移动互联网的时候,到处找关于Monkey的文档看,每篇文章都说Monkey很简单,就一条命令,然后就是对各种参数的说明。
后面等我实践的时候,发现用好Monkey不是件容易的事情。如果仅仅是执行这条命令,当然很容易。一般情况下,跑Monkey的同时,获取其Logcat。对Logcat的日志进行分析能发现很多问题。
请看我的实现:

#encoding:utf-8
import os
import time
import re

###############################################################
######### Monkey测试 #########
######### 作者:Anderson 糖果 #########
######### 版本 V1.0.1 #########
######### 时间:2015.04.25 #########
################################################################

packageName="com.XXXX.app"
logdir=r"d:\jenkins"
remote_path=r"\\10.21.101.100\build\android"

os.system('adb shell cat /system/build.prop >D:\jenkins\phone.text')

f = r"D:\jenkins\phone.text"

def getcmd(cmd):
f = open(cmd,"r")
lines = f.readlines()
for line in lines:

line=line.split('=')
if (line[0]=='ro.build.version.release'):
version = line[1]
if (line[0]=='ro.product.model'):
model = line[1]
if (line[0]=='ro.product.brand'):
brand = line[1]
return version,model,brand


version,model,brand=getcmd(f)

print version,model,brand
os.remove(f)

#print "使用Logcat清空Phone中log"
os.popen("adb logcat -c")

#print"暂停2秒..."
print "wait"
time.sleep(2)

now1 = time.strftime('%Y-%m-%d-%H_%M_%S', time.localtime(time.time()))

#print"开始执行Monkey命令"
monkeylogname=logdir+"\\"+now1+"monkey.log"
print monkeylogname
cmd="adb shell monkey -p com.XXXX -s 500 --ignore-timeouts --monitor-native-crashes -v -v 10000 >>%s" %(monkeylogname)
os.popen(cmd)

#print"手机截屏"
os.popen("adb shell screencap -p /sdcard/monkey_run.png")

#print"拷贝截屏图片至电脑"
cmd1="adb pull /sdcard/monkey_run.png %s" %(logdir)
os.popen(cmd1)
print "gai ming"
oldname=logdir+"\\"+r"monkey_run.png"
if (os.path.exists(oldname)):
print "file is exist"
else:
print "file isn't exist"
newname=logdir+"\\"+now1+r"monkey.png"
os.rename(oldname, newname)

#print"使用Logcat导出日志"

logcatname=logdir+"\\"+now1+r"logcat.log"
cmd2="adb logcat -d >%s" %(logcatname)
os.popen(cmd2)

#print"导出traces文件"

tracesname=logdir+"\\"+now1+r"traces.log"
cmd3="adb shell cat /data/anr/traces.txt>%s" %(tracesname)
os.popen(cmd3)

Log的分析


当时在网上找文档时,都是说在Monkey的log里面找“FC”,“ANR”。我另劈蹊径,对Logcat日志进行解析。

######################
#获取error
######################

NullPointer="java.lang.NullPointerException"
IllegalState="java.lang.IllegalStateException"
IllegalArgument="java.lang.IllegalArgumentException"
ArrayIndexOutOfBounds="java.lang.ArrayIndexOutOfBoundsException"
RuntimeException="java.lang.RuntimeException"
SecurityException="java.lang.SecurityException"

def geterror():
f = open(logcatname,"r")
lines = f.readlines()
errfile="%s\error.log" %(remote_path)
if (os.path.exists(errfile)):
os.remove(errfile)
fr = open(errfile,"a")
fr.write(version)
fr.write("\n")
fr.write(model)
fr.write("\n")
fr.write(brand)
fr.write("\n")
fr.write(now1)
fr.write("\n")

count=0
for line in lines:
if ( re.findall(NullPointer,line) or re.findall(IllegalState,line) or re.findall(IllegalArgument,line) or re.findall(ArrayIndexOutOfBounds,line) or re.findall(RuntimeException,line) or re.findall(SecurityException,line) ):
a=lines.index(line)
count +=1
for var in range(a,a+22):
print lines[var]
fr.write(lines[var])
fr.write("\n")
f.close()
fr.close()
return count


number=geterror()
print number

看到的结果是这样子的:

所有的crash都在这个log里面展现,一目了然,而且放到了共享目录,开发可以直接访问。其实这里面还统计了出现闪退的次数,为了统计次数,没有去重。(这个脚本还是写得比较粗糙,但是能达到要求了,有兴趣的可以在上面继续优化。)

Crash的采集


这种方式是能采集到一些闪退,但这远远不够。因为客户那边出现闪退,你是没有现场的。有没有一种方法来监控这些闪退。不管是测试这边还是客户那边,只要有crash,就会向服务器发请求,将crash的具体信息记录在数据库里面。
例如:

后面有跟这个系统的作者有交流,他是重写了线程监控UncaughtExceptionHandler。他说可以把接口开放给我,我目前还没开始研究。等有了结果,再来分享。

思考和讨论


  1. IOS上的crash 如何监控?
  2. 跑Monkey时,如何屏幕解锁?有登录咋办? 在登录以后跑,它退出了咋办?
  3. 跑Monkey时,怎么避免它将wifi或网络关掉?
  4. 开发如何面对这些你捕获的crash log? (我们的开发有一大堆理由说看不懂,解不了)
  5. 有没有更好的crash捕获机制?你们是如何做的?

PS: 最近想挪窝,base上海,求收留。可以联系恒温和在群里找糖果

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 28 条回复 时间 点赞
snake #1 · May 08, 2015 作者

现在精神不济,写得自己都不知道在说什么,将就着看吧。

#1楼 @snake 挪窝的事情,不要反复说啊。。。

提个建议,为了更好的阅读,英文单词前后加空格。其他人也注意。关于 monkey, 这个还远远不够。跑 monkey,需要监控太多数据了。

snake #4 · May 08, 2015 作者

真早。

哈哈。好思考~呆喔回上海来回帖。。。赶火车去了~赞文章~

厉害

IOS上的crash 如何监控?
跑Monkey时,如何屏幕解锁?有登录咋办? 在登录以后跑,它退出了咋办?
跑Monkey时,怎么避免它将wifi或网络关掉?
开发如何面对这些你捕获的crash log? (我们的开发有一大堆理由说看不懂,解不了)
有没有更好的crash捕获机制?你们是如何做的?

  1. ios 的 crash, 论坛里有文章了。
  2. 跑 Monkey 时,如何屏幕解锁?有登录咋办? 在登录以后跑,它退出了咋办? —— monkey 做不了逻辑的东西,这个和 monkey 违背。
  3. 跑Monkey时,怎么避免它将wifi或网络关掉? 所以我们用 串口 跑 monkey 或者把 com.android.settings 加入黑名单
  4. 开发如何面对这些你捕获的crash log? (我们的开发有一大堆理由说看不懂,解不了) —— 太弱,无解
  5. 有,裁剪自己的 log 系统。然后使用 elk 来做日志分析。

#7楼 @lihuazhang
串口是什么?
解锁和appium一样做个unlock.apk

#8楼 @sanlengjingvv 串口,rx tx gnd

@snake 在你该系列第一篇文章,把后面的文章的链接全部更新进去,做成一个合集

最近在做iOS的Monkey 目前已实现真机monkey 轨迹记录+截图+iPhone系统日志收集+crash日志收集,我是参考的github上的CrashMonkey和ui-auto-monkey自己改造了一些,现在除了那个app拉后台怎样重新拉起的问题其它都解决,等完整方案出来会开帖子。

#11楼 @vigossjjj 等你的帖子等了好久好久了。。

#11楼 @vigossjjj
期待你的ios monkey分析系统啊

snake #15 · May 11, 2015 作者

@vigossjjj 不错,做了我想做而没做到的事情,大大的赞。

楼主,请问一下代码中的:
for var in range(a,a+22):
这个22是怎么来的?

snake #17 · May 11, 2015 作者

@shixue33 : 哦,是剪烛妹子啊。 这个22是表示从找到某个出错的信息开始,打印log22行,这个数据你可以根据自己的需要改。基本上22行能把所有的出错有关的log展现出来了。

#16楼 @shixue33 为何叫剪烛妹子?

#17楼 @snake 搜嘎!

#18楼 @weamylady =。= 因为叫剪烛啊,然后是妹子啊

#20楼 @shixue33 (o)/~名字不错哦!我还以为你叫史雪之类的~ ~

有什么办法在APP ,crash时自动截屏

snake #23 · May 25, 2015 作者

@idoit007 一般crash 时 截屏无助于问题的定位和解决,抓log比较靠谱一点。

如果是UI自动化测试跑脚本期间遇到的crash 楼主有什么好点的处理方案?

snake #25 · May 29, 2015 作者

@jennyhui 这个需要开发帮忙或者开发配合, 在apk 中加代码来监听 UncaughtExceptionHandler ,将闪退发到服务器或者邮件发出来,这样就不论你啥时候有闪退,都能抓到。本来想做一套这个工具的,结果现在论坛那个入住的企业早已经做出来。

@snake 请问这个是什么语言的脚本啊?python perl?

@Snake,还在考虑机会么?杭州的机会考不考虑?

赞。。。。

测试小书童 [Topic was deleted] 中提及了此贴 03 Sep 11:26
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up