Home | History | Annotate | Download | only in testrunner
      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 
     17 package com.android.uiautomator.testrunner;
     18 
     19 import junit.framework.TestCase;
     20 
     21 import java.lang.reflect.Method;
     22 import java.util.ArrayList;
     23 import java.util.Collections;
     24 import java.util.List;
     25 
     26 /**
     27  * A convenient class that encapsulates functions for adding test classes
     28  *
     29  * @hide
     30  */
     31 public class TestCaseCollector {
     32 
     33     private ClassLoader mClassLoader;
     34     private List<TestCase> mTestCases;
     35     private TestCaseFilter mFilter;
     36 
     37     public TestCaseCollector(ClassLoader classLoader, TestCaseFilter filter) {
     38         mClassLoader = classLoader;
     39         mTestCases = new ArrayList<TestCase>();
     40         mFilter = filter;
     41     }
     42 
     43     /**
     44      * Adds classes to test by providing a list of class names in string
     45      *
     46      * The class name may be in "<class name>#<method name>" format
     47      *
     48      * @param classNames class must be subclass of {@link UiAutomatorTestCase}
     49      * @throws ClassNotFoundException
     50      */
     51     public void addTestClasses(List<String> classNames) throws ClassNotFoundException {
     52         for (String className : classNames) {
     53             addTestClass(className);
     54         }
     55     }
     56 
     57     /**
     58      * Adds class to test by providing class name in string.
     59      *
     60      * The class name may be in "<class name>#<method name>" format
     61      *
     62      * @param className classes must be subclass of {@link UiAutomatorTestCase}
     63      * @throws ClassNotFoundException
     64      */
     65     public void addTestClass(String className) throws ClassNotFoundException {
     66         int hashPos = className.indexOf('#');
     67         String methodName = null;
     68         if (hashPos != -1) {
     69             methodName = className.substring(hashPos + 1);
     70             className = className.substring(0, hashPos);
     71         }
     72         addTestClass(className, methodName);
     73     }
     74 
     75     /**
     76      * Adds class to test by providing class name and method name in separate strings
     77      *
     78      * @param className class must be subclass of {@link UiAutomatorTestCase}
     79      * @param methodName may be null, in which case all "public void testNNN(void)" functions
     80      *                   will be added
     81      * @throws ClassNotFoundException
     82      */
     83     public void addTestClass(String className, String methodName) throws ClassNotFoundException {
     84         Class<?> clazz = mClassLoader.loadClass(className);
     85         if (methodName != null) {
     86             addSingleTestMethod(clazz, methodName);
     87         } else {
     88             Method[] methods = clazz.getMethods();
     89             for (Method method : methods) {
     90                 if (mFilter.accept(method)) {
     91                     addSingleTestMethod(clazz, method.getName());
     92                 }
     93             }
     94         }
     95     }
     96 
     97     /**
     98      * Gets the list of added test cases so far
     99      * @return a list of {@link TestCase}
    100      */
    101     public List<TestCase> getTestCases() {
    102         return Collections.unmodifiableList(mTestCases);
    103     }
    104 
    105     protected void addSingleTestMethod(Class<?> clazz, String method) {
    106         if (!(mFilter.accept(clazz))) {
    107             throw new RuntimeException("Test class must be derived from UiAutomatorTestCase");
    108         }
    109         try {
    110             TestCase testCase = (TestCase) clazz.newInstance();
    111             testCase.setName(method);
    112             mTestCases.add(testCase);
    113         } catch (InstantiationException e) {
    114             mTestCases.add(error(clazz, "InstantiationException: could not instantiate " +
    115                     "test class. Class: " + clazz.getName()));
    116         } catch (IllegalAccessException e) {
    117             mTestCases.add(error(clazz, "IllegalAccessException: could not instantiate " +
    118                     "test class. Class: " + clazz.getName()));
    119         }
    120     }
    121 
    122     private UiAutomatorTestCase error(Class<?> clazz, final String message) {
    123         UiAutomatorTestCase warning = new UiAutomatorTestCase() {
    124             protected void runTest() {
    125                 fail(message);
    126             }
    127         };
    128 
    129         warning.setName(clazz.getName());
    130         return warning;
    131     }
    132 
    133     /**
    134      * Determine if a class and its method should be accepted into test suite
    135      *
    136      */
    137     public interface TestCaseFilter {
    138 
    139         /**
    140          * Determine that based on the method signature, if it can be accepted
    141          * @param method
    142          */
    143         public boolean accept(Method method);
    144 
    145         /**
    146          * Determine that based on the class type, if it can be accepted
    147          * @param clazz
    148          * @return
    149          */
    150         public boolean accept(Class<?> clazz);
    151     }
    152 }
    153