1 package org.apache.maven.surefire.junit4;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Iterator;
23 import java.util.List;
24 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
25 import org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory;
26 import org.apache.maven.surefire.common.junit4.JUnit4TestChecker;
27 import org.apache.maven.surefire.providerapi.AbstractProvider;
28 import org.apache.maven.surefire.providerapi.ProviderParameters;
29 import org.apache.maven.surefire.report.ConsoleOutputCapture;
30 import org.apache.maven.surefire.report.ConsoleOutputReceiver;
31 import org.apache.maven.surefire.report.PojoStackTraceWriter;
32 import org.apache.maven.surefire.report.ReportEntry;
33 import org.apache.maven.surefire.report.ReporterException;
34 import org.apache.maven.surefire.report.ReporterFactory;
35 import org.apache.maven.surefire.report.RunListener;
36 import org.apache.maven.surefire.report.SimpleReportEntry;
37 import org.apache.maven.surefire.suite.RunResult;
38 import org.apache.maven.surefire.testset.TestSetFailedException;
39 import org.apache.maven.surefire.util.DefaultDirectoryScanner;
40 import org.apache.maven.surefire.util.DirectoryScanner;
41 import org.apache.maven.surefire.util.TestsToRun;
42
43 import org.junit.runner.Result;
44 import org.junit.runner.notification.RunNotifier;
45
46
47
48
49 public class JUnit4Provider
50 extends AbstractProvider
51 {
52 private final ClassLoader testClassLoader;
53
54 private final DirectoryScanner directoryScanner;
55
56 private final List<org.junit.runner.notification.RunListener> customRunListeners;
57
58 private final JUnit4TestChecker jUnit4TestChecker;
59
60 private final String requestedTestMethod;
61
62 private TestsToRun testsToRun;
63
64 private final ProviderParameters providerParameters;
65
66 public JUnit4Provider( ProviderParameters booterParameters )
67 {
68 this.providerParameters = booterParameters;
69 this.testClassLoader = booterParameters.getTestClassLoader();
70 this.directoryScanner = booterParameters.getDirectoryScanner();
71 customRunListeners = JUnit4RunListenerFactory.
72 createCustomListeners( booterParameters.getProviderProperties().getProperty( "listener" ) );
73 jUnit4TestChecker = new JUnit4TestChecker( testClassLoader );
74 requestedTestMethod = booterParameters.getTestRequest().getRequestedTestMethod();
75
76 }
77
78 public RunResult invoke( Object forkTestSet )
79 throws TestSetFailedException, ReporterException
80 {
81 if ( testsToRun == null )
82 {
83 testsToRun = forkTestSet == null ? scanClassPath() : TestsToRun.fromClass( (Class) forkTestSet );
84 }
85
86 upgradeCheck();
87
88 final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
89
90 final RunListener reporter = reporterFactory.createReporter();
91
92
93 ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
94
95 JUnit4RunListener jUnit4TestSetReporter = new JUnit4RunListener( reporter );
96
97 Result result = new Result();
98 RunNotifier runNotifer = getRunNotifer( jUnit4TestSetReporter, result, customRunListeners );
99
100 runNotifer.fireTestRunStarted( null );
101
102 for ( Class clazz : testsToRun.getLocatedClasses() )
103 {
104 executeTestSet( clazz, reporter, runNotifer );
105 }
106
107 runNotifer.fireTestRunFinished( result );
108
109 closeRunNotifer( jUnit4TestSetReporter, customRunListeners );
110
111 return reporterFactory.close();
112 }
113
114 private void executeTestSet( Class clazz, RunListener reporter, RunNotifier listeners )
115 throws ReporterException, TestSetFailedException
116 {
117 final ReportEntry report = new SimpleReportEntry( this.getClass().getName(), clazz.getName() );
118
119 reporter.testSetStarting( report );
120
121 try
122 {
123 JUnit4TestSet.execute( clazz, listeners, this.requestedTestMethod );
124 }
125 catch ( TestSetFailedException e )
126 {
127 throw e;
128 }
129 catch ( Throwable e )
130 {
131 reporter.testError( new SimpleReportEntry( report.getSourceName(), report.getName(),
132 new PojoStackTraceWriter( report.getSourceName(),
133 report.getName(), e ) ) );
134 }
135 finally
136 {
137 reporter.testSetCompleted( report );
138 }
139 }
140
141 private RunNotifier getRunNotifer( org.junit.runner.notification.RunListener main, Result result, List<org.junit.runner.notification.RunListener> others )
142 {
143 RunNotifier fNotifier = new RunNotifier();
144 fNotifier.addListener( main );
145 fNotifier.addListener( result.createListener() );
146 for ( org.junit.runner.notification.RunListener listener : others )
147 {
148 fNotifier.addListener( listener );
149 }
150 return fNotifier;
151 }
152
153
154
155 private void closeRunNotifer( org.junit.runner.notification.RunListener main,
156 List<org.junit.runner.notification.RunListener> others )
157 {
158 RunNotifier fNotifier = new RunNotifier();
159 fNotifier.removeListener( main );
160 for ( org.junit.runner.notification.RunListener listener : others )
161 {
162 fNotifier.removeListener( listener );
163 }
164 }
165
166 public Iterator getSuites()
167 {
168 testsToRun = scanClassPath();
169 return testsToRun.iterator();
170 }
171
172 private TestsToRun scanClassPath()
173 {
174 return directoryScanner.locateTestClasses( testClassLoader, jUnit4TestChecker );
175 }
176
177 private void upgradeCheck()
178 throws TestSetFailedException
179 {
180 if ( isJunit4UpgradeCheck()
181 && ( (DefaultDirectoryScanner) directoryScanner ).getClassesSkippedByValidation().size() > 0 )
182 {
183 StringBuilder reason = new StringBuilder();
184 reason.append( "Updated check failed\n" );
185 reason.append( "There are tests that would be run with junit4 / surefire 2.6 but not with [2.7,):\n" );
186
187 for ( Class testClass : (List<Class>) ( (DefaultDirectoryScanner) directoryScanner ).getClassesSkippedByValidation() )
188 {
189 reason.append( " " );
190 reason.append( testClass.getCanonicalName() );
191 reason.append( "\n" );
192 }
193 throw new TestSetFailedException( reason.toString() );
194 }
195 }
196
197 private boolean isJunit4UpgradeCheck()
198 {
199 final String property = System.getProperty( "surefire.junit4.upgradecheck" );
200 return property != null;
201 }
202 }