| package org.apache.maven.surefire.testng; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.File; |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.maven.surefire.cli.CommandLineOption; |
| import org.apache.maven.surefire.report.RunListener; |
| import org.apache.maven.surefire.testset.TestListResolver; |
| import org.apache.maven.surefire.testset.TestSetFailedException; |
| import org.apache.maven.surefire.util.TestsToRun; |
| |
| import static org.apache.maven.surefire.testng.TestNGExecutor.run; |
| import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; |
| |
| /** |
| * Test suite for TestNG based on a directory of Java test classes. Can also execute JUnit tests. |
| * |
| * @author <a href="mailto:brett@apache.org">Brett Porter</a> |
| * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a> |
| */ |
| final class TestNGDirectoryTestSuite |
| extends TestSuite |
| { |
| private final Map<String, String> options; |
| |
| private final Map<String, String> junitOptions; |
| |
| private final File testSourceDirectory; |
| |
| private final File reportsDirectory; |
| |
| private final TestListResolver methodFilter; |
| |
| private final Class<?> junitTestClass; |
| |
| private final Class<? extends Annotation> junitRunWithAnnotation; |
| |
| private final Class<? extends Annotation> junitTestAnnotation; |
| |
| private final List<CommandLineOption> mainCliOptions; |
| |
| private final int skipAfterFailureCount; |
| |
| TestNGDirectoryTestSuite( File testSourceDirectory, Map<String, String> confOptions, File reportsDirectory, |
| TestListResolver methodFilter, List<CommandLineOption> mainCliOptions, |
| int skipAfterFailureCount ) |
| { |
| this.options = confOptions; |
| this.testSourceDirectory = testSourceDirectory; |
| this.reportsDirectory = reportsDirectory; |
| this.methodFilter = methodFilter; |
| this.junitTestClass = findJUnitTestClass(); |
| this.junitRunWithAnnotation = findJUnitRunWithAnnotation(); |
| this.junitTestAnnotation = findJUnitTestAnnotation(); |
| this.junitOptions = createJUnitOptions(); |
| this.mainCliOptions = mainCliOptions; |
| this.skipAfterFailureCount = skipAfterFailureCount; |
| } |
| |
| void execute( TestsToRun testsToRun, RunListener reporterManager ) |
| throws TestSetFailedException |
| { |
| if ( !testsToRun.allowEagerReading() ) |
| { |
| executeLazy( testsToRun, reporterManager ); |
| } |
| else if ( testsToRun.containsAtLeast( 2 ) ) |
| { |
| executeMulti( testsToRun, reporterManager ); |
| } |
| else if ( testsToRun.containsAtLeast( 1 ) ) |
| { |
| Class<?> testClass = testsToRun.iterator().next(); |
| executeSingleClass( reporterManager, testClass ); |
| } |
| } |
| |
| private void executeSingleClass( RunListener reporter, Class<?> testClass ) |
| throws TestSetFailedException |
| { |
| options.put( "suitename", testClass.getName() ); |
| |
| startTestSuite( reporter ); |
| |
| Map<String, String> optionsToUse = isJUnitTest( testClass ) ? junitOptions : options; |
| |
| run( Collections.<Class<?>>singleton( testClass ), testSourceDirectory, optionsToUse, reporter, |
| reportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); |
| |
| finishTestSuite( reporter ); |
| } |
| |
| private void executeLazy( TestsToRun testsToRun, RunListener reporterManager ) |
| throws TestSetFailedException |
| { |
| for ( Class<?> testToRun : testsToRun ) |
| { |
| executeSingleClass( reporterManager, testToRun ); |
| } |
| } |
| |
| private static Class<?> findJUnitTestClass() |
| { |
| return lookupClass( "junit.framework.Test" ); |
| } |
| |
| private static Class<Annotation> findJUnitRunWithAnnotation() |
| { |
| return lookupAnnotation( "org.junit.runner.RunWith" ); |
| } |
| |
| private static Class<Annotation> findJUnitTestAnnotation() |
| { |
| return lookupAnnotation( "org.junit.Test" ); |
| } |
| |
| @SuppressWarnings( "unchecked" ) |
| private static Class<Annotation> lookupAnnotation( String className ) |
| { |
| try |
| { |
| return (Class<Annotation>) Class.forName( className ); |
| } |
| catch ( ClassNotFoundException e ) |
| { |
| return null; |
| } |
| } |
| |
| private static Class<?> lookupClass( String className ) |
| { |
| try |
| { |
| return Class.forName( className ); |
| } |
| catch ( ClassNotFoundException e ) |
| { |
| return null; |
| } |
| } |
| |
| private void executeMulti( TestsToRun testsToRun, RunListener reporterManager ) |
| throws TestSetFailedException |
| { |
| List<Class<?>> testNgTestClasses = new ArrayList<Class<?>>(); |
| List<Class<?>> junitTestClasses = new ArrayList<Class<?>>(); |
| for ( Class<?> testToRun : testsToRun ) |
| { |
| if ( isJUnitTest( testToRun ) ) |
| { |
| junitTestClasses.add( testToRun ); |
| } |
| else |
| { |
| testNgTestClasses.add( testToRun ); |
| } |
| } |
| |
| File testNgReportsDirectory = reportsDirectory, junitReportsDirectory = reportsDirectory; |
| |
| if ( !junitTestClasses.isEmpty() && !testNgTestClasses.isEmpty() ) |
| { |
| testNgReportsDirectory = new File( reportsDirectory, "testng-native-results" ); |
| junitReportsDirectory = new File( reportsDirectory, "testng-junit-results" ); |
| } |
| startTestSuite( reporterManager ); |
| |
| run( testNgTestClasses, testSourceDirectory, options, reporterManager, |
| testNgReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); |
| |
| if ( !junitTestClasses.isEmpty() ) |
| { |
| run( junitTestClasses, testSourceDirectory, junitOptions, reporterManager, |
| junitReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount ); |
| } |
| |
| finishTestSuite( reporterManager ); |
| } |
| |
| private boolean isJUnitTest( Class<?> c ) |
| { |
| return isJunit3Test( c ) || isJunit4Test( c ); |
| } |
| |
| private boolean isJunit4Test( Class<?> c ) |
| { |
| return hasJunit4RunWithAnnotation( c ) || hasJunit4TestAnnotation( c ); |
| } |
| |
| private boolean hasJunit4RunWithAnnotation( Class<?> c ) |
| { |
| return junitRunWithAnnotation != null && c.getAnnotation( junitRunWithAnnotation ) != null; |
| } |
| |
| private boolean hasJunit4TestAnnotation( Class<?> c ) |
| { |
| if ( junitTestAnnotation != null ) |
| { |
| for ( Method m : c.getMethods() ) |
| { |
| if ( m.getAnnotation( junitTestAnnotation ) != null ) |
| { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| private boolean isJunit3Test( Class<?> c ) |
| { |
| return junitTestClass != null && junitTestClass.isAssignableFrom( c ); |
| } |
| |
| private Map<String, String> createJUnitOptions() |
| { |
| Map<String, String> junitOptions = new HashMap<String, String>( options ); |
| String onlyJUnit = options.get( "junit" ); |
| if ( isBlank( onlyJUnit ) ) |
| { |
| onlyJUnit = "true"; |
| } |
| junitOptions.put( "junit", onlyJUnit ); |
| return junitOptions; |
| } |
| |
| @Override |
| Map<String, String> getOptions() |
| { |
| return options; |
| } |
| } |