1 package org.apache.maven.surefire.junitplatform;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static java.util.Arrays.stream;
23 import static java.util.Collections.emptyMap;
24 import static java.util.Optional.empty;
25 import static java.util.Optional.of;
26 import static java.util.logging.Level.WARNING;
27 import static java.util.stream.Collectors.toList;
28 import static org.apache.maven.surefire.booter.ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP;
29 import static org.apache.maven.surefire.booter.ProviderParameterNames.TESTNG_GROUPS_PROP;
30 import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
31 import static org.apache.maven.surefire.util.TestsToRun.fromClass;
32 import static org.junit.platform.commons.util.StringUtils.isBlank;
33 import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
34 import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
35
36 import java.io.IOException;
37 import java.io.StringReader;
38 import java.io.UncheckedIOException;
39 import java.util.ArrayList;
40 import java.util.HashMap;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Optional;
44 import java.util.Properties;
45 import java.util.logging.Logger;
46
47 import org.apache.maven.surefire.providerapi.AbstractProvider;
48 import org.apache.maven.surefire.providerapi.ProviderParameters;
49 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
50 import org.apache.maven.surefire.report.ReporterException;
51 import org.apache.maven.surefire.report.ReporterFactory;
52 import org.apache.maven.surefire.report.RunListener;
53 import org.apache.maven.surefire.suite.RunResult;
54 import org.apache.maven.surefire.testset.TestListResolver;
55 import org.apache.maven.surefire.testset.TestSetFailedException;
56 import org.apache.maven.surefire.util.ScanResult;
57 import org.apache.maven.surefire.util.TestsToRun;
58 import org.junit.platform.commons.util.StringUtils;
59 import org.junit.platform.engine.Filter;
60 import org.junit.platform.launcher.Launcher;
61 import org.junit.platform.launcher.LauncherDiscoveryRequest;
62 import org.junit.platform.launcher.TagFilter;
63 import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
64 import org.junit.platform.launcher.core.LauncherFactory;
65
66
67
68
69
70
71 public class JUnitPlatformProvider
72 extends AbstractProvider
73 {
74 static final String CONFIGURATION_PARAMETERS = "configurationParameters";
75
76 private final ProviderParameters parameters;
77
78 private final Launcher launcher;
79
80 private final Filter<?>[] filters;
81
82 private final Map<String, String> configurationParameters;
83
84 public JUnitPlatformProvider( ProviderParameters parameters )
85 {
86 this( parameters, LauncherFactory.create() );
87 }
88
89 JUnitPlatformProvider( ProviderParameters parameters, Launcher launcher )
90 {
91 this.parameters = parameters;
92 this.launcher = launcher;
93 filters = newFilters();
94 configurationParameters = newConfigurationParameters();
95 Logger.getLogger( "org.junit" ).setLevel( WARNING );
96 }
97
98 @Override
99 public Iterable<Class<?>> getSuites()
100 {
101 return scanClasspath();
102 }
103
104 @Override
105 public RunResult invoke( Object forkTestSet )
106 throws TestSetFailedException, ReporterException
107 {
108 ReporterFactory reporterFactory = parameters.getReporterFactory();
109 final RunResult runResult;
110 try
111 {
112 RunListener runListener = reporterFactory.createReporter();
113 startCapture( ( ConsoleOutputReceiver ) runListener );
114 if ( forkTestSet instanceof TestsToRun )
115 {
116 invokeAllTests( (TestsToRun) forkTestSet, runListener );
117 }
118 else if ( forkTestSet instanceof Class )
119 {
120 invokeAllTests( fromClass( ( Class<?> ) forkTestSet ), runListener );
121 }
122 else if ( forkTestSet == null )
123 {
124 invokeAllTests( scanClasspath(), runListener );
125 }
126 else
127 {
128 throw new IllegalArgumentException(
129 "Unexpected value of forkTestSet: " + forkTestSet );
130 }
131 }
132 finally
133 {
134 runResult = reporterFactory.close();
135 }
136 return runResult;
137 }
138
139 private TestsToRun scanClasspath()
140 {
141 TestPlanScannerFilter filter = new TestPlanScannerFilter( launcher, filters );
142 ScanResult scanResult = parameters.getScanResult();
143 TestsToRun scannedClasses = scanResult.applyFilter( filter, parameters.getTestClassLoader() );
144 return parameters.getRunOrderCalculator().orderTestClasses( scannedClasses );
145 }
146
147 private void invokeAllTests( TestsToRun testsToRun, RunListener runListener )
148 {
149 LauncherDiscoveryRequest discoveryRequest = buildLauncherDiscoveryRequest( testsToRun );
150 launcher.execute( discoveryRequest, new RunListenerAdapter( runListener ) );
151 }
152
153 private LauncherDiscoveryRequest buildLauncherDiscoveryRequest( TestsToRun testsToRun )
154 {
155 LauncherDiscoveryRequestBuilder builder =
156 request().filters( filters ).configurationParameters( configurationParameters );
157 for ( Class<?> testClass : testsToRun )
158 {
159 builder.selectors( selectClass( testClass ) );
160 }
161 return builder.build();
162 }
163
164 private Filter<?>[] newFilters()
165 {
166 List<Filter<?>> filters = new ArrayList<>();
167
168 getPropertiesList( TESTNG_GROUPS_PROP )
169 .map( TagFilter::includeTags )
170 .ifPresent( filters::add );
171
172 getPropertiesList( TESTNG_EXCLUDEDGROUPS_PROP )
173 .map( TagFilter::excludeTags )
174 .ifPresent( filters::add );
175
176 TestListResolver testListResolver = parameters.getTestRequest().getTestListResolver();
177 if ( !testListResolver.isEmpty() )
178 {
179 filters.add( new TestMethodFilter( testListResolver ) );
180 }
181
182 return filters.toArray( new Filter<?>[ filters.size() ] );
183 }
184
185 Filter<?>[] getFilters()
186 {
187 return filters;
188 }
189
190 private Map<String, String> newConfigurationParameters()
191 {
192 String content = parameters.getProviderProperties().get( CONFIGURATION_PARAMETERS );
193 if ( content == null )
194 {
195 return emptyMap();
196 }
197 try ( StringReader reader = new StringReader( content ) )
198 {
199 Map<String, String> result = new HashMap<>();
200 Properties props = new Properties();
201 props.load( reader );
202 props.stringPropertyNames()
203 .forEach( key -> result.put( key, props.getProperty( key ) ) );
204 return result;
205 }
206 catch ( IOException e )
207 {
208 throw new UncheckedIOException( "Error reading " + CONFIGURATION_PARAMETERS, e );
209 }
210 }
211
212 Map<String, String> getConfigurationParameters()
213 {
214 return configurationParameters;
215 }
216
217 private Optional<List<String>> getPropertiesList( String key )
218 {
219 String property = parameters.getProviderProperties().get( key );
220 return isBlank( property ) ? empty()
221 : of( stream( property.split( "[,]+" ) )
222 .filter( StringUtils::isNotBlank )
223 .map( String::trim )
224 .collect( toList() ) );
225 }
226 }