118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/* 218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Copyright (C) 2012 The Android Open Source Project 318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * you may not use this file except in compliance with the License. 618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * You may obtain a copy of the License at 718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 1018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Unless required by applicable law or agreed to in writing, software 1118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 1218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * See the License for the specific language governing permissions and 1418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * limitations under the License. 1518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 1618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 1718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupackage com.android.uiautomator.testrunner; 1818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 1918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport junit.framework.TestCase; 2018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 2118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.lang.reflect.Method; 2218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.ArrayList; 2318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.Collections; 2418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhuimport java.util.List; 2518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 2618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu/** 2718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * A convenient class that encapsulates functions for adding test classes 2818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 2918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @hide 3018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 3118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhupublic class TestCaseCollector { 3218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 3318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private ClassLoader mClassLoader; 3418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private List<TestCase> mTestCases; 3518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private TestCaseFilter mFilter; 3618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 3718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public TestCaseCollector(ClassLoader classLoader, TestCaseFilter filter) { 3818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mClassLoader = classLoader; 3918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestCases = new ArrayList<TestCase>(); 4018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mFilter = filter; 4118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 4218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 4318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 4418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Adds classes to test by providing a list of class names in string 4518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 4618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * The class name may be in "<class name>#<method name>" format 4718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 4818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param classNames class must be subclass of {@link UiAutomatorTestCase} 4918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @throws ClassNotFoundException 5018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 5118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void addTestClasses(List<String> classNames) throws ClassNotFoundException { 5218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu for (String className : classNames) { 5318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu addTestClass(className); 5418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 5518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 5618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 5718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 5818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Adds class to test by providing class name in string. 5918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 6018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * The class name may be in "<class name>#<method name>" format 6118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 6218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param className classes must be subclass of {@link UiAutomatorTestCase} 6318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @throws ClassNotFoundException 6418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 6518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void addTestClass(String className) throws ClassNotFoundException { 6618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu int hashPos = className.indexOf('#'); 6718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu String methodName = null; 6818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (hashPos != -1) { 6918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu methodName = className.substring(hashPos + 1); 7018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu className = className.substring(0, hashPos); 7118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 7218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu addTestClass(className, methodName); 7318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 7418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 7518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 7618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Adds class to test by providing class name and method name in separate strings 7718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 7818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param className class must be subclass of {@link UiAutomatorTestCase} 7918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param methodName may be null, in which case all "public void testNNN(void)" functions 8018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * will be added 8118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @throws ClassNotFoundException 8218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 8318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public void addTestClass(String className, String methodName) throws ClassNotFoundException { 8418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Class<?> clazz = mClassLoader.loadClass(className); 8518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (methodName != null) { 8618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu addSingleTestMethod(clazz, methodName); 8718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } else { 8818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu Method[] methods = clazz.getMethods(); 8918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu for (Method method : methods) { 9018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (mFilter.accept(method)) { 9118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu addSingleTestMethod(clazz, method.getName()); 9218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 9318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 9418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 9518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 9618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 9718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 9818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Gets the list of added test cases so far 9918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @return a list of {@link TestCase} 10018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 10118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public List<TestCase> getTestCases() { 10218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu return Collections.unmodifiableList(mTestCases); 10318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 10418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 10518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected void addSingleTestMethod(Class<?> clazz, String method) { 10618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu if (!(mFilter.accept(clazz))) { 10718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu throw new RuntimeException("Test class must be derived from UiAutomatorTestCase"); 10818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 10918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu try { 11018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu TestCase testCase = (TestCase) clazz.newInstance(); 11118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu testCase.setName(method); 11218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestCases.add(testCase); 11318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } catch (InstantiationException e) { 11418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestCases.add(error(clazz, "InstantiationException: could not instantiate " + 11518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu "test class. Class: " + clazz.getName())); 11618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } catch (IllegalAccessException e) { 11718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu mTestCases.add(error(clazz, "IllegalAccessException: could not instantiate " + 11818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu "test class. Class: " + clazz.getName())); 11918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 12018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 12118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 12218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu private UiAutomatorTestCase error(Class<?> clazz, final String message) { 12318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu UiAutomatorTestCase warning = new UiAutomatorTestCase() { 12418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu protected void runTest() { 12518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu fail(message); 12618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 12718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu }; 12818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 12918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu warning.setName(clazz.getName()); 13018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu return warning; 13118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 13218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 13318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 13418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Determine if a class and its method should be accepted into test suite 13518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * 13618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 13718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public interface TestCaseFilter { 13818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 13918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 14018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Determine that based on the method signature, if it can be accepted 14118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param method 14218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 14318b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public boolean accept(Method method); 14418b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu 14518b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu /** 14618b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * Determine that based on the class type, if it can be accepted 14718b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @param clazz 14818b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu * @return 14918b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu */ 15018b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu public boolean accept(Class<?> clazz); 15118b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu } 15218b892c723e812a7e111f102d2b0c0782b116bb6Guang Zhu} 153