• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.test;
18 
19 import android.app.Instrumentation;
20 import android.content.Context;
21 import android.os.PerformanceCollector.PerformanceResultsWriter;
22 
23 import com.google.android.collect.Lists;
24 import junit.framework.Test;
25 import junit.framework.TestCase;
26 import junit.framework.TestListener;
27 import junit.framework.TestResult;
28 import junit.framework.TestSuite;
29 import junit.runner.BaseTestRunner;
30 
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.InvocationTargetException;
33 import java.util.List;
34 
35 public class AndroidTestRunner extends BaseTestRunner {
36 
37     private TestResult mTestResult;
38     private String mTestClassName;
39     private List<TestCase> mTestCases;
40     private Context mContext;
41     private boolean mSkipExecution = false;
42 
43     private List<TestListener> mTestListeners = Lists.newArrayList();
44     private Instrumentation mInstrumentation;
45     private PerformanceResultsWriter mPerfWriter;
46 
47     @SuppressWarnings("unchecked")
setTestClassName(String testClassName, String testMethodName)48     public void setTestClassName(String testClassName, String testMethodName) {
49         Class testClass = loadTestClass(testClassName);
50 
51         if (shouldRunSingleTestMethod(testMethodName, testClass)) {
52             TestCase testCase = buildSingleTestMethod(testClass, testMethodName);
53             mTestCases = Lists.newArrayList(testCase);
54             mTestClassName = testClass.getSimpleName();
55         } else {
56             setTest(getTest(testClass), testClass);
57         }
58     }
59 
setTest(Test test)60     public void setTest(Test test) {
61         setTest(test, test.getClass());
62     }
63 
setTest(Test test, Class<? extends Test> testClass)64     private void setTest(Test test, Class<? extends Test> testClass) {
65         mTestCases = (List<TestCase>) TestCaseUtil.getTests(test, true);
66         if (TestSuite.class.isAssignableFrom(testClass)) {
67             mTestClassName = TestCaseUtil.getTestName(test);
68         } else {
69             mTestClassName = testClass.getSimpleName();
70         }
71     }
72 
clearTestListeners()73     public void clearTestListeners() {
74         mTestListeners.clear();
75     }
76 
addTestListener(TestListener testListener)77     public void addTestListener(TestListener testListener) {
78         if (testListener != null) {
79             mTestListeners.add(testListener);
80         }
81     }
82 
83     @SuppressWarnings("unchecked")
loadTestClass(String testClassName)84     private Class<? extends Test> loadTestClass(String testClassName) {
85         try {
86             return (Class<? extends Test>) mContext.getClassLoader().loadClass(testClassName);
87         } catch (ClassNotFoundException e) {
88             runFailed("Could not find test class. Class: " + testClassName);
89         }
90         return null;
91     }
92 
buildSingleTestMethod(Class testClass, String testMethodName)93     private TestCase buildSingleTestMethod(Class testClass, String testMethodName) {
94         try {
95             Constructor c = testClass.getConstructor();
96             return newSingleTestMethod(testClass, testMethodName, c);
97         } catch (NoSuchMethodException e) {
98         }
99 
100         try {
101             Constructor c = testClass.getConstructor(String.class);
102             return newSingleTestMethod(testClass, testMethodName, c, testMethodName);
103         } catch (NoSuchMethodException e) {
104         }
105 
106         return null;
107     }
108 
newSingleTestMethod(Class testClass, String testMethodName, Constructor constructor, Object... args)109     private TestCase newSingleTestMethod(Class testClass, String testMethodName,
110             Constructor constructor, Object... args) {
111         try {
112             TestCase testCase = (TestCase) constructor.newInstance(args);
113             testCase.setName(testMethodName);
114             return testCase;
115         } catch (IllegalAccessException e) {
116             runFailed("Could not access test class. Class: " + testClass.getName());
117         } catch (InstantiationException e) {
118             runFailed("Could not instantiate test class. Class: " + testClass.getName());
119         } catch (IllegalArgumentException e) {
120             runFailed("Illegal argument passed to constructor. Class: " + testClass.getName());
121         } catch (InvocationTargetException e) {
122             runFailed("Constructor thew an exception. Class: " + testClass.getName());
123         }
124         return null;
125     }
126 
shouldRunSingleTestMethod(String testMethodName, Class<? extends Test> testClass)127     private boolean shouldRunSingleTestMethod(String testMethodName,
128             Class<? extends Test> testClass) {
129         return testMethodName != null && TestCase.class.isAssignableFrom(testClass);
130     }
131 
getTest(Class clazz)132     private Test getTest(Class clazz) {
133         if (TestSuiteProvider.class.isAssignableFrom(clazz)) {
134             try {
135                 TestSuiteProvider testSuiteProvider =
136                         (TestSuiteProvider) clazz.getConstructor().newInstance();
137                 return testSuiteProvider.getTestSuite();
138             } catch (InstantiationException e) {
139                 runFailed("Could not instantiate test suite provider. Class: " + clazz.getName());
140             } catch (IllegalAccessException e) {
141                 runFailed("Illegal access of test suite provider. Class: " + clazz.getName());
142             } catch (InvocationTargetException e) {
143                 runFailed("Invocation exception test suite provider. Class: " + clazz.getName());
144             } catch (NoSuchMethodException e) {
145                 runFailed("No such method on test suite provider. Class: " + clazz.getName());
146             }
147         }
148         return getTest(clazz.getName());
149     }
150 
createTestResult()151     protected TestResult createTestResult() {
152         if (mSkipExecution) {
153             return new NoExecTestResult();
154         }
155         return new TestResult();
156     }
157 
setSkipExecution(boolean skip)158     void setSkipExecution(boolean skip) {
159         mSkipExecution = skip;
160     }
161 
getTestCases()162     public List<TestCase> getTestCases() {
163         return mTestCases;
164     }
165 
getTestClassName()166     public String getTestClassName() {
167         return mTestClassName;
168     }
169 
getTestResult()170     public TestResult getTestResult() {
171         return mTestResult;
172     }
173 
runTest()174     public void runTest() {
175         runTest(createTestResult());
176     }
177 
runTest(TestResult testResult)178     public void runTest(TestResult testResult) {
179         mTestResult = testResult;
180 
181         for (TestListener testListener : mTestListeners) {
182             mTestResult.addListener(testListener);
183         }
184 
185         Context testContext = mInstrumentation == null ? mContext : mInstrumentation.getContext();
186         for (TestCase testCase : mTestCases) {
187             setContextIfAndroidTestCase(testCase, mContext, testContext);
188             setInstrumentationIfInstrumentationTestCase(testCase, mInstrumentation);
189             setPerformanceWriterIfPerformanceCollectorTestCase(testCase, mPerfWriter);
190             testCase.run(mTestResult);
191         }
192     }
193 
setContextIfAndroidTestCase(Test test, Context context, Context testContext)194     private void setContextIfAndroidTestCase(Test test, Context context, Context testContext) {
195         if (AndroidTestCase.class.isAssignableFrom(test.getClass())) {
196             ((AndroidTestCase) test).setContext(context);
197             ((AndroidTestCase) test).setTestContext(testContext);
198         }
199     }
200 
setContext(Context context)201     public void setContext(Context context) {
202         mContext = context;
203     }
204 
setInstrumentationIfInstrumentationTestCase( Test test, Instrumentation instrumentation)205     private void setInstrumentationIfInstrumentationTestCase(
206             Test test, Instrumentation instrumentation) {
207         if (InstrumentationTestCase.class.isAssignableFrom(test.getClass())) {
208             ((InstrumentationTestCase) test).injectInstrumentation(instrumentation);
209         }
210     }
211 
setPerformanceWriterIfPerformanceCollectorTestCase( Test test, PerformanceResultsWriter writer)212     private void setPerformanceWriterIfPerformanceCollectorTestCase(
213             Test test, PerformanceResultsWriter writer) {
214         if (PerformanceCollectorTestCase.class.isAssignableFrom(test.getClass())) {
215             ((PerformanceCollectorTestCase) test).setPerformanceResultsWriter(writer);
216         }
217     }
218 
setInstrumentation(Instrumentation instrumentation)219     public void setInstrumentation(Instrumentation instrumentation) {
220         mInstrumentation = instrumentation;
221     }
222 
223     /**
224      * @deprecated Incorrect spelling,
225      * use {@link #setInstrumentation(android.app.Instrumentation)} instead.
226      */
227     @Deprecated
setInstrumentaiton(Instrumentation instrumentation)228     public void setInstrumentaiton(Instrumentation instrumentation) {
229         setInstrumentation(instrumentation);
230     }
231 
232     /**
233      * {@hide} Pending approval for public API.
234      */
setPerformanceResultsWriter(PerformanceResultsWriter writer)235     public void setPerformanceResultsWriter(PerformanceResultsWriter writer) {
236         mPerfWriter = writer;
237     }
238 
239     @Override
loadSuiteClass(String suiteClassName)240     protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
241         return mContext.getClassLoader().loadClass(suiteClassName);
242     }
243 
testStarted(String testName)244     public void testStarted(String testName) {
245     }
246 
testEnded(String testName)247     public void testEnded(String testName) {
248     }
249 
testFailed(int status, Test test, Throwable t)250     public void testFailed(int status, Test test, Throwable t) {
251     }
252 
runFailed(String message)253     protected void runFailed(String message) {
254         throw new RuntimeException(message);
255     }
256 }
257