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