1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/* 2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project 3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License. 6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at 7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software 11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and 14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License. 15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.testrunner; 18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.app.Activity; 20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.app.IInstrumentationWatcher; 21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.app.Instrumentation; 22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.content.ComponentName; 23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.Bundle; 24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.Debug; 2589f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganovimport android.os.HandlerThread; 26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.IBinder; 27d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavineimport android.os.SystemClock; 28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.test.RepetitiveTest; 29e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.Log; 30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 31cd08ab4b0d19e68cc1cf18396cb9076e828c1a63Guang Zhuimport com.android.uiautomator.core.ShellUiAutomatorBridge; 32f406deb12db531785300f04e219fef28ef60b126Maxim Siniavineimport com.android.uiautomator.core.Tracer; 3389f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganovimport com.android.uiautomator.core.UiAutomationShellWrapper; 34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport com.android.uiautomator.core.UiDevice; 35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 3648c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtazimport java.io.ByteArrayOutputStream; 3748c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtazimport java.io.PrintStream; 3848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtazimport java.lang.Thread.UncaughtExceptionHandler; 3948c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtazimport java.lang.reflect.Method; 4048c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtazimport java.util.ArrayList; 4148c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtazimport java.util.List; 4248c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz 43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.AssertionFailedError; 44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.Test; 45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestCase; 46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestListener; 47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestResult; 48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.runner.BaseTestRunner; 49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.textui.ResultPrinter; 50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 51ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu/** 52ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu * @hide 53ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu */ 54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class UiAutomatorTestRunner { 55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String LOGTAG = UiAutomatorTestRunner.class.getSimpleName(); 57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int EXIT_OK = 0; 58e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int EXIT_EXCEPTION = -1; 59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 6089f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov private static final String HANDLER_THREAD_NAME = "UiAutomatorHandlerThread"; 6189f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov 62e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private boolean mDebug; 6348c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private boolean mMonkey; 64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private Bundle mParams = null; 65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private UiDevice mUiDevice; 66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private List<String> mTestClasses = null; 6748c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final FakeInstrumentationWatcher mWatcher = new FakeInstrumentationWatcher(); 6848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final IAutomationSupport mAutomationSupport = new IAutomationSupport() { 69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 70e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void sendStatus(int resultCode, Bundle status) { 71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mWatcher.instrumentationStatus(null, resultCode, status); 72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu }; 7448c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final List<TestListener> mTestListeners = new ArrayList<TestListener>(); 75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 7689f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov private HandlerThread mHandlerThread; 7789f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov 7848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz public void run(List<String> testClasses, Bundle params, boolean debug, boolean monkey) { 79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { 80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void uncaughtException(Thread thread, Throwable ex) { 82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.e(LOGTAG, "uncaught exception", ex); 83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Bundle results = new Bundle(); 84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu results.putString("shortMsg", ex.getClass().getName()); 85e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu results.putString("longMsg", ex.getMessage()); 86e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mWatcher.instrumentationFinished(null, 0, results); 87e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // bailing on uncaught exception 88e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.exit(EXIT_EXCEPTION); 89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu }); 91e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 92e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestClasses = testClasses; 93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mParams = params; 94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mDebug = debug; 9548c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz mMonkey = monkey; 96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu start(); 97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.exit(EXIT_OK); 98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 99e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 101e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Called after all test classes are in place, ready to test 102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected void start() { 104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu TestCaseCollector collector = getTestCaseCollector(this.getClass().getClassLoader()); 105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu try { 106e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu collector.addTestClasses(mTestClasses); 107e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } catch (ClassNotFoundException e) { 108e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // will be caught by uncaught handler 109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new RuntimeException(e.getMessage(), e); 110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (mDebug) { 112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Debug.waitForDebugger(); 113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 11489f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME); 11589f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov mHandlerThread.setDaemon(true); 11689f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov mHandlerThread.start(); 11789f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov UiAutomationShellWrapper automationWrapper = new UiAutomationShellWrapper(); 11889f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov automationWrapper.connect(); 119f406deb12db531785300f04e219fef28ef60b126Maxim Siniavine 12071aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz long startTime = SystemClock.uptimeMillis(); 121d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine TestResult testRunResult = new TestResult(); 122d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine ResultReporter resultPrinter; 123d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine String outputFormat = mParams.getString("outputFormat"); 12471aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz List<TestCase> testCases = collector.getTestCases(); 12571aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz Bundle testRunOutput = new Bundle(); 126d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine if ("simple".equals(outputFormat)) { 127d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine resultPrinter = new SimpleResultPrinter(System.out, true); 128d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } else { 129d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine resultPrinter = new WatcherResultPrinter(testCases.size()); 130d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 131d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine try { 13271aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz automationWrapper.setRunAsMonkey(mMonkey); 13371aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz mUiDevice = UiDevice.getInstance(); 13471aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz mUiDevice.initialize(new ShellUiAutomatorBridge(automationWrapper.getUiAutomation())); 13571aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz 13671aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz String traceType = mParams.getString("traceOutputMode"); 13771aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz if(traceType != null) { 13871aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz Tracer.Mode mode = Tracer.Mode.valueOf(Tracer.Mode.class, traceType); 13971aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz if (mode == Tracer.Mode.FILE || mode == Tracer.Mode.ALL) { 14071aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz String filename = mParams.getString("traceLogFilename"); 14171aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz if (filename == null) { 14271aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz throw new RuntimeException("Name of log file not specified. " + 14371aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz "Please specify it using traceLogFilename parameter"); 14471aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz } 14571aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz Tracer.getInstance().setOutputFilename(filename); 14671aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz } 14771aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz Tracer.getInstance().setOutputMode(mode); 14871aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz } 14971aebfa11443a9a04777cde3d9c7e29cdbb5d447Adam Momtaz 150e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // add test listeners 151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu testRunResult.addListener(resultPrinter); 152e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // add all custom listeners 153e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (TestListener listener : mTestListeners) { 154e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu testRunResult.addListener(listener); 155e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 156e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 157e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // run tests for realz! 158e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (TestCase testCase : testCases) { 159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu prepareTestCase(testCase); 160e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu testCase.run(testRunResult); 161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 162e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } catch (Throwable t) { 163e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // catch all exceptions so a more verbose error message can be outputted 164d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine resultPrinter.printUnexpectedError(t); 165dba37a78454da33c43921dd289df3b9e8080ed8aGuang Zhu testRunOutput.putString("shortMsg", t.getMessage()); 166e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } finally { 167d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine long runTime = SystemClock.uptimeMillis() - startTime; 168d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine resultPrinter.print(testRunResult, runTime, testRunOutput); 16989f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov automationWrapper.disconnect(); 17048c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz automationWrapper.setRunAsMonkey(false); 17189f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov mHandlerThread.quit(); 172e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 173e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 174e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 175e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // copy & pasted from com.android.commands.am.Am 176e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private class FakeInstrumentationWatcher implements IInstrumentationWatcher { 177e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 17848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final boolean mRawMode = true; 179e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 180e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 181e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public IBinder asBinder() { 182e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UnsupportedOperationException("I'm just a fake!"); 183e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 184e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 185e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 186e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) { 187e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu synchronized (this) { 188e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // pretty printer mode? 189e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String pretty = null; 190e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (!mRawMode && results != null) { 191e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 192e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 193e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (pretty != null) { 194e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.out.print(pretty); 195e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 196e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (results != null) { 197e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (String key : results.keySet()) { 198e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.out.println("INSTRUMENTATION_STATUS: " + key + "=" 199e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu + results.get(key)); 200e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 201e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 202e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode); 203e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 204e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu notifyAll(); 205e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 206e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 207e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 208e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 209e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void instrumentationFinished(ComponentName name, int resultCode, Bundle results) { 210e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu synchronized (this) { 211e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // pretty printer mode? 212e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String pretty = null; 213e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (!mRawMode && results != null) { 214e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 215e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 216e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (pretty != null) { 217e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.out.println(pretty); 218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 219e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (results != null) { 220e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (String key : results.keySet()) { 221e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.out.println("INSTRUMENTATION_RESULT: " + key + "=" 222e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu + results.get(key)); 223e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 224e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 225e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu System.out.println("INSTRUMENTATION_CODE: " + resultCode); 226e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 227e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu notifyAll(); 228e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 229e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 230e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 231e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 232d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine private interface ResultReporter extends TestListener { 233d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public void print(TestResult result, long runTime, Bundle testOutput); 234d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public void printUnexpectedError(Throwable t); 235d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 236d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 237e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Copy & pasted from InstrumentationTestRunner.WatcherResultPrinter 238d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine private class WatcherResultPrinter implements ResultReporter { 239e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 240e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_KEY_NUM_TOTAL = "numtests"; 241e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_KEY_NAME_CLASS = "class"; 242e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_KEY_NUM_CURRENT = "current"; 243e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_KEY_NAME_TEST = "test"; 244e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_KEY_NUM_ITERATIONS = "numiterations"; 245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_VALUE_ID = "UiAutomatorTestRunner"; 246e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String REPORT_KEY_STACK = "stack"; 247e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 248e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int REPORT_VALUE_RESULT_START = 1; 249e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int REPORT_VALUE_RESULT_ERROR = -1; 250e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int REPORT_VALUE_RESULT_FAILURE = -2; 251e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 252e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private final Bundle mResultTemplate; 253e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Bundle mTestResult; 254e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int mTestNum = 0; 255e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int mTestResultCode = 0; 256e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String mTestClass = null; 257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 25848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final SimpleResultPrinter mPrinter; 25948c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final ByteArrayOutputStream mStream; 26048c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final PrintStream mWriter; 261d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 262e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public WatcherResultPrinter(int numTests) { 263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mResultTemplate = new Bundle(); 264e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID); 265e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests); 266d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 267d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mStream = new ByteArrayOutputStream(); 268d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mWriter = new PrintStream(mStream); 269d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mPrinter = new SimpleResultPrinter(mWriter, false); 270e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 271e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 272e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 273e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * send a status for the start of a each test, so long tests can be seen 274e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * as "running" 275e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 276e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 277e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void startTest(Test test) { 278e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String testClass = test.getClass().getName(); 279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String testName = ((TestCase) test).getName(); 280e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult = new Bundle(mResultTemplate); 281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass); 282e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(REPORT_KEY_NAME_TEST, testName); 283e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum); 284e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // pretty printing 285e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (testClass != null && !testClass.equals(mTestClass)) { 286e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 287e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String.format("\n%s:", testClass)); 288e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestClass = testClass; 289e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 290e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ""); 291e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 292e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 293e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Method testMethod = null; 294e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu try { 295e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu testMethod = test.getClass().getMethod(testName); 296e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Report total number of iterations, if test is repetitive 297e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (testMethod.isAnnotationPresent(RepetitiveTest.class)) { 298e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int numIterations = testMethod.getAnnotation(RepetitiveTest.class) 299e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu .numIterations(); 300e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putInt(REPORT_KEY_NUM_ITERATIONS, numIterations); 301e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 302e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } catch (NoSuchMethodException e) { 303e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // ignore- the test with given name does not exist. Will be 304e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // handled during test 305e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // execution 306e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 307e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 308e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mAutomationSupport.sendStatus(REPORT_VALUE_RESULT_START, mTestResult); 309e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResultCode = 0; 310d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 311d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mPrinter.startTest(test); 312e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 313e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 314e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void addError(Test test, Throwable t) { 316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t)); 317e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResultCode = REPORT_VALUE_RESULT_ERROR; 318e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // pretty printing 319e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 320e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String.format("\nError in %s:\n%s", 321e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t))); 322d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 323d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mPrinter.addError(test, t); 324e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 325e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 326e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 327e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void addFailure(Test test, AssertionFailedError t) { 328e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(REPORT_KEY_STACK, BaseTestRunner.getFilteredTrace(t)); 329e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResultCode = REPORT_VALUE_RESULT_FAILURE; 330e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // pretty printing 331e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 332e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String.format("\nFailure in %s:\n%s", 333e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu ((TestCase)test).getName(), BaseTestRunner.getFilteredTrace(t))); 334d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 335d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mPrinter.addFailure(test, t); 336e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 337e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 338e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 339e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void endTest(Test test) { 340e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (mTestResultCode == 0) { 341e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "."); 342e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 343e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mAutomationSupport.sendStatus(mTestResultCode, mTestResult); 344d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 345d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mPrinter.endTest(test); 346e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 347e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 34848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz @Override 349d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public void print(TestResult result, long runTime, Bundle testOutput) { 350d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mPrinter.print(result, runTime, testOutput); 351d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine testOutput.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 352d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine String.format("\nTest results for %s=%s", 353d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine getClass().getSimpleName(), 354d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mStream.toString())); 355d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mWriter.close(); 356d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mAutomationSupport.sendStatus(Activity.RESULT_OK, testOutput); 357d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 358e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 35948c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz @Override 360d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public void printUnexpectedError(Throwable t) { 361d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mWriter.println(String.format("Test run aborted due to unexpected exception: %s", 362d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine t.getMessage())); 363d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine t.printStackTrace(mWriter); 364d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 365d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 366e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 367d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine /** 368d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine * Class that produces the same output as JUnit when running from command line. Can be 369d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine * used when default UiAutomator output is too verbose. 370d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine */ 371d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine private class SimpleResultPrinter extends ResultPrinter implements ResultReporter { 37248c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz private final boolean mFullOutput; 373d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public SimpleResultPrinter(PrintStream writer, boolean fullOutput) { 374e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu super(writer); 375d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine mFullOutput = fullOutput; 376e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 377e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 37848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz @Override 379d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public void print(TestResult result, long runTime, Bundle testOutput) { 380e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu printHeader(runTime); 381d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine if (mFullOutput) { 382d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine printErrors(result); 383d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine printFailures(result); 384d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 385e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu printFooter(result); 386e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 387d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine 38848c83ae3e5fc36138a412fc5854d543fffe80376Adam Momtaz @Override 389d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine public void printUnexpectedError(Throwable t) { 390d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine if (mFullOutput) { 391d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine getWriter().printf("Test run aborted due to unexpected exeption: %s", 392d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine t.getMessage()); 393d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine t.printStackTrace(getWriter()); 394d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 395d053117ad50d47a7f2b25be4303d945e4e9edd1eMaxim Siniavine } 396e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 397e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 398e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected TestCaseCollector getTestCaseCollector(ClassLoader classLoader) { 399bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine return new TestCaseCollector(classLoader, getTestCaseFilter()); 400bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine } 401bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine 402bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine /** 403bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine * Returns an object which determines if the class and its methods should be 404bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine * accepted into the test suite. 405bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine * @return 406bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine */ 407bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine public UiAutomatorTestCaseFilter getTestCaseFilter() { 408bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine return new UiAutomatorTestCaseFilter(); 409e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 410e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 411e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected void addTestListener(TestListener listener) { 412e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (!mTestListeners.contains(listener)) { 413e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestListeners.add(listener); 414e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 415e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 416e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 417e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected void removeTestListener(TestListener listener) { 418e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestListeners.remove(listener); 419e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 420e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 421e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 422e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * subclass may override this method to perform further preparation 423e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 424e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param testCase 425e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 426e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected void prepareTestCase(TestCase testCase) { 427e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu ((UiAutomatorTestCase)testCase).setAutomationSupport(mAutomationSupport); 428e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu ((UiAutomatorTestCase)testCase).setUiDevice(mUiDevice); 429e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu ((UiAutomatorTestCase)testCase).setParams(mParams); 430e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 431e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu} 432