View Javadoc

1   package org.apache.maven.surefire.junit4;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.surefire.Surefire;
23  import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
24  import org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory;
25  import org.apache.maven.surefire.common.junit4.JUnit4TestChecker;
26  import org.apache.maven.surefire.providerapi.AbstractProvider;
27  import org.apache.maven.surefire.providerapi.ProviderParameters;
28  import org.apache.maven.surefire.report.PojoStackTraceWriter;
29  import org.apache.maven.surefire.report.RunListener;
30  import org.apache.maven.surefire.report.ReportEntry;
31  import org.apache.maven.surefire.report.ReporterException;
32  import org.apache.maven.surefire.report.ReporterFactory;
33  import org.apache.maven.surefire.report.SimpleReportEntry;
34  import org.apache.maven.surefire.suite.RunResult;
35  import org.apache.maven.surefire.testset.TestSetFailedException;
36  import org.apache.maven.surefire.util.DefaultDirectoryScanner;
37  import org.apache.maven.surefire.util.DirectoryScanner;
38  import org.apache.maven.surefire.util.TestsToRun;
39  
40  import org.junit.runner.notification.RunNotifier;
41  
42  import java.util.Iterator;
43  import java.util.List;
44  import java.util.ResourceBundle;
45  
46  
47  /**
48   * @author Kristian Rosenvold
49   */
50  @SuppressWarnings( { "UnusedDeclaration" } )
51  public class JUnit4Provider extends AbstractProvider
52  {
53  
54      private static ResourceBundle bundle = ResourceBundle.getBundle( Surefire.SUREFIRE_BUNDLE_NAME );
55  
56      private final ClassLoader testClassLoader;
57  
58      private final DirectoryScanner directoryScanner;
59  
60      private final List<org.junit.runner.notification.RunListener> customRunListeners;
61  
62      private final JUnit4TestChecker jUnit4TestChecker;
63      
64      private final String requestedTestMethod;
65  
66      private TestsToRun testsToRun;
67  
68      private final ProviderParameters providerParameters;
69  
70      public JUnit4Provider( ProviderParameters booterParameters )
71      {
72          this.providerParameters = booterParameters;
73          this.testClassLoader = booterParameters.getTestClassLoader();
74          this.directoryScanner = booterParameters.getDirectoryScanner();
75          customRunListeners = JUnit4RunListenerFactory.
76              createCustomListeners( booterParameters.getProviderProperties().getProperty( "listener" ) );
77          jUnit4TestChecker = new JUnit4TestChecker( testClassLoader );
78          requestedTestMethod = booterParameters.getTestRequest().getRequestedTestMethod();
79  
80      }
81  
82      @SuppressWarnings( { "UnnecessaryUnboxing" } )
83      public RunResult invoke( Object forkTestSet )
84          throws TestSetFailedException, ReporterException
85      {
86          if ( testsToRun == null )
87          {
88              testsToRun = forkTestSet == null ? scanClassPath() : TestsToRun.fromClass( (Class) forkTestSet );
89          }
90  
91          upgradeCheck();
92  
93          final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
94  
95          RunListener reporter = reporterFactory.createReporter();
96          JUnit4RunListener jUnit4TestSetReporter = new JUnit4RunListener( reporter );
97          RunNotifier runNotifer = getRunNotifer( jUnit4TestSetReporter, customRunListeners );
98  
99          for ( Class clazz : testsToRun.getLocatedClasses() )
100         {
101             executeTestSet( clazz, reporter, testClassLoader, runNotifer );
102         }
103 
104         closeRunNotifer( jUnit4TestSetReporter, customRunListeners );
105 
106         return reporterFactory.close();
107 
108     }
109 
110     private void executeTestSet( Class clazz, RunListener reporter, ClassLoader classLoader, RunNotifier listeners )
111         throws ReporterException, TestSetFailedException
112     {
113         final ReportEntry report = new SimpleReportEntry( this.getClass().getName(), clazz.getName() );
114 
115         reporter.testSetStarting( report );
116 
117         try
118         {
119             JUnit4TestSet.execute( clazz, listeners, this.requestedTestMethod );
120         }
121         catch ( TestSetFailedException e )
122         {
123             throw e;
124         }
125         catch ( Throwable e )
126         {
127             reporter.testError( new SimpleReportEntry( report.getSourceName(), report.getName(),
128                                                        new PojoStackTraceWriter( report.getSourceName(),
129                                                                                  report.getName(), e ) ) );
130         }
131         finally
132         {
133             reporter.testSetCompleted( report );
134         }
135     }
136 
137     private RunNotifier getRunNotifer( org.junit.runner.notification.RunListener main, List<org.junit.runner.notification.RunListener> others )
138     {
139         RunNotifier fNotifier = new RunNotifier();
140         fNotifier.addListener( main );
141         for ( org.junit.runner.notification.RunListener listener : others )
142         {
143             fNotifier.addListener( listener );
144         }
145         return fNotifier;
146     }
147 
148     // I am not entierly sure as to why we do this explicit freeing, it's one of those
149     // pieces of code that just seem to linger on in here ;)
150     private void closeRunNotifer( org.junit.runner.notification.RunListener main, List<org.junit.runner.notification.RunListener> others )
151     {
152         RunNotifier fNotifier = new RunNotifier();
153         fNotifier.removeListener( main );
154         for ( org.junit.runner.notification.RunListener listener : others )
155         {
156             fNotifier.removeListener( listener );
157         }
158     }
159 
160     public Iterator getSuites()
161     {
162         testsToRun = scanClassPath();
163         return testsToRun.iterator();
164     }
165 
166     private TestsToRun scanClassPath()
167     {
168         return directoryScanner.locateTestClasses( testClassLoader, jUnit4TestChecker );
169     }
170 
171     private void upgradeCheck()
172         throws TestSetFailedException
173     {
174         if ( isJunit4UpgradeCheck()
175             && ( (DefaultDirectoryScanner) directoryScanner ).getClassesSkippedByValidation().size() > 0 )
176         {
177             StringBuilder reason = new StringBuilder();
178             reason.append( "Updated check failed\n" );
179             reason.append( "There are tests that would be run with junit4 / surefire 2.6 but not with [2.7,):\n" );
180             //noinspection unchecked
181             for ( Class testClass : (List<Class>) ( (DefaultDirectoryScanner) directoryScanner ).getClassesSkippedByValidation() )
182             {
183                 reason.append( "   " );
184                 reason.append( testClass.getCanonicalName() );
185                 reason.append( "\n" );
186             }
187             throw new TestSetFailedException( reason.toString() );
188         }
189     }
190 
191     private boolean isJunit4UpgradeCheck()
192     {
193         final String property = System.getProperty( "surefire.junit4.upgradecheck" );
194         return property != null;
195     }
196 
197     public Boolean isRunnable()
198     {
199         return Boolean.TRUE;
200     }
201 }