1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/* 2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project 3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License. 6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at 7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software 11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and 14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License. 15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.testrunner; 18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport junit.framework.TestCase; 20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.lang.reflect.Method; 22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.ArrayList; 23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.Collections; 24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport java.util.List; 25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/** 27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenient class that encapsulates functions for adding test classes 28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 29ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu * @hide 30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class TestCaseCollector { 32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private ClassLoader mClassLoader; 34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private List<TestCase> mTestCases; 35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private TestCaseFilter mFilter; 36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public TestCaseCollector(ClassLoader classLoader, TestCaseFilter filter) { 38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mClassLoader = classLoader; 39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestCases = new ArrayList<TestCase>(); 40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mFilter = filter; 41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Adds classes to test by providing a list of class names in string 45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The class name may be in "<class name>#<method name>" format 47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param classNames class must be subclass of {@link UiAutomatorTestCase} 49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws ClassNotFoundException 50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void addTestClasses(List<String> classNames) throws ClassNotFoundException { 52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (String className : classNames) { 53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu addTestClass(className); 54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 58e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Adds class to test by providing class name in string. 59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 60e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The class name may be in "<class name>#<method name>" format 61e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 621893caed0ad4e73b0676f206282d490c2d345316Thanh Le * @param className classes must be subclass of {@link UiAutomatorTestCase} 63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws ClassNotFoundException 64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void addTestClass(String className) throws ClassNotFoundException { 66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int hashPos = className.indexOf('#'); 67e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String methodName = null; 68e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (hashPos != -1) { 69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu methodName = className.substring(hashPos + 1); 70e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu className = className.substring(0, hashPos); 71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu addTestClass(className, methodName); 73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Adds class to test by providing class name and method name in separate strings 77e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param className class must be subclass of {@link UiAutomatorTestCase} 79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param methodName may be null, in which case all "public void testNNN(void)" functions 80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * will be added 81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws ClassNotFoundException 82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void addTestClass(String className, String methodName) throws ClassNotFoundException { 84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Class<?> clazz = mClassLoader.loadClass(className); 85e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (methodName != null) { 86e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu addSingleTestMethod(clazz, methodName); 87e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 88e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Method[] methods = clazz.getMethods(); 89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (Method method : methods) { 90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (mFilter.accept(method)) { 91e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu addSingleTestMethod(clazz, method.getName()); 92e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Gets the list of added test cases so far 991893caed0ad4e73b0676f206282d490c2d345316Thanh Le * @return a list of {@link TestCase} 100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 101e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public List<TestCase> getTestCases() { 102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return Collections.unmodifiableList(mTestCases); 103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected void addSingleTestMethod(Class<?> clazz, String method) { 106e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (!(mFilter.accept(clazz))) { 107e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new RuntimeException("Test class must be derived from UiAutomatorTestCase"); 108e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu try { 110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu TestCase testCase = (TestCase) clazz.newInstance(); 111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu testCase.setName(method); 112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mTestCases.add(testCase); 113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } catch (InstantiationException e) { 114bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine mTestCases.add(error(clazz, "InstantiationException: could not instantiate " + 115bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine "test class. Class: " + clazz.getName())); 116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } catch (IllegalAccessException e) { 117bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine mTestCases.add(error(clazz, "IllegalAccessException: could not instantiate " + 118bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine "test class. Class: " + clazz.getName())); 119e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 120bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine } 121bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine 122bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine private UiAutomatorTestCase error(Class<?> clazz, final String message) { 123bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine UiAutomatorTestCase warning = new UiAutomatorTestCase() { 124bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine protected void runTest() { 125bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine fail(message); 126bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine } 127bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine }; 128e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 129bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine warning.setName(clazz.getName()); 130bc81b387c8d6c464f9b2a0f4f6f3224270466181Maxim Siniavine return warning; 131e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 132e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 133e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 134e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Determine if a class and its method should be accepted into test suite 135e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 137e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public interface TestCaseFilter { 138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 139e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 140e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Determine that based on the method signature, if it can be accepted 141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param method 142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean accept(Method method); 144e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 145e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 146e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Determine that based on the class type, if it can be accepted 147e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param clazz 148e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return 149e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 150e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean accept(Class<?> clazz); 151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 152e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu} 153