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 17package com.android.uiautomator.testrunner; 18 19import junit.framework.TestCase; 20 21import java.lang.reflect.Method; 22import java.util.ArrayList; 23import java.util.Collections; 24import java.util.List; 25 26/** 27 * A convenient class that encapsulates functions for adding test classes 28 * 29 * @hide 30 */ 31public 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