1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.test.runner.listener; 17 18 import android.app.Instrumentation; 19 import android.os.Bundle; 20 21 import org.junit.runner.Description; 22 import org.junit.runner.Result; 23 import org.junit.runner.notification.Failure; 24 25 /** 26 * A {@link RunListener} that sends detailed pass/fail results back as instrumentation status 27 * bundles. This output appears when running the instrumentation in '-r' or raw mode. 28 */ 29 public class InstrumentationResultPrinter extends InstrumentationRunListener { 30 31 /** 32 * This value, if stored with key {@link android.app.Instrumentation#REPORT_KEY_IDENTIFIER}, 33 * identifies AndroidJUnitRunner as the source of the report. This is sent with all 34 * status messages. 35 */ 36 public static final String REPORT_VALUE_ID = "AndroidJUnitRunner"; 37 /** 38 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 39 * identifies the total number of tests that are being run. This is sent with all status 40 * messages. 41 */ 42 public static final String REPORT_KEY_NUM_TOTAL = "numtests"; 43 /** 44 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 45 * identifies the sequence number of the current test. This is sent with any status message 46 * describing a specific test being started or completed. 47 */ 48 public static final String REPORT_KEY_NUM_CURRENT = "current"; 49 /** 50 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 51 * identifies the name of the current test class. This is sent with any status message 52 * describing a specific test being started or completed. 53 */ 54 public static final String REPORT_KEY_NAME_CLASS = "class"; 55 /** 56 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 57 * identifies the name of the current test. This is sent with any status message 58 * describing a specific test being started or completed. 59 */ 60 public static final String REPORT_KEY_NAME_TEST = "test"; 61 62 /** 63 * The test is starting. 64 */ 65 public static final int REPORT_VALUE_RESULT_START = 1; 66 /** 67 * The test completed successfully. 68 */ 69 public static final int REPORT_VALUE_RESULT_OK = 0; 70 /** 71 * The test completed with an error. 72 */ 73 public static final int REPORT_VALUE_RESULT_ERROR = -1; 74 /** 75 * The test completed with a failure. 76 */ 77 public static final int REPORT_VALUE_RESULT_FAILURE = -2; 78 /** 79 * The test was ignored. 80 */ 81 public static final int REPORT_VALUE_RESULT_IGNORED = -3; 82 /** 83 * If included in the status bundle sent to an IInstrumentationWatcher, this key 84 * identifies a stack trace describing an error or failure. This is sent with any status 85 * message describing a specific test being completed. 86 */ 87 public static final String REPORT_KEY_STACK = "stack"; 88 89 private final Bundle mResultTemplate; 90 Bundle mTestResult; 91 int mTestNum = 0; 92 int mTestResultCode = 0; 93 String mTestClass = null; 94 95 public InstrumentationResultPrinter(Instrumentation i) { 96 super(i); 97 mResultTemplate = new Bundle(); 98 } 99 100 @Override 101 public void testRunStarted(Description description) throws Exception { 102 mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID); 103 mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, description.testCount()); 104 } 105 106 @Override 107 public void testRunFinished(Result result) throws Exception { 108 } 109 110 /** 111 * send a status for the start of a each test, so long tests can be seen 112 * as "running" 113 */ 114 @Override 115 public void testStarted(Description description) throws Exception { 116 String testClass = description.getClassName(); 117 String testName = description.getMethodName(); 118 mTestResult = new Bundle(mResultTemplate); 119 mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass); 120 mTestResult.putString(REPORT_KEY_NAME_TEST, testName); 121 mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mTestNum); 122 // pretty printing 123 if (testClass != null && !testClass.equals(mTestClass)) { 124 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 125 String.format("\n%s:", testClass)); 126 mTestClass = testClass; 127 } else { 128 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ""); 129 } 130 131 sendStatus(REPORT_VALUE_RESULT_START, mTestResult); 132 mTestResultCode = 0; 133 } 134 135 @Override 136 public void testFinished(Description description) throws Exception { 137 if (mTestResultCode == 0) { 138 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "."); 139 } 140 sendStatus(mTestResultCode, mTestResult); 141 } 142 143 @Override 144 public void testFailure(Failure failure) throws Exception { 145 mTestResultCode = REPORT_VALUE_RESULT_ERROR; 146 reportFailure(failure); 147 } 148 149 150 @Override 151 public void testAssumptionFailure(Failure failure) { 152 mTestResultCode = REPORT_VALUE_RESULT_FAILURE; 153 reportFailure(failure); 154 } 155 156 private void reportFailure(Failure failure) { 157 mTestResult.putString(REPORT_KEY_STACK, failure.getTrace()); 158 // pretty printing 159 mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, 160 String.format("\nError in %s:\n%s", 161 failure.getDescription().getDisplayName(), failure.getTrace())); 162 } 163 164 @Override 165 public void testIgnored(Description description) throws Exception { 166 testStarted(description); 167 mTestResultCode = REPORT_VALUE_RESULT_IGNORED; 168 testFinished(description); 169 } 170 } 171