TestRequestBuilder.java revision e514756957cb44d88ceab42c53ef321e76e1368b
14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/* 24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2012 The Android Open Source Project 34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License. 64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at 74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and 144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License. 154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage com.android.test.runner; 174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.app.Instrumentation; 194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Bundle; 20d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.test.suitebuilder.annotation.LargeTest; 21d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.test.suitebuilder.annotation.MediumTest; 22d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.test.suitebuilder.annotation.SmallTest; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.test.suitebuilder.annotation.Suppress; 244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.test.runner.ClassPathScanner.ChainedClassNameFilter; 274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.test.runner.ClassPathScanner.ExcludePackageNameFilter; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.test.runner.ClassPathScanner.ExternalClassNameFilter; 29d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 30d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport org.junit.runner.Computer; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport org.junit.runner.Description; 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport org.junit.runner.Request; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport org.junit.runner.Runner; 347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslavimport org.junit.runner.manipulation.Filter; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport org.junit.runners.model.InitializationError; 36704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.IOException; 38a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.io.PrintStream; 39704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport java.lang.annotation.Annotation; 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Arrays; 4144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganovimport java.util.Collection; 424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections; 432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 4544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * Builds a {@link Request} from test classes in given apk paths, filtered on provided set of 46860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * restrictions. 474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 487bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslavpublic class TestRequestBuilder { 49a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private static final String LOG_TAG = "TestRequestBuilder"; 51d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final String LARGE_SIZE = "large"; 53a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public static final String MEDIUM_SIZE = "medium"; 544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final String SMALL_SIZE = "small"; 55b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov 56b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov private String[] mApkPaths; 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private TestLoader mTestLoader; 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private Filter mFilter = new AnnotationExclusionFilter(Suppress.class); 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private PrintStream mWriter; 604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private boolean mSkipExecution = false; 614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Filter that only runs tests whose method or class has been annotated with given filter. 644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 65d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav private static class AnnotationInclusionFilter extends Filter { 66d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 67d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav private final Class<? extends Annotation> mAnnotationClass; 684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov AnnotationInclusionFilter(Class<? extends Annotation> annotation) { 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mAnnotationClass = annotation; 714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 72a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@inheritDoc} 754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public boolean shouldRun(Description description) { 784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (description.isTest()) { 79a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return description.getAnnotation(mAnnotationClass) != null || 80a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov description.getTestClass().isAnnotationPresent(mAnnotationClass); 81a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } else { 82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // don't filter out any test classes/suites, because their methods may have correct 83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // annotation 84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return true; 85a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 862fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 87a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 882fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav /** 89a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * {@inheritDoc} 90a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */ 912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav @Override 922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public String describe() { 932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return String.format("annotation %s", mAnnotationClass.getName()); 942fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 95a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 96a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Filter out tests whose method or class has been annotated with given filter. 994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1007bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav private static class AnnotationExclusionFilter extends Filter { 1017bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 102a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final Class<? extends Annotation> mAnnotationClass; 103a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 1047bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav AnnotationExclusionFilter(Class<? extends Annotation> annotation) { 105a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mAnnotationClass = annotation; 106a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 107a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 108a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /** 1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@inheritDoc} 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 1127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public boolean shouldRun(Description description) { 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (description.getTestClass().isAnnotationPresent(mAnnotationClass) || 1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov description.getAnnotation(mAnnotationClass) != null) { 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return false; 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } else { 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return true; 1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 119a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 120a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 121a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /** 122a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * {@inheritDoc} 123a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */ 124a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 125a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public String describe() { 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return String.format("not annotation %s", mAnnotationClass.getName()); 1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1282fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public TestRequestBuilder(PrintStream writer, String... apkPaths) { 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mApkPaths = apkPaths; 1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mTestLoader = new TestLoader(writer); 1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1352fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav /** 136a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * Add a test class to be executed. All test methods in this class will be executed. 137a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * 138a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * @param className 139a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */ 140a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void addTestClass(String className) { 141a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mTestLoader.loadClass(className); 1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav /** 1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Adds a test method to run. 1464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p/> 1474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Currently only supports one test method to be run. 1484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void addTestMethod(String testClassName, String testMethodName) { 1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Class<?> clazz = mTestLoader.loadClass(testClassName); 1512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (clazz != null) { 152a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mFilter = mFilter.intersect(Filter.matchMethodDescription( 153a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Description.createTestDescription(clazz, testMethodName))); 154a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 155a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 156a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 157a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /** 1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Run only tests with given size 1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param testSize 1602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav */ 1618c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov public void addTestSizeFilter(String testSize) { 1628c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov if (SMALL_SIZE.equals(testSize)) { 1638c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov mFilter = mFilter.intersect(new AnnotationInclusionFilter(SmallTest.class)); 1648c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } else if (MEDIUM_SIZE.equals(testSize)) { 1658c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov mFilter = mFilter.intersect(new AnnotationInclusionFilter(MediumTest.class)); 1668c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } else if (LARGE_SIZE.equals(testSize)) { 1672fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mFilter = mFilter.intersect(new AnnotationInclusionFilter(LargeTest.class)); 1688c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } else { 1698c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov Log.e(LOG_TAG, String.format("Unrecognized test size '%s'", testSize)); 1702fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 1718c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } 1722fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 1738c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov /** 1748c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov * Only run tests annotated with given annotation class. 1758c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov * 1762fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav * @param annotation the full class name of annotation 1774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void addAnnotationInclusionFilter(String annotation) { 1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Class<? extends Annotation> annotationClass = loadAnnotationClass(annotation); 1804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (annotationClass != null) { 1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mFilter = mFilter.intersect(new AnnotationInclusionFilter(annotationClass)); 182860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 183860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 184860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov 185860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov /** 186860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * Skip tests annotated with given annotation class. 187860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * 188860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * @param notAnnotation the full class name of annotation 189860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov */ 190860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov public void addAnnotationExclusionFilter(String notAnnotation) { 191860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov Class<? extends Annotation> annotationClass = loadAnnotationClass(notAnnotation); 192860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov if (annotationClass != null) { 193860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov mFilter = mFilter.intersect(new AnnotationExclusionFilter(annotationClass)); 194860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 195860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 196860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov 19744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov /** 198d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * Build a request that will generate test started and test ended events, but will skip actual 199d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * test execution. 200d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav */ 201d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav public void setSkipExecution(boolean b) { 202d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav mSkipExecution = b; 203d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 204d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav 205d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav /** 206d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * Builds the {@link TestRequest} based on current contents of added classes and methods. 207d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * <p/> 208d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * If no classes have been explicitly added, will scan the classpath for all tests. 209d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * 210d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav */ 211d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav public TestRequest build(Instrumentation instr, Bundle bundle) { 212d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav if (mTestLoader.isEmpty()) { 21344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov // no class restrictions have been specified. Load all classes 21444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov loadClassesFromClassPath(); 21544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 21644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 21744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Request request = classes(instr, bundle, mSkipExecution, new Computer(), 21844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov mTestLoader.getLoadedClasses().toArray(new Class[0])); 21944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return new TestRequest(mTestLoader.getLoadFailures(), request.filterWith(mFilter)); 22044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 22144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 22244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov /** 22344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * Create a <code>Request</code> that, when processed, will run all the tests 22444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * in a set of classes. 22544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * 22644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @param instr the {@link Instrumentation} to inject into any tests that require it 22744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @param bundle the {@link Bundle} of command line args to inject into any tests that require 22844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * it 22944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @param computer Helps construct Runners from classes 23044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @param classes the classes containing the tests 23144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @return a <code>Request</code> that will cause all tests in the classes to be run 23244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov */ 23344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov private static Request classes(Instrumentation instr, Bundle bundle, boolean skipExecution, 23444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Computer computer, Class<?>... classes) { 23544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 23644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov AndroidRunnerBuilder builder = new AndroidRunnerBuilder(true, instr, bundle, 23744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov skipExecution); 23844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Runner suite = computer.getSuite(builder, classes); 23944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return Request.runner(suite); 24044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } catch (InitializationError e) { 24144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov throw new RuntimeException( 24244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov "Suite constructor, called as above, should always complete"); 24344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 24444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 24544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 24644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov private void loadClassesFromClassPath() { 24744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Collection<String> classNames = getClassNamesFromClassPath(); 24844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov for (String className : classNames) { 24944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov mTestLoader.loadIfTest(className); 25044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 25144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 25244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 25344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov private Collection<String> getClassNamesFromClassPath() { 25444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Log.i(LOG_TAG, String.format("Scanning classpath to find tests in apks %s", 25544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Arrays.toString(mApkPaths))); 25644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov ClassPathScanner scanner = new ClassPathScanner(mApkPaths); 25744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 25844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov // exclude inner classes, and classes from junit and this lib namespace 25944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return scanner.getClassPathEntries(new ChainedClassNameFilter( 26044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov new ExcludePackageNameFilter("junit"), 26144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov new ExcludePackageNameFilter("org.junit"), 26244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov new ExcludePackageNameFilter("org.hamcrest"), 26344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov new ExternalClassNameFilter(), 26444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov new ExcludePackageNameFilter("com.android.test.runner.junit3"))); 26544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } catch (IOException e) { 26644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov mWriter.println("failed to scan classes"); 26744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Log.e(LOG_TAG, "Failed to scan classes", e); 26844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 26944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return Collections.emptyList(); 27044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 27144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 27244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov /** 27344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * Factory method for {@link ClassPathScanner}. 27444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * <p/> 27544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * Exposed so unit tests can mock. 276d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov */ 27744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov ClassPathScanner createClassPathScanner(String... apkPaths) { 27844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return new ClassPathScanner(apkPaths); 27944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 28044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 28144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov @SuppressWarnings("unchecked") 28244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov private Class<? extends Annotation> loadAnnotationClass(String className) { 28344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 284d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov Class<?> clazz = Class.forName(className); 285d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov return (Class<? extends Annotation>)clazz; 286d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } catch (ClassNotFoundException e) { 287d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov Log.e(LOG_TAG, String.format("Could not find annotation class: %s", className)); 288d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } catch (ClassCastException e) { 289d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov Log.e(LOG_TAG, String.format("Class %s is not an annotation", className)); 290d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 291d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov return null; 292d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 293d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov} 294d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov