-
MonkeyRunner.java
2012-03-19 15:05:42
路径:android-2.2-froyo/com/android/monkeyrunner/MonkeyRunner.java
/** * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.monkeyrunner; import com.android.ddmlib.AndroidDebugBridge; import com.android.ddmlib.IDevice; import com.android.ddmlib.Log; import com.android.ddmlib.NullOutputReceiver; import com.android.ddmlib.RawImage; import com.android.ddmlib.Log.ILogOutput; import com.android.ddmlib.Log.LogLevel; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; /*** * MonkeyRunner is a host side application to control a monkey instance on a * device. MonkeyRunner provides some useful helper functions to control the * device as well as various other methods to help script. tests. */ public class MonkeyRunner { static String monkeyServer = "127.0.0.1"; static int monkeyPort = 1080; static Socket monkeySocket = null; static IDevice monkeyDevice; static BufferedReader monkeyReader; static BufferedWriter monkeyWriter; static String monkeyResponse; static MonkeyRecorder monkeyRecorder; static String scriptName = null; // Obtain a suitable logger. private static Logger logger = Logger.getLogger("com.android.monkeyrunner"); // delay between key events final static int KEY_INPUT_DELAY = 1000; // version of monkey runner final static String monkeyRunnerVersion = "0.4"; // TODO: interface cmd; class xml tags; fix logger; test class/script. public static void main(String[] args) throws IOException { // haven't figure out how to get below INFO...bad parent. Pass -v INFO to turn on logging logger.setLevel(Level.parse("WARNING")); processOptions(args); logger.info("initAdb"); initAdbConnection(); logger.info("openMonkeyConnection"); openMonkeyConnection(); logger.info("start_script"); start_script(); logger.info("ScriptRunner.run"); ScriptRunner.run(scriptName); logger.info("end_script"); end_script(); logger.info("closeMonkeyConnection"); closeMonkeyConnection(); } /*** * Initialize an adb session with a device connected to the host * */ public static void initAdbConnection() { String adbLocation = "adb"; boolean device = false; boolean emulator = false; String serial = null; AndroidDebugBridge.init(false /** debugger support */); try { AndroidDebugBridge bridge = AndroidDebugBridge.createBridge( adbLocation, true /** forceNewBridge */); // we can't just ask for the device list right away, as the internal thread getting // them from ADB may not be done getting the first list. // Since we don't really want getDevices() to be blocking, we wait here manually. int count = 0; while (bridge.hasInitialDeviceList() == false) { try { Thread.sleep(100); count++; } catch (InterruptedException e) { // pass } // let's not wait > 10 sec. if (count > 100) { System.err.println("Timeout getting device list!"); return; } } // now get the devices IDevice[] devices = bridge.getDevices(); if (devices.length == 0) { printAndExit("No devices found!", true /** terminate */); } monkeyDevice = null; if (emulator || device) { for (IDevice d : devices) { // this test works because emulator and device can't both be true at the same // time. if (d.isEmulator() == emulator) { // if we already found a valid target, we print an error and return. if (monkeyDevice != null) { if (emulator) { printAndExit("Error: more than one emulator launched!", true /** terminate */); } else { printAndExit("Error: more than one device connected!",true /** terminate */); } } monkeyDevice = d; } } } else if (serial != null) { for (IDevice d : devices) { if (serial.equals(d.getSerialNumber())) { monkeyDevice = d; break; } } } else { if (devices.length > 1) { printAndExit("Error: more than one emulator or device available!", true /** terminate */); } monkeyDevice = devices[0]; } monkeyDevice.createForward(monkeyPort, monkeyPort); String command = "monkey --port " + monkeyPort; monkeyDevice.executeShellCommand(command, new NullOutputReceiver()); } catch(IOException e) { e.printStackTrace(); } } /*** * Open a tcp session over adb with the device to communicate monkey commands */ public static void openMonkeyConnection() { try { InetAddress addr = InetAddress.getByName(monkeyServer); monkeySocket = new Socket(addr, monkeyPort); monkeyWriter = new BufferedWriter(new OutputStreamWriter(monkeySocket.getOutputStream())); monkeyReader = new BufferedReader(new InputStreamReader(monkeySocket.getInputStream())); } catch (UnknownHostException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } /*** * Close tcp session with the monkey on the device * */ public static void closeMonkeyConnection() { try { monkeyReader.close(); monkeyWriter.close(); monkeySocket.close(); AndroidDebugBridge.terminate(); } catch(IOException e) { e.printStackTrace(); } } /*** * This is a house cleaning routine to run before starting a script. Puts * the device in a known state and starts recording interesting info. */ public static void start_script() throws IOException { press("menu", false); press("menu", false); press("home", false); // Start recording the script. output, might want md5 signature of file for completeness monkeyRecorder = new MonkeyRecorder(scriptName, monkeyRunnerVersion); // Record what device we are running on addDeviceVars(); monkeyRecorder.addComment("Script. commands"); } /*** * This is a house cleaning routine to run after finishing a script. * Puts the monkey server in a known state and closes the recording. */ public static void end_script() throws IOException { String command = "done"; sendMonkeyEvent(command, false, false); // Stop the recording and zip up the results monkeyRecorder.close(); } /*** This is a method for scripts to launch an activity on the device * * @param name The name of the activity to launch */ public static void launch_activity(String name) throws IOException { System.out.println("Launching: " + name); recordCommand("Launching: " + name); monkeyDevice.executeShellCommand("am start -a android.intent.action.MAIN -n " + name, new NullOutputReceiver()); // void return, so no response given, just close the command element in the xml file. monkeyRecorder.endCommand(); } /*** * Grabs the current state of the screen stores it as a png * * @param tag filename or tag descriptor of the screenshot */ public static void grabscreen(String tag) throws IOException { tag += ".png"; try { Thread.sleep(1000); getDeviceImage(monkeyDevice, tag, false); } catch (InterruptedException e) { } } /*** * Sleeper method for script. to call * * @param msec msecs to sleep for */ public static void sleep(int msec) throws IOException { try { recordCommand("sleep: " + msec); Thread.sleep(msec); recordResponse("OK"); } catch (InterruptedException e) { e.printStackTrace(); } } /*** * Tap function for scripts to call at a particular x and y location * * @param x x-coordinate * @param y y-coordinate */ public static boolean tap(int x, int y) throws IOException { String command = "tap " + x + " " + y; boolean result = sendMonkeyEvent(command); return result; } /*** * Press function for scripts to call on a particular button or key * * @param key key to press */ public static boolean press(String key) throws IOException { return press(key, true); } /*** * Press function for scripts to call on a particular button or key * * @param key key to press * @param print whether to send output to user */ private static boolean press(String key, boolean print) throws IOException { String command = "press " + key; boolean result = sendMonkeyEvent(command, print, true); return result; } /*** * dpad down function */ public static boolean down() throws IOException { return press("dpad_down"); } /*** * dpad up function */ public static boolean up() throws IOException { return press("dpad_up"); } /*** * Function to type text on the device * * @param text text to type */ public static boolean type(String text) throws IOException { boolean result = false; // text might have line ends, which signal new monkey command, so we have to eat and reissue String[] lines = text.split("[\\r\\n]+"); for (String line: lines) { result = sendMonkeyEvent("type " + line + "\n"); } // return last result. Should never fail..? return result; } /*** * Function to get a static variable from the device * * @param name name of static variable to get */ public static boolean getvar(String name) throws IOException { return sendMonkeyEvent("getvar " + name + "\n"); } /*** * Function to get the list of static variables from the device */ public static boolean listvar() throws IOException { return sendMonkeyEvent("listvar \n"); } /*** * This function is the communication bridge between the host and the device. * It sends monkey events and waits for responses over the adb tcp socket. * This version if for all scripted events so that they get recorded and reported to user. * * @param command the monkey command to send to the device */ private static boolean sendMonkeyEvent(String command) throws IOException { return sendMonkeyEvent(command, true, true); } /*** * This function allows the communication bridge between the host and the device * to be invisible to the script. for internal needs. * It splits a command into monkey events and waits for responses for each over an adb tcp socket. * Returns on an error, else continues and sets up last response. * * @param command the monkey command to send to the device * @param print whether to print out the responses to the user * @param record whether to put the command in the xml file that stores test outputs */ private static boolean sendMonkeyEvent(String command, Boolean print, Boolean record) throws IOException { command = command.trim(); if (print) System.out.println("MonkeyCommand: " + command); if (record) recordCommand(command); logger.info("Monkey Command: " + command + "."); // send a single command and get the response monkeyWriter.write(command + "\n"); monkeyWriter.flush(); monkeyResponse = monkeyReader.readLine(); if(monkeyResponse != null) { // if a command returns with a response if (print) System.out.println("MonkeyServer: " + monkeyResponse); if (record) recordResponse(monkeyResponse); logger.info("Monkey Response: " + monkeyResponse + "."); // return on error if (monkeyResponse.startsWith("ERROR")) return false; // return on ok if(monkeyResponse.startsWith("OK")) return true; // return on something else? return false; } // didn't get a response... if (print) System.out.println("MonkeyServer: ??no response"); if (record) recordResponse("??no response"); logger.info("Monkey Response: ??no response."); //return on no response return false; } /*** * Record the command in the xml file * * @param command the command sent to the monkey server */ private static void recordCommand(String command) throws IOException { if (monkeyRecorder != null) { // don't record setup junk monkeyRecorder.startCommand(); monkeyRecorder.addInput(command); } } /*** * Record the response in the xml file * * @param response the response sent by the monkey server */ private static void recordResponse(String response) throws IOException { recordResponse(response, ""); } /*** * Record the response and the filename in the xml file, store the file (to be zipped up later) * * @param response the response sent by the monkey server * @param filename the filename of a file to be time stamped, recorded in the xml file and stored */ private static void recordResponse(String response, String filename) throws IOException { if (monkeyRecorder != null) { // don't record setup junk monkeyRecorder.addResult(response, filename); // ignores file if filename empty monkeyRecorder.endCommand(); } } /*** * Add the device variables to the xml file in monkeyRecorder. * The results get added as device_var tags in the script_run tag */ private static void addDeviceVars() throws IOException { monkeyRecorder.addComment("Device specific variables"); sendMonkeyEvent("listvar \n", false, false); if (monkeyResponse.startsWith("OK:")) { // peel off "OK:" string and get the individual var names String[] varNames = monkeyResponse.substring(3).split("\\s+"); // grab all the individual var values for (String name: varNames) { sendMonkeyEvent("getvar " + name, false, false); if(monkeyResponse != null) { if (monkeyResponse.startsWith("OK") ) { if (monkeyResponse.length() > 2) { monkeyRecorder.addDeviceVar(name, monkeyResponse.substring(3)); } else { // only got OK - good variable but no value monkeyRecorder.addDeviceVar(name, "null"); } } else { // error returned - couldn't get var value for name... include error return monkeyRecorder.addDeviceVar(name, monkeyResponse); } } else { // no monkeyResponse - bad variable with no value monkeyRecorder.addDeviceVar(name, "null"); } } } else { // it's an error, can't find variable names... monkeyRecorder.addAttribute("listvar", monkeyResponse); } } /*** * Process the command-line options * * @return Returns true if options were parsed with no apparent errors. */ private static void processOptions(String[] args) { // parse command line parameters. int index = 0; do { String argument = args[index++]; if ("-s".equals(argument)) { if(index == args.length) { printUsageAndQuit("Missing Server after -s"); } monkeyServer = args[index++]; } else if ("-p".equals(argument)) { // quick check on the next argument. if (index == args.length) { printUsageAndQuit("Missing Server port after -p"); } monkeyPort = Integer.parseInt(args[index++]); } else if ("-v".equals(argument)) { // quick check on the next argument. if (index == args.length) { printUsageAndQuit("Missing Log Level after -v"); } Level level = Level.parse(args[index++]); logger.setLevel(level); level = logger.getLevel(); System.out.println("Log level set to: " + level + "(" + level.intValue() + ")."); System.out.println("Warning: Log levels below INFO(800) not working currently... parent issues"); } else if (argument.startsWith("-")) { // we have an unrecognized argument. printUsageAndQuit("Unrecognized argument: " + argument + "."); monkeyPort = Integer.parseInt(args[index++]); } else { // get the filepath of the script. to run. This will be the last undashed argument. scriptName = argument; } } while (index < args.length); } /** * Grab an image from an ADB-connected device. */ private static void getDeviceImage(IDevice device, String filepath, boolean landscape) throws IOException { RawImage rawImage; recordCommand("grabscreen"); System.out.println("Grabbing Screeshot: " + filepath + "."); try { rawImage = device.getScreenshot(); } catch (IOException ioe) { recordResponse("No frame. buffer", ""); printAndExit("Unable to get frame. buffer: " + ioe.getMessage(), true /** terminate */); return; } // device/adb not available? if (rawImage == null) { recordResponse("No image", ""); return; } assert rawImage.bpp == 16; BufferedImage image; logger.info("Raw Image - height: " + rawImage.height + ", width: " + rawImage.width); if (landscape) { // convert raw data to an Image image = new BufferedImage(rawImage.height, rawImage.width, BufferedImage.TYPE_INT_ARGB); byte[] buffer = rawImage.data; int index = 0; for (int y = 0 ; y < rawImage.height ; y++) { for (int x = 0 ; x < rawImage.width ; x++) { int value = buffer[index++] & 0x00FF; value |= (buffer[index++] << 8) & 0x0FF00; int r = ((value >> 11) & 0x01F) << 3; int g = ((value >> 5) & 0x03F) << 2; int b = ((value >> 0) & 0x01F) << 3; value = 0xFF << 24 | r << 16 | g << 8 | b; image.setRGB(y, rawImage.width - x - 1, value); } } } else { // convert raw data to an Image image = new BufferedImage(rawImage.width, rawImage.height, BufferedImage.TYPE_INT_ARGB); byte[] buffer = rawImage.data; int index = 0; for (int y = 0 ; y < rawImage.height ; y++) { for (int x = 0 ; x < rawImage.width ; x++) { int value = buffer[index++] & 0x00FF; value |= (buffer[index++] << 8) & 0x0FF00; int r = ((value >> 11) & 0x01F) << 3; int g = ((value >> 5) & 0x03F) << 2; int b = ((value >> 0) & 0x01F) << 3; value = 0xFF << 24 | r << 16 | g << 8 | b; image.setRGB(x, y, value); } } } if (!ImageIO.write(image, "png", new File(filepath))) { recordResponse("No png writer", ""); throw new IOException("Failed to find png writer"); } recordResponse("OK", filepath); } private static void printUsageAndQuit(String message) { // 80 cols marker: 01234567890123456789012345678901234567890123456789012345678901234567890123456789 System.out.println(message); System.out.println("Usage: monkeyrunner [options] SCRIPT_FILE"); System.out.println(""); System.out.println(" -s MonkeyServer IP Address."); System.out.println(" -p MonkeyServer TCP Port."); System.out.println(" -v MonkeyServer Logging level (ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF)"); System.out.println(""); System.out.println(""); System.exit(1); } private static void printAndExit(String message, boolean terminate) { System.out.println(message); if (terminate) { AndroidDebugBridge.terminate(); } System.exit(1); } }
-
ScriptRunner.java
2012-03-19 15:05:42
路径:android-2.2-froyo/com/android/monkeyrunner/ScriptRunner.java
package com.android.monkeyrunner; import org.python.core.Py; import org.python.core.PyObject; import org.python.util.PythonInterpreter; import org.python.util.InteractiveConsole; import java.io.File; import java.io.IOException; import java.io.FileInputStream; import java.lang.RuntimeException; import java.util.Properties; /*** * Runs Jython based scripts. */ public class ScriptRunner { /*** The "this" scope object for scripts. */ private final Object scope; private final String variable; /*** Private constructor. */ private ScriptRunner(Object scope, String variable) { this.scope = scope; this.variable = variable; } /*** Creates a new instance for the given scope object. */ public static ScriptRunner newInstance(Object scope, String variable) { return new ScriptRunner(scope, variable); } /*** * Runs the specified Jython script. First runs the initialization script. to * preload the appropriate client library version. */ public static void run(String scriptfilename) { try { initPython(); PythonInterpreter python = new PythonInterpreter(); python.execfile(scriptfilename); } catch(Exception e) { e.printStackTrace(); } } /*** Initialize the python interpreter. */ private static void initPython() { Properties props = new Properties(); // Default is 'message' which displays sys-package-mgr bloat // Choose one of error,warning,message,comment,debug props.setProperty("python.verbose", "error"); props.setProperty("python.path", System.getProperty("java.class.path")); PythonInterpreter.initialize(System.getProperties(), props, new String[] {""}); } /*** * Create and run a console using a new python interpreter for the test * associated with this instance. */ public void console() throws IOException { initPython(); InteractiveConsole python = new InteractiveConsole(); initInterpreter(python, scope, variable); python.interact(); } /*** * Start an interactive python interpreter using the specified set of local * variables. Use this to interrupt a running test script. with a prompt: * * @param locals */ public static void console(PyObject locals) { initPython(); InteractiveConsole python = new InteractiveConsole(locals); python.interact(); } /*** * Initialize a python interpreter. * * @param python * @param scope * @throws IOException */ public static void initInterpreter(PythonInterpreter python, Object scope, String variable) throws IOException { // Store the current test case as the this variable python.set(variable, scope); } }
-
MonkeyRecorder.java源码
2012-03-19 15:01:48
路径:android-2.2-froyo/com/android/monkeyrunner/MonkeyRecorder.java
/** * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.monkeyrunner; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.List; import java.util.ArrayList; import java.util.Calendar; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.jheer.XMLWriter; /*** * MonkeyRecorder is a host side class that records the output of scripts that are run. * It creates a unique directory, puts in an xml file that records each cmd and result. * It stores every screenshot in this directory. * When finished, it zips this all up. * * Calling Sequence: * mr = new MonkeyRecorder(scriptName); * mr.startCommand(); * [mr.addAttribute(name, value);] * ... * [mr.addInput(cmd);] * [mr.addResults(result, filename);] // filename = "" if no screenshot * mr.endCommand(); * mr.addComment(comment); * mr.startCommand(); * ... * mr.endCommand(); * ... * mr.close(); * * With MonkeyRunner this should output an xml file, <script_name>-yyyyMMdd-HH:mm:ss.xml, into the * directory out/<script_name>-yyyyMMdd-HH:mm:ss with the contents like: * * <?xml version="1.0" encoding='UTF-8'?> * <!-- Monkey Script. Results --> * <script_run script_name="filename" monkeyRunnerVersion="0.2"> * <!-- Device specific variables --> * <device_var var_name="name" var_value="value" /> * <device_var name="build.display" value="opal-userdebug 1.6 DRC79 14207 test-keys"/> * ... * <!-- Script. commands --> * <command> * dateTime="20090921-17:08:43" * <input cmd="Pressing: menu"/> * <response result="OK" dateTime="20090921-17:08:43"/> * </command> * ... * <command> * dateTime="20090921-17:09:44" * <input cmd="grabscreen"/> * <response result="OK" dateTime="20090921-17:09:45" screenshot="home_screen-20090921-17:09:45.png"/> * </command> * ... * </script_run> * * And then zip it up with all the screenshots in the file: <script_name>-yyyyMMdd-HH:mm:ss.zip. */ public class MonkeyRecorder { // xml file to store output results in private static String mXmlFilename; private static FileWriter mXmlFile; private static XMLWriter mXmlWriter; // unique subdirectory to put results in (screenshots and xml file) private static String mDirname; private static List<String> mScreenShotNames = new ArrayList<String>(); // where we store all the results for all the script. runs private static final String ROOT_DIR = "out"; // for getting the date and time in now() private static final SimpleDateFormat SIMPLE_DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMdd-HH:mm:ss"); /*** * Create a new MonkeyRecorder that records commands and zips up screenshots for submittal * * @param scriptName filepath of the monkey script. we are running */ public MonkeyRecorder(String scriptName, String version) throws IOException { // Create directory structure to store xml file, images and zips File scriptFile = new File(scriptName); scriptName = scriptFile.getName(); // Get rid of path mDirname = ROOT_DIR + "/" + stripType(scriptName) + "-" + now(); new File(mDirname).mkdirs(); // Initialize xml file mXmlFilename = stampFilename(stripType(scriptName) + ".xml"); initXmlFile(scriptName, version); } // Get the current date and time in a simple string format (used for timestamping filenames) private static String now() { return SIMPLE_DATE_TIME_FORMAT.format(Calendar.getInstance().getTime()); } /*** * Initialize the xml file writer * * @param scriptName filename (not path) of the monkey script, stored as attribute in the xml file * @param version of the monkey runner test system */ private static void initXmlFile(String scriptName, String version) throws IOException { String[] names = new String[] { "script_name", "monkeyRunnerVersion" }; String[] values = new String[] { scriptName, version }; mXmlFile = new FileWriter(mDirname + "/" + mXmlFilename); mXmlWriter = new XMLWriter(mXmlFile); mXmlWriter.begin(); mXmlWriter.comment("Monkey Script. Results"); mXmlWriter.start("script_run", names, values, names.length); } /*** * Add a comment to the xml file. * * @param comment comment to add to the xml file */ public static void addComment(String comment) throws IOException { mXmlWriter.comment(comment); } /*** * Begin writing a command xml element */ public static void startCommand() throws IOException { mXmlWriter.start("command", "dateTime", now()); } /*** * Write a command name attribute in a command xml element. * It's add as a sinlge script. command could be multiple monkey commands. * * @param cmd command sent to the monkey */ public static void addInput(String cmd) throws IOException { String name = "cmd"; String value = cmd; mXmlWriter.tag("input", name, value); } /*** * Write a response xml element in a command. * Attributes include the monkey result, datetime, and possibly screenshot filename * * @param result response of the monkey to the command * @param filename filename of the screen shot (or other file to be included) */ public static void addResult(String result, String filename) throws IOException { int num_args = 2; String[] names = new String[3]; String[] values = new String[3]; names[0] = "result"; values[0] = result; names[1] = "dateTime"; values[1] = now(); if (filename.length() != 0) { names[2] = "screenshot"; values[2] = stampFilename(filename); addScreenShot(filename); num_args = 3; } mXmlWriter.tag("response", names, values, num_args); } /*** * Add an attribut to an open xml element. name="escaped_value" * * @param name name of the attribute * @param value value of the attribute */ public static void addAttribute(String name, String value) throws IOException { mXmlWriter.addAttribute(name, value); } /*** * Add an xml device variable element. name="escaped_value" * * @param name name of the variable * @param value value of the variable */ public static void addDeviceVar(String name, String value) throws IOException { String[] names = {"name", "value"}; String[] values = {name, value}; mXmlWriter.tag("device_var", names, values, names.length); } /*** * Move the screenshot to storage and remember you did it so it can be zipped up later. * * @param filename file name of the screenshot to be stored (Not path name) */ private static void addScreenShot(String filename) { File file = new File(filename); String screenShotName = stampFilename(filename); file.renameTo(new File(mDirname, screenShotName)); mScreenShotNames.add(screenShotName); } /*** * Finish writing a command xml element */ public static void endCommand() throws IOException { mXmlWriter.end(); } /*** * Add datetime in front of filetype (the stuff after and including the last infamous '.') * * @param filename path of file to be stamped */ private static String stampFilename(String filename) { // int typeIndex = filename.lastIndexOf('.'); if (typeIndex == -1) { return filename + "-" + now(); } return filename.substring(0, typeIndex) + "-" + now() + filename.substring(typeIndex); } /*** * Strip out the file type (the stuff after and including the last infamous '.') * * @param filename path of file to be stripped of type information */ private static String stripType(String filename) { // int typeIndex = filename.lastIndexOf('.'); if (typeIndex == -1) return filename; return filename.substring(0, typeIndex); } /*** * Close the monkeyRecorder by closing the xml file and zipping it up with the screenshots. * * @param filename path of file to be stripped of type information */ public static void close() throws IOException { // zip up xml file and screenshots into ROOT_DIR. byte[] buf = new byte[1024]; String zipFileName = mXmlFilename + ".zip"; endCommand(); mXmlFile.close(); FileOutputStream zipFile = new FileOutputStream(ROOT_DIR + "/" + zipFileName); ZipOutputStream ut = new ZipOutputStream(zipFile); // add the xml file addFileToZip(out, mDirname + "/" + mXmlFilename, buf); // Add the screenshots for (String filename : mScreenShotNames) { addFileToZip(out, mDirname + "/" + filename, buf); } out.close(); } /*** * Helper function to zip up a file into an open zip archive. * * @param zip the stream of the zip archive * @param filepath the filepath of the file to be added to the zip archive * @param buf storage place to stage reads of file before zipping */ private static void addFileToZip(ZipOutputStream zip, String filepath, byte[] buf) throws IOException { FileInputStream in = new FileInputStream(filepath); zip.putNextEntry(new ZipEntry(filepath)); int len; while ((len = in.read(buf)) > 0) { zip.write(buf, 0, len); } zip.closeEntry(); in.close(); } }
-
monkeyrunner脚本生成器
2012-01-11 10:02:54
monkeyrunner脚本生成器 -
monkeyrunner测试apk包安装卸载
2011-04-21 18:54:51
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
device = MonkeyRunner.waitForConnection()
#device.removePackage ('ApiDemos.apk')
device.removePackage ('com.example.android.notepad')
print ('卸载成功')
MonkeyRunner.sleep(15)
device.installPackage('ApiDemos.apk')
print ('安装成功') -
了解monkey命令行的一些参数
2011-04-21 18:47:34
1.-p:所在测试的包,可以是一个也可以是多个(如:monkey -p com.androd.a -p com.androd.b)
2.-c:如果用此参数指定了一个或几个类别,Monkey将只允许系统启动被这些类别中的某个类别列出的Activity。如果不指定任何类别,Monkey将选择下列类别中列出的Activity: Intent.CATEGORY_LAUNCHER或Intent.CATEGORY_MONKEY。要指定多个类别,需要使用多个-c选项,每个-c选项只能用于一个类别.
3.-ignore-crash:当应用程序崩溃或发生任何失控异常时,Monkey将停止运行。如果设置此选项,Monkey将继续向系统发送事件,直到计数完成.
4.-ignore-timeouts:通常,当应用程序发生任何超时错误(如“Application Not Responding”对话框)时,Monkey将停止运行。如果设置此选项,Monkey将继续向系统发送事件,直到计数完成.
5.-ignore-security-exceptions:通常,当应用程序发生许可错误(如启动一个需要某些许可的Activity)时,Monkey将停止运行。如果设置了此选项,Monkey将继续向系统发送事件,直到计数完成
6.-monitor-native-crashes:监视并报告Android系统中本地代码的崩溃事件。如果设置了–kill-process-after-error,系统将停止运行
7.-kill-process-after-error:如果程序出现错误,monkey将结束此程序进程
8.-hprof:设置此项,将在monkey事件序列之前和之后立即生成profilling报告。这将会在data/misc中生成大文件(约5mb)所以要小心使用它
9.-pct-touch:调整触摸事件的百分比(触摸事件是一个down-up事件,它发生在屏幕的某单一位置)
10.-pct-motion:动作事件的百分比(动作事件由屏幕上某处的一个down事件、一系列的随机事件和一个up事件组成)
11.-pct-trackball:调整轨迹事件的百分比(轨迹事件由一个或几个随机移动组成,有时还伴随着点击)
12.-pct-syskeys:调整系统按键事件的百分比(这些按键通常被保留,由系统使用,如home,back,start call,end call及音量控制)
13.-pct-nav 调整基本导航事件的百分比(导航事件来自方向输入设备的up/down/left/right组成)
14.-pct-majornav:调整“主要”导航事件的百分比(这些导航事件通常引发图形界面中的动作,如:5-way键盘的中间按键、回退按键、菜单按键)
15.-pct-appswitch:调整启动Activity的百分比。在随机间隔里,Monkey将执行一个startActivity()调用,作为最大程度覆盖包中全部Activity的一种方法
16.-pct-anyevent:调整启动Activity的百分比。它包罗了所有其它的事件类型,如:按键,其它不常用的设备按钮
17.–wait-dbg:停止执行中的Monkey,直到有调试器和它相连接
18.–dbg-no-events:设置此选项,Monkey将执行初始启动,进入到一个测试Activity,然后不会再进一步生成事件。为了得到最佳结果,把它与-v、一个或几个包约束、以及一个保持Monkey运行30秒或更长时间的非零值联合起来,从而提供一个环境,可以监视应用程序所调用的包之间的转换
19.-port:为monkey开启专用端口。此时只monkey不会帮你乱点击,而此时你自己就是一只monkey了,在你乱点的时候,monkey会输出你点击后回馈的信息。如果你打完命令之后模拟器上没有启动你所要启动的包,你需要自己启动,但是你只能启动你-p中指定的那几个包。ctrl+c中断
20.--throttle :当事件起效时等待的毫秒数
21.-s:随机数生成器的seed值。如果用相同的seed值再次运行monkey,它将生成相同的事件序列
22.COUNT:要发送的事件数
-
android的monkey测试小结
2011-04-21 17:39:29
Monkey测试是Android自动化测试的一种手段,Monkey测试本身非常简单,就是模拟用户的按键输入,触摸屏输入,手势输入等,看设备多长时间会出异常。
当Monkey程序在模拟器或设备运行的时候,如果用户出发了比如点击,触摸,手势或一些系统级别的事件的时候,它就会产生随机脉冲,所以可以用Monkey用随机重复的方法去做相关的性能测试。
命令:$ adb shell monkey -v -p your.package.name 500
例如:monkey -v -p com.android.camera --throttle 5000 --pct-anyevent 100 500
-v显示默认程度的信息
-p com.android.camera是指定测试的程序(这是开始测试的camera的内容)
--throttle 5000 设定延时
--pct-anyevent 100(设定启动activity的百分比为100%)
500设定的事件数
(具体可以看monkey的命令帮助)
以下是个例子: monkey -p com.example.android.notepad -v -v -v 10
运行结果相关解释如下:
各种事件所占的比例
// Event percentages:
// 0: 15.0%
// 1: 10.0%
// 2: 15.0%
// 3: 25.0%
// 4: 15.0%
// 5: 2.0%
// 6: 2.0%
// 7: 1.0%
// 8: 15.0%表示跳转到com.example.android.notepad里面的NotesList这一个Activity里
:Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.categ
ory.LAUNCHER;launchFlags=0x10000000;component=com.example.android.notepad/.Notes
List;end允许此Intent跳转
Allowing start of Intent { act=android.intent.action.MAIN cat=[android.in
tent.category.LAUNCHER] cmp=com.example.android.notepad/.NotesList } in package
com.example.android.notepad发送的一些动作:
Sleeping for 0 milliseconds
:SendKey (ACTION_DOWN): 21 // KEYCODE_DPAD_LEFT
:SendKey (ACTION_UP): 21 // KEYCODE_DPAD_LEFT
Sleeping for 0 milliseconds
:Sending Pointer ACTION_MOVE x=-4.0 y=2.0
:Sending Pointer ACTION_MOVE x=-5.0 y=-4.0
:Sending Pointer ACTION_MOVE x=0.0 y=-1.0
:Sending Pointer ACTION_MOVE x=-3.0 y=2.0
:Sending Pointer ACTION_MOVE x=-4.0 y=2.0
:Sending Pointer ACTION_MOVE x=-2.0 y=4.0
:Sending Pointer ACTION_MOVE x=4.0 y=1.0
Events injected: 10丢弃的,键=0,指针=0,轨迹球=0,翻转=0
:Dropped: keys=0 pointers=0 trackballs=0 flips=0
网络统计经过时间为7249ms,其中7249ms是用于在手机上的,0ms用于无线网络上,没有连接的时间为0ms
## Network stats: elapsed time=7249ms (7249ms mobile, 0ms wifi, 0ms not connecte
d)结束// Monkey finished
标题搜索
我的存档
数据统计
- 访问量: 28426
- 日志数: 37
- 图片数: 2
- 建立时间: 2007-08-15
- 更新时间: 2017-06-03