blob: aa7c677c968f5b7937ec08725d95cd6e74f04af3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package android.test;
18
19import android.app.Instrumentation;
20import android.content.Context;
Jack Wangff1df692009-08-26 17:19:13 -070021import android.os.PerformanceCollector.PerformanceResultsWriter;
22
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.google.android.collect.Lists;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import junit.framework.Test;
26import junit.framework.TestCase;
27import junit.framework.TestListener;
28import junit.framework.TestResult;
29import junit.framework.TestSuite;
30import junit.runner.BaseTestRunner;
31
Brian Muramatsu87571b72012-04-03 11:46:56 -070032import java.lang.reflect.Constructor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import java.lang.reflect.InvocationTargetException;
34import java.util.List;
35
36public class AndroidTestRunner extends BaseTestRunner {
37
38 private TestResult mTestResult;
39 private String mTestClassName;
40 private List<TestCase> mTestCases;
41 private Context mContext;
42 private boolean mSkipExecution = false;
43
44 private List<TestListener> mTestListeners = Lists.newArrayList();
45 private Instrumentation mInstrumentation;
Jack Wangff1df692009-08-26 17:19:13 -070046 private PerformanceResultsWriter mPerfWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
48 @SuppressWarnings("unchecked")
49 public void setTestClassName(String testClassName, String testMethodName) {
50 Class testClass = loadTestClass(testClassName);
51
52 if (shouldRunSingleTestMethod(testMethodName, testClass)) {
53 TestCase testCase = buildSingleTestMethod(testClass, testMethodName);
54 mTestCases = Lists.newArrayList(testCase);
55 mTestClassName = testClass.getSimpleName();
56 } else {
57 setTest(getTest(testClass), testClass);
58 }
59 }
60
61 public void setTest(Test test) {
62 setTest(test, test.getClass());
63 }
64
65 private void setTest(Test test, Class<? extends Test> testClass) {
66 mTestCases = (List<TestCase>) TestCaseUtil.getTests(test, true);
67 if (TestSuite.class.isAssignableFrom(testClass)) {
68 mTestClassName = TestCaseUtil.getTestName(test);
69 } else {
70 mTestClassName = testClass.getSimpleName();
71 }
72 }
73
74 public void clearTestListeners() {
75 mTestListeners.clear();
76 }
77
78 public void addTestListener(TestListener testListener) {
79 if (testListener != null) {
80 mTestListeners.add(testListener);
81 }
82 }
83
84 @SuppressWarnings("unchecked")
85 private Class<? extends Test> loadTestClass(String testClassName) {
86 try {
87 return (Class<? extends Test>) mContext.getClassLoader().loadClass(testClassName);
88 } catch (ClassNotFoundException e) {
89 runFailed("Could not find test class. Class: " + testClassName);
90 }
91 return null;
92 }
93
94 private TestCase buildSingleTestMethod(Class testClass, String testMethodName) {
95 try {
Brian Muramatsu87571b72012-04-03 11:46:56 -070096 Constructor c = testClass.getConstructor();
97 return newSingleTestMethod(testClass, testMethodName, c);
98 } catch (NoSuchMethodException e) {
99 }
100
101 try {
102 Constructor c = testClass.getConstructor(String.class);
103 return newSingleTestMethod(testClass, testMethodName, c, testMethodName);
104 } catch (NoSuchMethodException e) {
105 }
106
107 return null;
108 }
109
110 private TestCase newSingleTestMethod(Class testClass, String testMethodName,
111 Constructor constructor, Object... args) {
112 try {
113 TestCase testCase = (TestCase) constructor.newInstance(args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 testCase.setName(testMethodName);
115 return testCase;
116 } catch (IllegalAccessException e) {
117 runFailed("Could not access test class. Class: " + testClass.getName());
118 } catch (InstantiationException e) {
119 runFailed("Could not instantiate test class. Class: " + testClass.getName());
Brian Muramatsu87571b72012-04-03 11:46:56 -0700120 } catch (IllegalArgumentException e) {
121 runFailed("Illegal argument passed to constructor. Class: " + testClass.getName());
122 } catch (InvocationTargetException e) {
123 runFailed("Constructor thew an exception. Class: " + testClass.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 return null;
126 }
127
128 private boolean shouldRunSingleTestMethod(String testMethodName,
129 Class<? extends Test> testClass) {
130 return testMethodName != null && TestCase.class.isAssignableFrom(testClass);
131 }
132
133 private Test getTest(Class clazz) {
134 if (TestSuiteProvider.class.isAssignableFrom(clazz)) {
135 try {
136 TestSuiteProvider testSuiteProvider =
137 (TestSuiteProvider) clazz.getConstructor().newInstance();
138 return testSuiteProvider.getTestSuite();
139 } catch (InstantiationException e) {
140 runFailed("Could not instantiate test suite provider. Class: " + clazz.getName());
141 } catch (IllegalAccessException e) {
142 runFailed("Illegal access of test suite provider. Class: " + clazz.getName());
143 } catch (InvocationTargetException e) {
144 runFailed("Invocation exception test suite provider. Class: " + clazz.getName());
145 } catch (NoSuchMethodException e) {
146 runFailed("No such method on test suite provider. Class: " + clazz.getName());
147 }
148 }
149 return getTest(clazz.getName());
150 }
151
152 protected TestResult createTestResult() {
153 if (mSkipExecution) {
154 return new NoExecTestResult();
155 }
156 return new TestResult();
157 }
Jack Wang4f414bd2009-11-06 20:53:47 -0800158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 void setSkipExecution(boolean skip) {
160 mSkipExecution = skip;
161 }
162
163 public List<TestCase> getTestCases() {
164 return mTestCases;
165 }
166
167 public String getTestClassName() {
168 return mTestClassName;
169 }
170
171 public TestResult getTestResult() {
172 return mTestResult;
173 }
174
175 public void runTest() {
176 runTest(createTestResult());
177 }
178
179 public void runTest(TestResult testResult) {
180 mTestResult = testResult;
181
182 for (TestListener testListener : mTestListeners) {
183 mTestResult.addListener(testListener);
184 }
185
Jack Wanga8db0a42009-08-17 14:19:52 -0700186 Context testContext = mInstrumentation == null ? mContext : mInstrumentation.getContext();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 for (TestCase testCase : mTestCases) {
Dmitri Plotnikov44a29dd2009-08-03 14:27:20 -0700188 setContextIfAndroidTestCase(testCase, mContext, testContext);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 setInstrumentationIfInstrumentationTestCase(testCase, mInstrumentation);
Jack Wang4f414bd2009-11-06 20:53:47 -0800190 setPerformanceWriterIfPerformanceCollectorTestCase(testCase, mPerfWriter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 testCase.run(mTestResult);
192 }
193 }
194
Dmitri Plotnikov44a29dd2009-08-03 14:27:20 -0700195 private void setContextIfAndroidTestCase(Test test, Context context, Context testContext) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 if (AndroidTestCase.class.isAssignableFrom(test.getClass())) {
197 ((AndroidTestCase) test).setContext(context);
Dmitri Plotnikov44a29dd2009-08-03 14:27:20 -0700198 ((AndroidTestCase) test).setTestContext(testContext);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 }
200 }
201
202 public void setContext(Context context) {
203 mContext = context;
204 }
205
206 private void setInstrumentationIfInstrumentationTestCase(
207 Test test, Instrumentation instrumentation) {
208 if (InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
Jack Wang7aba54b2009-08-20 19:20:54 -0700209 ((InstrumentationTestCase) test).injectInstrumentation(instrumentation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 }
211 }
212
Jack Wang4f414bd2009-11-06 20:53:47 -0800213 private void setPerformanceWriterIfPerformanceCollectorTestCase(
Jack Wangff1df692009-08-26 17:19:13 -0700214 Test test, PerformanceResultsWriter writer) {
Jack Wang4f414bd2009-11-06 20:53:47 -0800215 if (PerformanceCollectorTestCase.class.isAssignableFrom(test.getClass())) {
216 ((PerformanceCollectorTestCase) test).setPerformanceResultsWriter(writer);
Jack Wangff1df692009-08-26 17:19:13 -0700217 }
218 }
219
Jack Wang7aba54b2009-08-20 19:20:54 -0700220 public void setInstrumentation(Instrumentation instrumentation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 mInstrumentation = instrumentation;
222 }
223
Jack Wang7aba54b2009-08-20 19:20:54 -0700224 /**
225 * @deprecated Incorrect spelling,
226 * use {@link #setInstrumentation(android.app.Instrumentation)} instead.
227 */
228 @Deprecated
229 public void setInstrumentaiton(Instrumentation instrumentation) {
230 setInstrumentation(instrumentation);
231 }
232
Jack Wangff1df692009-08-26 17:19:13 -0700233 /**
234 * {@hide} Pending approval for public API.
235 */
236 public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
237 mPerfWriter = writer;
238 }
239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 @Override
241 protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
242 return mContext.getClassLoader().loadClass(suiteClassName);
243 }
244
245 public void testStarted(String testName) {
246 }
247
248 public void testEnded(String testName) {
249 }
250
251 public void testFailed(int status, Test test, Throwable t) {
252 }
253
254 protected void runFailed(String message) {
255 throw new RuntimeException(message);
256 }
257}