1bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot/* 2bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * Copyright (C) 2012 The Android Open Source Project 3bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * 4bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * Licensed under the Apache License, Version 2.0 (the "License"); 5bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * you may not use this file except in compliance with the License. 6bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * You may obtain a copy of the License at 7bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * 8bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * http://www.apache.org/licenses/LICENSE-2.0 9bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * 10bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * Unless required by applicable law or agreed to in writing, software 11bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * distributed under the License is distributed on an "AS IS" BASIS, 12bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * See the License for the specific language governing permissions and 14bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * limitations under the License. 15bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot */ 16bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotpackage com.android.test.runner; 17bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 1853196f43b44ff02da07c243798168d7e5614ec34Brett Chabotimport android.app.Instrumentation; 195e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabotimport android.test.suitebuilder.annotation.LargeTest; 205e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabotimport android.test.suitebuilder.annotation.MediumTest; 215e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabotimport android.test.suitebuilder.annotation.SmallTest; 2216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabotimport android.test.suitebuilder.annotation.Suppress; 23bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport android.util.Log; 24bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 25bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport com.android.test.runner.ClassPathScanner.ChainedClassNameFilter; 26bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport com.android.test.runner.ClassPathScanner.ExcludePackageNameFilter; 27bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport com.android.test.runner.ClassPathScanner.ExternalClassNameFilter; 28bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 2953196f43b44ff02da07c243798168d7e5614ec34Brett Chabotimport org.junit.runner.Computer; 300e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabotimport org.junit.runner.Description; 31bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport org.junit.runner.Request; 3253196f43b44ff02da07c243798168d7e5614ec34Brett Chabotimport org.junit.runner.Runner; 33bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport org.junit.runner.manipulation.Filter; 3453196f43b44ff02da07c243798168d7e5614ec34Brett Chabotimport org.junit.runners.model.InitializationError; 35bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 36bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport java.io.IOException; 37bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport java.io.PrintStream; 385e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabotimport java.lang.annotation.Annotation; 39bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport java.util.Arrays; 40bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport java.util.Collection; 41bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotimport java.util.Collections; 42bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 43bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot/** 44bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * Builds a {@link Request} from test classes in given apk paths, filtered on provided set of 45bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * restrictions. 46bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot */ 47bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabotpublic class TestRequestBuilder { 48bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 49bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot private static final String LOG_TAG = "TestRequestBuilder"; 50bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 51bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot private String[] mApkPaths; 520e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot private TestLoader mTestLoader; 5316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot private Filter mFilter = new AnnotationExclusionFilter(Suppress.class); 540e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot private PrintStream mWriter; 553604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot private boolean mSkipExecution = false; 560e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot 575e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot /** 585e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot * Filter that only runs tests whose method or class has been annotated with given filter. 595e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot */ 605e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot private static class AnnotationInclusionFilter extends Filter { 615e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot 625e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot private final Class<? extends Annotation> mAnnotationClass; 635e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot 645e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot AnnotationInclusionFilter(Class<? extends Annotation> annotation) { 655e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot mAnnotationClass = annotation; 665e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 675e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot 685e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot /** 695e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot * {@inheritDoc} 705e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot */ 715e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot @Override 725e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot public boolean shouldRun(Description description) { 735e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot if (description.isTest()) { 745e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot return description.getAnnotation(mAnnotationClass) != null || 755e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot description.getTestClass().isAnnotationPresent(mAnnotationClass); 765e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } else { 775e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot // don't filter out any test classes/suites, because their methods may have correct 785e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot // annotation 795e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot return true; 805e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 815e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 825e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot 835e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot /** 845e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot * {@inheritDoc} 855e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot */ 865e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot @Override 875e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot public String describe() { 885e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot return String.format("annotation %s", mAnnotationClass.getName()); 895e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 905e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 915e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot 9216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot /** 9316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * Filter out tests whose method or class has been annotated with given filter. 9416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot */ 9516522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot private static class AnnotationExclusionFilter extends Filter { 9616522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 9716522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot private final Class<? extends Annotation> mAnnotationClass; 9816522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 9916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot AnnotationExclusionFilter(Class<? extends Annotation> annotation) { 10016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot mAnnotationClass = annotation; 10116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 10216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 10316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot /** 10416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * {@inheritDoc} 10516522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot */ 10616522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot @Override 10716522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot public boolean shouldRun(Description description) { 10816522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot if (description.getTestClass().isAnnotationPresent(mAnnotationClass) || 10916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot description.getAnnotation(mAnnotationClass) != null) { 11016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot return false; 11116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } else { 11216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot return true; 11316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 11416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 11516522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 11616522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot /** 11716522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * {@inheritDoc} 11816522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot */ 11916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot @Override 12016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot public String describe() { 12116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot return String.format("not annotation %s", mAnnotationClass.getName()); 12216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 12316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 12416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 1250e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot public TestRequestBuilder(PrintStream writer, String... apkPaths) { 126bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot mApkPaths = apkPaths; 1270e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot mTestLoader = new TestLoader(writer); 128bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } 129bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 130bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot /** 1310e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * Add a test class to be executed. All test methods in this class will be executed. 132bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot * 1330e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * @param className 134bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot */ 135bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot public void addTestClass(String className) { 1360e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot mTestLoader.loadClass(className); 137bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } 138bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 1390e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot /** 1400e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * Adds a test method to run. 1410e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * <p/> 1420e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * Currently only supports one test method to be run. 1430e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot */ 1440e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot public void addTestMethod(String testClassName, String testMethodName) { 1450e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot Class<?> clazz = mTestLoader.loadClass(testClassName); 1460e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot if (clazz != null) { 1470e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot mFilter = mFilter.intersect(Filter.matchMethodDescription( 1480e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot Description.createTestDescription(clazz, testMethodName))); 1490e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot } 1500e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot } 1510e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot 1520e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot /** 1535e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot * Run only tests with given size 1545e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot * @param testSize 1555e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot */ 1565e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot public void addTestSizeFilter(String testSize) { 1575e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot if ("small".equals(testSize)) { 1585e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot mFilter = mFilter.intersect(new AnnotationInclusionFilter(SmallTest.class)); 1595e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } else if ("medium".equals(testSize)) { 1605e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot mFilter = mFilter.intersect(new AnnotationInclusionFilter(MediumTest.class)); 1615e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } else if ("large".equals(testSize)) { 1625e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot mFilter = mFilter.intersect(new AnnotationInclusionFilter(LargeTest.class)); 1635e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } else { 1645e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot Log.e(LOG_TAG, String.format("Unrecognized test size '%s'", testSize)); 1655e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 1665e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot } 1675e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot 1685e6ca275201fea0fd0316fb15bc7d0248e224b2cBrett Chabot /** 16916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * Only run tests annotated with given annotation class. 17016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * 17116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * @param annotation the full class name of annotation 17216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot */ 17316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot public void addAnnotationInclusionFilter(String annotation) { 17416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot Class<? extends Annotation> annotationClass = loadAnnotationClass(annotation); 17516522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot if (annotationClass != null) { 17616522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot mFilter = mFilter.intersect(new AnnotationInclusionFilter(annotationClass)); 17716522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 17816522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 17916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 18016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot /** 18116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * Skip tests annotated with given annotation class. 18216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * 18316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot * @param notAnnotation the full class name of annotation 18416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot */ 18516522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot public void addAnnotationExclusionFilter(String notAnnotation) { 18616522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot Class<? extends Annotation> annotationClass = loadAnnotationClass(notAnnotation); 18716522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot if (annotationClass != null) { 18816522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot mFilter = mFilter.intersect(new AnnotationExclusionFilter(annotationClass)); 18916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 19016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 19116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 19216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot /** 1933604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot * Build a request that will generate test started and test ended events, but will skip actual 1943604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot * test execution. 1953604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot */ 1963604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot public void setSkipExecution(boolean b) { 1973604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot mSkipExecution = b; 1983604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot } 1993604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot 2003604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot /** 2010e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * Builds the {@link TestRequest} based on current contents of added classes and methods. 2020e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * <p/> 2030e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * If no classes have been explicitly added, will scan the classpath for all tests. 2040e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * 2050e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot */ 206cebe48ef03abf67e1957a8df4574c79191a5c482Brett Chabot public TestRequest build(Instrumentation instr) { 2070e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot if (mTestLoader.isEmpty()) { 2080e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot // no class restrictions have been specified. Load all classes 2090e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot loadClassesFromClassPath(); 210bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } 211bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 2123604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot Request request = classes(instr, mSkipExecution, new Computer(), 2133604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot mTestLoader.getLoadedClasses().toArray(new Class[0])); 2140e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot return new TestRequest(mTestLoader.getLoadFailures(), request.filterWith(mFilter)); 215bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } 216bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot 21753196f43b44ff02da07c243798168d7e5614ec34Brett Chabot /** 21853196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * Create a <code>Request</code> that, when processed, will run all the tests 21953196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * in a set of classes. 22053196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * 22153196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * @param instr the {@link Instrumentation} to inject into any tests that require it 22253196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * @param computer Helps construct Runners from classes 22353196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * @param classes the classes containing the tests 22453196f43b44ff02da07c243798168d7e5614ec34Brett Chabot * @return a <code>Request</code> that will cause all tests in the classes to be run 22553196f43b44ff02da07c243798168d7e5614ec34Brett Chabot */ 2263604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot private static Request classes(Instrumentation instr, boolean skipExecution, 2273604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot Computer computer, Class<?>... classes) { 22853196f43b44ff02da07c243798168d7e5614ec34Brett Chabot try { 2293604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot AndroidRunnerBuilder builder = new AndroidRunnerBuilder(true, instr, skipExecution); 23053196f43b44ff02da07c243798168d7e5614ec34Brett Chabot Runner suite = computer.getSuite(builder, classes); 23153196f43b44ff02da07c243798168d7e5614ec34Brett Chabot return Request.runner(suite); 23253196f43b44ff02da07c243798168d7e5614ec34Brett Chabot } catch (InitializationError e) { 23353196f43b44ff02da07c243798168d7e5614ec34Brett Chabot throw new RuntimeException( 23453196f43b44ff02da07c243798168d7e5614ec34Brett Chabot "Suite constructor, called as above, should always complete"); 23553196f43b44ff02da07c243798168d7e5614ec34Brett Chabot } 23653196f43b44ff02da07c243798168d7e5614ec34Brett Chabot } 23753196f43b44ff02da07c243798168d7e5614ec34Brett Chabot 2380e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot private void loadClassesFromClassPath() { 2390e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot Collection<String> classNames = getClassNamesFromClassPath(); 2400e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot for (String className : classNames) { 2410e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot mTestLoader.loadIfTest(className); 2420e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot } 2430e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot } 2440e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot 2450e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot private Collection<String> getClassNamesFromClassPath() { 246bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot Log.i(LOG_TAG, String.format("Scanning classpath to find tests in apks %s", 247bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot Arrays.toString(mApkPaths))); 248bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot ClassPathScanner scanner = new ClassPathScanner(mApkPaths); 249bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot try { 25053196f43b44ff02da07c243798168d7e5614ec34Brett Chabot // exclude inner classes, and classes from junit and this lib namespace 251bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot return scanner.getClassPathEntries(new ChainedClassNameFilter( 252bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot new ExcludePackageNameFilter("junit"), 253bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot new ExcludePackageNameFilter("org.junit"), 254bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot new ExcludePackageNameFilter("org.hamcrest"), 2553604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot new ExternalClassNameFilter(), 2563604db5bcd124dfd1396fb51434d3f4337690cffBrett Chabot new ExcludePackageNameFilter("com.android.test.runner.junit3"))); 257bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } catch (IOException e) { 2580e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot mWriter.println("failed to scan classes"); 259bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot Log.e(LOG_TAG, "Failed to scan classes", e); 260bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } 261bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot return Collections.emptyList(); 262bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot } 2630e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot 2640e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot /** 2650e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * Factory method for {@link ClassPathScanner}. 2660e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * <p/> 2670e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot * Exposed so unit tests can mock. 2680e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot */ 2690e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot ClassPathScanner createClassPathScanner(String... apkPaths) { 2700e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot return new ClassPathScanner(apkPaths); 2710e1d66fcd74344182e3bfca913744b1a66e7a188Brett Chabot } 27216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot 27316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot @SuppressWarnings("unchecked") 27416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot private Class<? extends Annotation> loadAnnotationClass(String className) { 27516522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot try { 27616522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot Class<?> clazz = Class.forName(className); 27716522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot return (Class<? extends Annotation>)clazz; 27816522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } catch (ClassNotFoundException e) { 27916522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot Log.e(LOG_TAG, String.format("Could not find annotation class: %s", className)); 28016522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } catch (ClassCastException e) { 28116522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot Log.e(LOG_TAG, String.format("Class %s is not an annotation", className)); 28216522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 28316522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot return null; 28416522ab7fbaaa627c2c51cfc1339c2248af6df1bBrett Chabot } 285bb23e68d4dc19a37df318b8d169e3dfd0dd1c20eBrett Chabot} 286