1,main方法
Monkeyrunner指令的入口是MonkeyRunnerStart的main方法,
public static void main(String[] args) {
MonkeyRunnerOptions options = MonkeyRunnerOptions.processOptions(args);
if (options == null) {
return;
}
replaceAllLogFormatters(MonkeyFormatter.DEFAULT_INSTANCE, options.getLogLevel());
MonkeyRunnerStarter runner = new MonkeyRunnerStarter(options);
int error = runner.run();
System.exit(error);
}
run方法首先設定預設參數
1,解析指令行參數
2,構造MonkeyRunnerStarter對象
3,進行測試
1.1 processOptions
processOptions主要解析輸入指令。
public static MonkeyRunnerOptions processOptions(String[] args)
{
int index = 0;
String hostname = DEFAULT_MONKEY_SERVER_ADDRESS;
File scriptFile = null;
int port = DEFAULT_MONKEY_PORT;
String backend = "adb";
Level logLevel = Level.SEVERE;
ImmutableList.Builder<File> pluginListBuilder = ImmutableList.builder();
ImmutableList.Builder<String> argumentBuilder = ImmutableList.builder();
while (index < args.length)
{
String argument = args[(index++)];
if ("-s".equals(argument))
{
if (index == args.length)
{
printUsage("Missing Server after -s");
return null;
}
hostname = args[(index++)];
}
•••
和monkey解析指令類似,在此就不論述了。
1.2 構造方法
MonkeyRunnerStarter的構造方法如下
public MonkeyRunnerStarter(MonkeyRunnerOptions options)
{
Map<String, String> chimp_options = new TreeMap();
chimp_options.put("backend", options.getBackendName());
this.options = options;
this.chimp = ChimpChat.getInstance(chimp_options);
MonkeyRunner.setChimpChat(this.chimp);
}
在該構造方法中,會擷取ChimpChat 對象,然後指派給chimp變量,其主要作用在後面論述。
1.3 run
run方法代碼如下,
private int run()
{
String monkeyRunnerPath = System.getProperty("com.android.monkeyrunner.bindir") + File.separator + "monkeyrunner";
Map<String, Predicate<PythonInterpreter>> plugins = handlePlugins();
if (this.options.getScriptFile() == null)
{
ScriptRunner.console(monkeyRunnerPath);
this.chimp.shutdown();
return 0;
}
int error = ScriptRunner.run(monkeyRunnerPath, this.options.getScriptFile().getAbsolutePath(), this.options.getArguments(), plugins);
this.chimp.shutdown();
return error;
}
根據測試解析的測試指令,分為2種情況,
1, 如果使用者在指令行運作monkeyrunner時沒有提供腳本檔案路徑這個參數,
那麼就調用ScriptRunner類的console來請求jython解析器打開一個互動視窗來讓使用者進行互動.
2, 如果使用者在指令行運作monkeyrunner時提供了腳本路徑這個參數,
那麼調用的将會是ScriptRunner的run方法來将該腳本運作起來,其實裡面最終調用的就是jython的解析器來運作腳本。
實際上,無論是打開互動console還是直接運作腳本,最終用到的都是jython解析器,并且互動console和運作腳本實質完全一樣。
如果是運作腳本,調用ScriptRunner的run方法,其方法如下,
public static int run(String executablePath, String scriptfilename, Collection<String> args, Map<String, Predicate<PythonInterpreter>> plugins)
{
File f = new File(scriptfilename);
Collection<String> classpath = Lists.newArrayList(new String[] { f.getParent() });
classpath.addAll(plugins.keySet());
String[] argv = new String[args.size() + 1];
argv[0] = f.getAbsolutePath();
int x = 1;
for (String arg : args) {
argv[(x++)] = arg;
}
initPython(executablePath, classpath, argv);
PythonInterpreter python = new PythonInterpreter();
for (Map.Entry<String, Predicate<PythonInterpreter>> entry : plugins.entrySet())
{
boolean success;
try
{
success = ((Predicate)entry.getValue()).apply(python);
}
catch (Exception e)
{
LOG.log(Level.SEVERE, "Plugin Main through an exception.", e);
}
continue;
if (!success) {
LOG.severe("Plugin Main returned error for: " + (String)entry.getKey());
}
}
python.set("__name__", "__main__");
python.set("__file__", scriptfilename);
try
{
python.execfile(scriptfilename);
}
catch (PyException e)
{
if (Py.SystemExit.equals(e.type)) {
return ((Integer)e.value.__tojava__(Integer.class)).intValue();
}
LOG.log(Level.SEVERE, "Script terminated due to an exception", e);
return 1;
}
return 0;
}
該方法執行個體化一個jython的解析器,PythonInterpreter所在的包是“org.Python.util”。
獲得jython解析器後就直接調用解析器的execfile方法去執行目标測試腳本。
運作測試腳本流程才走完萬裡長征第一步,還有一些其他的準備工作,測試腳本架構的調用還遠着呢。