微信号:grzlwx

介绍:光荣之路官方资讯

【Android测试】Monkey之源码浅谈

2015-11-03 22:24 carter_d

吴老的《selenium webdriver 实战宝典》出版了!

相关阅读:

【Android测试】Monkey(一)

【Android测试】Monkey(二)

前言


  根据上一篇我们学会了Monkey的用法,知道了Monkey可以非常容易的模拟伪随机的模拟事件。也许有的时候我们想让他稍微智能化一些,例如只在某个屏幕范围产生伪随机事件,或者说是只对某些指定Activity进行操作,这样就需要我们对Monkey进行改良了。而改良必须去改Monkey的源码,因此本节课们就简单的说说Monkey的源码。

  源码下载地址:https://code.google.com/p/android-source-browsing/source/browse/cmds/monkey/src/com/android/commands/monkey/?repo=platform--development&name=android-cts-4.2_r2 ( 这里只是Monkey的源码,如果要编译Monkey需要下载Android的源码 )

概述


  如果你真的打算改造一个属于你的Monkey,那么过程必须要做的是:

  1、下载Android源码

  2、阅读Monkey源码如果需要修改代码

  3、代码编译

  4、运行Monkey

  本节内容主要针对第二部分的 “阅读Monkey源码”,其他的1、3、4 部分会在另外一篇“只允许注册用户访问的”的番外篇里进行介绍,因为这部分有些内容不是本人原创,因此对博客进行了加密处理,以免侵犯到源作者的权利,如需交流这部分内容,请留言给我。

Monkey源码


Monkey的入口在 Monkey.java中:

/**
* Command-line entry point.
*
* @param args The command-line arguments
*/
public static void main(String[] args) {
// Set the process name showing in "ps" or "top"
Process.setArgV0("com.android.commands.monkey");

int resultCode = (new Monkey()).run(args);
System.exit(resultCode);
}

  第一句的意思就是在 shell 命令行下 使用 ps | grep com.**.monkey 就找到正在运行的monkey进程

  第二句是后续的内容,我们继续看后续干了什么。

/**
* Run the command!
*
* @param args The command-line arguments
* @return Returns a posix-style result code. 0 for no error.
*/
private int run(String[] args) {
// Super-early debugger wait
for (String s : args) {
if ("--wait-dbg".equals(s)) {
Debug.waitForDebugger();
}
}

// Default values for some command-line options
mVerbose = 0;
mCount = 1000;
mSeed = 0;
mThrottle = 0;

// prepare for command-line processing
mArgs = args;
mNextArg = 0;

// set a positive value, indicating none of the factors is provided yet
for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
mFactors[i] = 1.0f;
}

if (!processOptions()) {
return -1;
}

if (!loadPackageLists()) {
return -1;
}

// now set up additional data in preparation for launch
if (mMainCategories.size() == 0) {
mMainCategories.add(Intent.CATEGORY_LAUNCHER);
mMainCategories.add(Intent.CATEGORY_MONKEY);
}

if (mVerbose > 0) {
System.out.println(":Monkey: seed=" + mSeed + " count=" + mCount);
if (mValidPackages.size() > 0) {
Iterator<String> it = mValidPackages.iterator();
while (it.hasNext()) {
System.out.println(":AllowPackage: " + it.next());
}
}
if (mInvalidPackages.size() > 0) {
Iterator<String> it = mInvalidPackages.iterator();
while (it.hasNext()) {
System.out.println(":DisallowPackage: " + it.next());
}
}
if (mMainCategories.size() != 0) {
Iterator<String> it = mMainCategories.iterator();
while (it.hasNext()) {
System.out.println(":IncludeCategory: " + it.next());
}
}
}

if (!checkInternalConfiguration()) {
return -2;
}

if (!getSystemInterfaces()) {
return -3;
}

if (!getMainApps()) {
return -4;
}

mRandom = new SecureRandom();
mRandom.setSeed((mSeed == 0) ? -1 : mSeed);

if (mScriptFileNames != null && mScriptFileNames.size() == 1) {
// script mode, ignore other options
mEventSource = new MonkeySourceScript(mRandom, mScriptFileNames.get(0), mThrottle,
mRandomizeThrottle, mProfileWaitTime, mDeviceSleepTime);
mEventSource.setVerbose(mVerbose);

mCountEvents = false;
} else if (mScriptFileNames != null && mScriptFileNames.size() > 1) {
if (mSetupFileName != null) {
mEventSource = new MonkeySourceRandomScript(mSetupFileName,
mScriptFileNames, mThrottle, mRandomizeThrottle, mRandom,
mProfileWaitTime, mDeviceSleepTime, mRandomizeScript);
mCount++;
} else {
mEventSource = new MonkeySourceRandomScript(mScriptFileNames,
mThrottle, mRandomizeThrottle, mRandom,
mProfileWaitTime, mDeviceSleepTime, mRandomizeScript);
}
mEventSource.setVerbose(mVerbose);
mCountEvents = false;
} else if (mServerPort != -1) {
try {
mEventSource = new MonkeySourceNetwork(mServerPort);
} catch (IOException e) {
System.out.println("Error binding to network socket.");
return -5;
}
mCount = Integer.MAX_VALUE;
} else {
// random source by default
if (mVerbose >= 2) { // check seeding performance
System.out.println("// Seeded: " + mSeed);
}
mEventSource = new MonkeySourceRandom(mRandom, mMainApps, mThrottle, mRandomizeThrottle);
mEventSource.setVerbose(mVerbose);
// set any of the factors that has been set
for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
if (mFactors[i] <= 0.0f) {
((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]);
}
}

// in random mode, we start with a random activity
((MonkeySourceRandom) mEventSource).generateActivity();
}

// validate source generator
if (!mEventSource.validate()) {
return -5;
}

// If we're profiling, do it immediately before/after the main monkey
// loop
if (mGenerateHprof) {
signalPersistentProcesses();
}

mNetworkMonitor.start();
int crashedAtCycle = runMonkeyCycles();
mNetworkMonitor.stop();

synchronized (this) {
if (mRequestAnrTraces) {
reportAnrTraces();
mRequestAnrTraces = false;
}
if (mRequestAnrBugreport){
System.out.println("Print the anr report");
getBugreport("anr_" + mReportProcessName + "_");
mRequestAnrBugreport = false;
}
if (mRequestAppCrashBugreport){
getBugreport("app_crash" + mReportProcessName + "_");
mRequestAppCrashBugreport = false;
}
if (mRequestDumpsysMemInfo) {
reportDumpsysMemInfo();
mRequestDumpsysMemInfo = false;
}
if (mRequestPeriodicBugreport){
getBugreport("Bugreport_");
mRequestPeriodicBugreport = false;
}
}

if (mGenerateHprof) {
signalPersistentProcesses();
if (mVerbose > 0) {
System.out.println("// Generated profiling reports in /data/misc");
}
}

try {
mAm.setActivityController(null);
mNetworkMonitor.unregister(mAm);
} catch (RemoteException e) {
// just in case this was latent (after mCount cycles), make sure
// we report it
if (crashedAtCycle >= mCount) {
crashedAtCycle = mCount - 1;
}
}

// report dropped event stats
if (mVerbose > 0) {
System.out.print(":Dropped: keys=");
System.out.print(mDroppedKeyEvents);
System.out.print(" pointers=");
System.out.print(mDroppedPointerEvents);
System.out.print(" trackballs=");
System.out.print(mDroppedTrackballEvents);
System.out.print(" flips=");
System.out.println(mDroppedFlipEvents);
}

// report network stats
mNetworkMonitor.dump();

if (crashedAtCycle < mCount - 1) {
System.err.println("** System appears to have crashed at event " + crashedAtCycle
+ " of " + mCount + " using seed " + mSeed);
return crashedAtCycle;
} else {
if (mVerbose > 0) {
System.out.println("// Monkey finished");
}
return 0;
}
}
run

 看似代码很多事实上,Monkey主要分为3大块:

  1、总体控制模块,主要完成各种选项设置,Crash,ANR监控,禁止不允许的package运行,输出各种系统数据;

  2、Event模块,以MonkeyEvent为基类,衍生出各种Event类,如常见的点击,输入,滑动事件;

  3、Source模块,以MonkeyEventSource为接口,衍生出三种Source类:MonkeySourceRandom类 (随机生成事件)、MonkeySourceScript(从脚本获取事件)、MonkeySourceNetwork(从网络获取事件)。

(作者:carter_dream 来源:http://www.cnblogs.com/by-dream/p/4713466.html)


 
            
 
            
 
            
 
           
 
           
 
           
 
           
 
           
 
           
 
           
 
           
 
           
 
           

感谢作者,传播测试知识、技能与正能量!
分享测试生活,思考测试人生!欢迎来稿735821166@qq.com

光荣之路软件测试培训

官网:http://www.gloryroad.cn/

微信公众号:gloryroadtrain

性能测试QQ群:415987441
软件测试招聘QQ群: 203715128
自动化3群QQ: 371211499

 
光荣之路 更多文章 今天晚上的 linux 公开课- Awk 编程 7月28日(今天)晚上的 linux 公开课- shell编程 8月4日(今天)晚上的 linux 公开课- shell编程 9月1日(本周一)晚8点半,光荣之路Web自动化系列基础课—javascript第二讲 推荐本好书《与机器赛跑》
猜您喜欢 苹果最刁钻的33个面试题,有种就来挑战! Rails4 Stong parameters使用经验 惹毛程序员的十件事!需求变更居然不是排第一! 【详解python】pip的安装 2015:开源已经完胜,但这并不是结束