118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/* 218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Copyright (C) 2012 The Android Open Source Project 318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * you may not use this file except in compliance with the License. 618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * You may obtain a copy of the License at 718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 1018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Unless required by applicable law or agreed to in writing, software 1118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 1218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * See the License for the specific language governing permissions and 1418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * limitations under the License. 1518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 1618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 1718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupackage com.android.uiautomator.testrunner; 1818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 1918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.app.Activity; 2018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.app.IInstrumentationWatcher; 2118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.app.Instrumentation; 2218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.content.ComponentName; 2318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.Bundle; 2418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.Debug; 2518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.HandlerThread; 2618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.IBinder; 2718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.os.SystemClock; 2818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.test.RepetitiveTest; 2918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport android.util.Log; 3018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 3118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport com.android.uiautomator.core.ShellUiAutomatorBridge; 3218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport com.android.uiautomator.core.Tracer; 3318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport com.android.uiautomator.core.UiAutomationShellWrapper; 3418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport com.android.uiautomator.core.UiDevice; 3518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 3618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.io.ByteArrayOutputStream; 3718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.io.PrintStream; 3818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.lang.Thread.UncaughtExceptionHandler; 3918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.lang.reflect.Method; 4018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.ArrayList; 4118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.List; 4218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 4318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.framework.AssertionFailedError; 4418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.framework.Test; 4518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.framework.TestCase; 4618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.framework.TestListener; 4718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.framework.TestResult; 4818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.runner.BaseTestRunner; 4918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.textui.ResultPrinter; 5018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 5118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/** 5218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @hide 5318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 5418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupublic class UiAutomatorTestRunner { 5518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 5618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String LOGTAG = UiAutomatorTestRunner.class.getSimpleName(); 5718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final int EXIT_OK = 0; 5818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final int EXIT_EXCEPTION = -1; 5918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 6018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String HANDLER_THREAD_NAME = "UiAutomatorHandlerThread"; 6118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 6218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private boolean mDebug; 6318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private boolean mMonkey; 6418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private Bundle mParams = null; 6518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private UiDevice mUiDevice; 6618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private List<String> mTestClasses = null; 6718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final FakeInstrumentationWatcher mWatcher = new FakeInstrumentationWatcher(); 6818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final IAutomationSupport mAutomationSupport = new IAutomationSupport() { 6918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 7018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void sendStatus(int resultCode, Bundle status) { 7118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mWatcher.instrumentationStatus(null, resultCode, status); 7218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 7318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu }; 7418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final List<TestListener> mTestListeners = new ArrayList<TestListener>(); 7518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 7618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private HandlerThread mHandlerThread; 7718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 7818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void run(List<String> testClasses, Bundle params, boolean debug, boolean monkey) { 7918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { 8018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 8118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void uncaughtException(Thread thread, Throwable ex) { 8218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Log.e(LOGTAG, "uncaught exception", ex); 8318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Bundle results = new Bundle(); 8418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu results.putString("shortMsg", ex.getClass().getName()); 8518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu results.putString("longMsg", ex.getMessage()); 8618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mWatcher.instrumentationFinished(null, 0, results); 8718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // bailing on uncaught exception 8818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.exit(EXIT_EXCEPTION); 8918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 9018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu }); 9118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 9218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestClasses = testClasses; 9318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mParams = params; 9418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mDebug = debug; 9518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mMonkey = monkey; 9618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu start(); 9718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.exit(EXIT_OK); 9818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 9918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 10018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 10118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Called after all test classes are in place, ready to test 10218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 10318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected void start() { 10418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu TestCaseCollector collector = getTestCaseCollector(this.getClass().getClassLoader()); 10518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu try { 10618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu collector.addTestClasses(mTestClasses); 10718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } catch (ClassNotFoundException e) { 10818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // will be caught by uncaught handler 10918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu throw new RuntimeException(e.getMessage(), e); 11018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 11118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (mDebug) { 11218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Debug.waitForDebugger(); 11318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 11418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME); 11518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mHandlerThread.setDaemon(true); 11618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mHandlerThread.start(); 11718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu UiAutomationShellWrapper automationWrapper = new UiAutomationShellWrapper(); 11818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu automationWrapper.connect(); 11918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 12018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu long startTime = SystemClock.uptimeMillis(); 12118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu TestResult testRunResult = new TestResult(); 12218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu ResultReporter resultPrinter; 12318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String outputFormat = mParams.getString("outputFormat"); 12418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu List<TestCase> testCases = collector.getTestCases(); 12518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Bundle testRunOutput = new Bundle(); 12618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if ("simple".equals(outputFormat)) { 12718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu resultPrinter = new SimpleResultPrinter(System.out, true); 12818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } else { 12918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu resultPrinter = new WatcherResultPrinter(testCases.size()); 13018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 13118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu try { 13218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu automationWrapper.setRunAsMonkey(mMonkey); 13318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mUiDevice = UiDevice.getInstance(); 13418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mUiDevice.initialize(new ShellUiAutomatorBridge(automationWrapper.getUiAutomation())); 13518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 13618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String traceType = mParams.getString("traceOutputMode"); 13718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if(traceType != null) { 13818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Tracer.Mode mode = Tracer.Mode.valueOf(Tracer.Mode.class, traceType); 13918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (mode == Tracer.Mode.FILE || mode == Tracer.Mode.ALL) { 14018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String filename = mParams.getString("traceLogFilename"); 14118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (filename == null) { 14218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu throw new RuntimeException("Name of log file not specified. " + 14318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu "Please specify it using traceLogFilename parameter"); 14418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 14518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Tracer.getInstance().setOutputFilename(filename); 14618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 14718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Tracer.getInstance().setOutputMode(mode); 14818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 14918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 15018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // add test listeners 15118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testRunResult.addListener(resultPrinter); 15218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // add all custom listeners 15318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu for (TestListener listener : mTestListeners) { 15418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testRunResult.addListener(listener); 15518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 15618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 15718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // run tests for realz! 15818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu for (TestCase testCase : testCases) { 15918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu prepareTestCase(testCase); 16018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testCase.run(testRunResult); 16118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 16218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } catch (Throwable t) { 16318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // catch all exceptions so a more verbose error message can be outputted 16418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu resultPrinter.printUnexpectedError(t); 16518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testRunOutput.putString("shortMsg", t.getMessage()); 16618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } finally { 16718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu long runTime = SystemClock.uptimeMillis() - startTime; 16818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu resultPrinter.print(testRunResult, runTime, testRunOutput); 16918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu automationWrapper.disconnect(); 17018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu automationWrapper.setRunAsMonkey(false); 17118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mHandlerThread.quit(); 17218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 17318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 17418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 17518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // copy & pasted from com.android.commands.am.Am 17618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private class FakeInstrumentationWatcher implements IInstrumentationWatcher { 17718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 17818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final boolean mRawMode = true; 17918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 18018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 18118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public IBinder asBinder() { 18218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu throw new UnsupportedOperationException("I'm just a fake!"); 18318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 18418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 18518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 18618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) { 18718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu synchronized (this) { 18818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // pretty printer mode? 18918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String pretty = null; 19018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (!mRawMode && results != null) { 19118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 19218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 19318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (pretty != null) { 19418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.out.print(pretty); 19518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } else { 19618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (results != null) { 19718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu for (String key : results.keySet()) { 19818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.out.println("INSTRUMENTATION_STATUS: " + key + "=" 19918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu + results.get(key)); 20018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 20118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 20218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode); 20318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 20418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu notifyAll(); 20518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 20618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 20718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 20818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 20918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void instrumentationFinished(ComponentName name, int resultCode, Bundle results) { 21018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu synchronized (this) { 21118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // pretty printer mode? 21218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String pretty = null; 21318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (!mRawMode && results != null) { 21418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 21518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 21618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (pretty != null) { 21718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.out.println(pretty); 21818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } else { 21918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (results != null) { 22018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu for (String key : results.keySet()) { 22118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.out.println("INSTRUMENTATION_RESULT: " + key + "=" 22218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu + results.get(key)); 22318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 22418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 22518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu System.out.println("INSTRUMENTATION_CODE: " + resultCode); 22618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 22718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu notifyAll(); 22818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 22918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 23018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 23118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 23218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private interface ResultReporter extends TestListener { 23318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void print(TestResult result, long runTime, Bundle testOutput); 23418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void printUnexpectedError(Throwable t); 23518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 23618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 23718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // Copy & pasted from InstrumentationTestRunner.WatcherResultPrinter 23818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private class WatcherResultPrinter implements ResultReporter { 23918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 24018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_KEY_NUM_TOTAL = "numtests"; 24118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_KEY_NAME_CLASS = "class"; 24218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_KEY_NUM_CURRENT = "current"; 24318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_KEY_NAME_TEST = "test"; 24418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_KEY_NUM_ITERATIONS = "numiterations"; 24518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_VALUE_ID = "UiAutomatorTestRunner"; 24618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final String REPORT_KEY_STACK = "stack"; 24718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 24818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final int REPORT_VALUE_RESULT_START = 1; 24918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final int REPORT_VALUE_RESULT_ERROR = -1; 25018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private static final int REPORT_VALUE_RESULT_FAILURE = -2; 25118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 25218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final Bundle mResultTemplate; 25318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Bundle mTestResult; 25418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu int mTestNum = 0; 25518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu int mTestResultCode = 0; 25618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String mTestClass = null; 25718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 25818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final SimpleResultPrinter mPrinter; 25918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final ByteArrayOutputStream mStream; 26018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final PrintStream mWriter; 26118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 26218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public WatcherResultPrinter(int numTests) { 26318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mResultTemplate = new Bundle(); 26418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID); 26518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests); 26618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 26718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mStream = new ByteArrayOutputStream(); 26818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mWriter = new PrintStream(mStream); 26918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mPrinter = new SimpleResultPrinter(mWriter, false); 27018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 27118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 27218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 27318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * send a status for the start of a each test, so long tests can be seen 27418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * as "running" 27518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 27618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 27718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void startTest(Test test) { 27818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String testClass = test.getClass().getName(); 27918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String testName = ((TestCase) test).getName(); 28018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult = new Bundle(mResultTemplate); 28118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass); 28218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(REPORT_KEY_NAME_TEST, testName); 28318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum); 28418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // pretty printing 28518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (testClass != null && !testClass.equals(mTestClass)) { 28618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 28718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String.format("\n%s:", testClass)); 28818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestClass = testClass; 28918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } else { 29018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ""); 29118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 29218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 29318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Method testMethod = null; 29418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu try { 29518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testMethod = test.getClass().getMethod(testName); 29618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // Report total number of iterations, if test is repetitive 29718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (testMethod.isAnnotationPresent(RepetitiveTest.class)) { 29818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu int numIterations = testMethod.getAnnotation(RepetitiveTest.class) 29918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu .numIterations(); 30018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putInt(REPORT_KEY_NUM_ITERATIONS, numIterations); 30118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 30218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } catch (NoSuchMethodException e) { 30318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // ignore- the test with given name does not exist. Will be 30418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // handled during test 30518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // execution 30618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 30718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 30818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mAutomationSupport.sendStatus(REPORT_VALUE_RESULT_START, mTestResult); 30918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResultCode = 0; 31018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 31118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mPrinter.startTest(test); 31218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 31318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 31418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 31518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void addError(Test test, Throwable t) { 31618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t)); 31718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResultCode = REPORT_VALUE_RESULT_ERROR; 31818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // pretty printing 31918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 32018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String.format("\nError in %s:\n%s", 32118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t))); 32218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 32318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mPrinter.addError(test, t); 32418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 32518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 32618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 32718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void addFailure(Test test, AssertionFailedError t) { 32818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t)); 32918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResultCode = REPORT_VALUE_RESULT_FAILURE; 33018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu // pretty printing 33118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 33218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String.format("\nFailure in %s:\n%s", 33318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t))); 33418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 33518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mPrinter.addFailure(test, t); 33618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 33718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 33818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 33918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void endTest(Test test) { 34018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (mTestResultCode == 0) { 34118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "."); 34218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 34318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mAutomationSupport.sendStatus(mTestResultCode, mTestResult); 34418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 34518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mPrinter.endTest(test); 34618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 34718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 34818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 34918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void print(TestResult result, long runTime, Bundle testOutput) { 35018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mPrinter.print(result, runTime, testOutput); 35118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testOutput.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 35218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String.format("\nTest results for %s=%s", 35318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu getClass().getSimpleName(), 35418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mStream.toString())); 35518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mWriter.close(); 35618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mAutomationSupport.sendStatus(Activity.RESULT_OK, testOutput); 35718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 35818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 35918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 36018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void printUnexpectedError(Throwable t) { 36118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mWriter.println(String.format("Test run aborted due to unexpected exception: %s", 36218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu t.getMessage())); 36318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu t.printStackTrace(mWriter); 36418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 36518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 36618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 36718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 36818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Class that produces the same output as JUnit when running from command line. Can be 36918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * used when default UiAutomator output is too verbose. 37018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 37118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private class SimpleResultPrinter extends ResultPrinter implements ResultReporter { 37218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private final boolean mFullOutput; 37318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public SimpleResultPrinter(PrintStream writer, boolean fullOutput) { 37418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu super(writer); 37518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mFullOutput = fullOutput; 37618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 37718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 37818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 37918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void print(TestResult result, long runTime, Bundle testOutput) { 38018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu printHeader(runTime); 38118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (mFullOutput) { 38218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu printErrors(result); 38318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu printFailures(result); 38418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 38518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu printFooter(result); 38618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 38718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 38818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu @Override 38918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void printUnexpectedError(Throwable t) { 39018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (mFullOutput) { 39118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu getWriter().printf("Test run aborted due to unexpected exeption: %s", 39218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu t.getMessage()); 39318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu t.printStackTrace(getWriter()); 39418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 39518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 39618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 39718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 39818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected TestCaseCollector getTestCaseCollector(ClassLoader classLoader) { 39918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu return new TestCaseCollector(classLoader, getTestCaseFilter()); 40018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 40118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 40218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 40318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Returns an object which determines if the class and its methods should be 40418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * accepted into the test suite. 40518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @return 40618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 40718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public UiAutomatorTestCaseFilter getTestCaseFilter() { 40818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu return new UiAutomatorTestCaseFilter(); 40918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 41018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 41118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected void addTestListener(TestListener listener) { 41218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (!mTestListeners.contains(listener)) { 41318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestListeners.add(listener); 41418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 41518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 41618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 41718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected void removeTestListener(TestListener listener) { 41818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestListeners.remove(listener); 41918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 42018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 42118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 42218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * subclass may override this method to perform further preparation 42318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 42418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param testCase 42518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 42618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected void prepareTestCase(TestCase testCase) { 42718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu ((UiAutomatorTestCase)testCase).setAutomationSupport(mAutomationSupport); 42818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu ((UiAutomatorTestCase)testCase).setUiDevice(mUiDevice); 42918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu ((UiAutomatorTestCase)testCase).setParams(mParams); 43018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 43118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu} 432