1 /* 2 * Copyright (C) 2016 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 17 package vogar.target.junit.junit3; 18 19 import java.lang.annotation.Annotation; 20 import java.lang.reflect.Method; 21 import java.lang.reflect.Modifier; 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.Comparator; 25 import java.util.List; 26 import junit.framework.AssertionFailedError; 27 import junit.framework.Test; 28 import junit.framework.TestCase; 29 import junit.framework.TestSuite; 30 31 /** 32 * Transforms a {@link TestCase} based test into another representation. 33 * 34 * <p>This delegates the work of constructing tests and a suite (collection of tests) to a 35 * {@link TestCaseFactory}. 36 * 37 * <p>Separates the scanning of the {@link TestCase} derived class from the construction of the 38 * objects representing the 'suite' and 'test' allowing it to be more easily reused. 39 * 40 * @param <S> the type of the 'suite' component 41 * @param <T> the type of the 'test' component 42 */ 43 public class TestCaseTransformer<S,T> { 44 45 private final TestCaseFactory<S, T> factory; 46 47 private final Comparator<? super T> comparator; 48 TestCaseTransformer(TestCaseFactory<S, T> factory, Comparator<? super T> comparator)49 public TestCaseTransformer(TestCaseFactory<S, T> factory, Comparator<? super T> comparator) { 50 this.comparator = comparator; 51 this.factory = factory; 52 } 53 createSuite(Class<? extends TestCase> testClass)54 public S createSuite(Class<? extends TestCase> testClass) { 55 List<T> tests = testsFromTestCase(testClass); 56 return factory.createSuite(testClass, tests); 57 } 58 createTest( Class<? extends TestCase> testClass, String methodName, Annotation[] annotations)59 private T createTest( 60 Class<? extends TestCase> testClass, String methodName, Annotation[] annotations) { 61 return factory.createTest(testClass, methodName, annotations); 62 } 63 createWarning(Class<? extends Test> testClass, String name, Throwable throwable)64 private T createWarning(Class<? extends Test> testClass, String name, Throwable throwable) { 65 return factory.createFailingTest(testClass, name, throwable); 66 } 67 testsFromTestCase(final Class<? extends TestCase> testClass)68 private List<T> testsFromTestCase(final Class<? extends TestCase> testClass) { 69 List<T> tests = new ArrayList<>(); 70 71 // Check as much as possible in advance to avoid generating multiple error messages for the 72 // same failure. 73 if (factory.eagerClassValidation()) { 74 try { 75 validateTestClass(testClass); 76 } catch (AssertionFailedError e) { 77 tests.add(createWarning(testClass, "warning", e)); 78 return tests; 79 } 80 } 81 82 for (Method method : testClass.getMethods()) { 83 if (!isTestMethod(method)) { 84 continue; 85 } 86 87 tests.add(createTest(testClass, method.getName(), method.getAnnotations())); 88 } 89 90 Collections.sort(tests, comparator); 91 92 return tests; 93 } 94 isTestMethod(Method m)95 private static boolean isTestMethod(Method m) { 96 return m.getParameterTypes().length == 0 97 && m.getName().startsWith("test") 98 && m.getReturnType().equals(Void.TYPE); 99 } 100 validateTestClass(Class<?> testClass)101 public static void validateTestClass(Class<?> testClass) { 102 try { 103 TestSuite.getTestConstructor(testClass); 104 } catch (NoSuchMethodException e) { 105 throw new AssertionFailedError( 106 "Class " + testClass.getName() 107 + " has no public constructor TestCase(String name) or TestCase()"); 108 } 109 110 if (!Modifier.isPublic(testClass.getModifiers())) { 111 throw new AssertionFailedError("Class " + testClass.getName() + " is not public"); 112 } 113 } 114 } 115