View Javadoc

1   package org.apache.maven.surefire.testng;
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.artifact.versioning.ArtifactVersion;
23  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
24  import org.apache.maven.surefire.NonAbstractClassFilter;
25  import org.apache.maven.surefire.report.RunListener;
26  import org.apache.maven.surefire.report.ReportEntry;
27  import org.apache.maven.surefire.report.ReporterException;
28  import org.apache.maven.surefire.report.ReporterFactory;
29  import org.apache.maven.surefire.report.ReporterManagerFactory;
30  import org.apache.maven.surefire.report.SimpleReportEntry;
31  import org.apache.maven.surefire.testset.TestSetFailedException;
32  import org.apache.maven.surefire.util.DefaultDirectoryScanner;
33  import org.apache.maven.surefire.util.DirectoryScanner;
34  import org.apache.maven.surefire.util.TestsToRun;
35  
36  import java.io.File;
37  import java.util.ArrayList;
38  import java.util.Collections;
39  import java.util.HashMap;
40  import java.util.Iterator;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.Properties;
44  import java.util.SortedMap;
45  import java.util.TreeMap;
46  
47  /**
48   * Test suite for TestNG based on a directory of Java test classes. Can also execute JUnit tests.
49   *
50   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
51   * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
52   */
53  public class TestNGDirectoryTestSuite
54      implements TestNgTestSuite
55  {
56      private final ArtifactVersion version;
57  
58      private final Map options;
59  
60      private final String testSourceDirectory;
61  
62      private final File reportsDirectory;
63  
64      private SortedMap testSets;
65  
66      private final DirectoryScanner surefireDirectoryScanner;
67      
68      private String testMethodPattern;
69  
70      public TestNGDirectoryTestSuite( File basedir, ArrayList includes, ArrayList excludes, String testSourceDirectory,
71                                       String artifactVersion, Properties confOptions, File reportsDirectory, String testMethodPattern )
72      {
73  
74          this.surefireDirectoryScanner = new DefaultDirectoryScanner( basedir, includes, excludes, "filesystem" );
75  
76          this.options = confOptions;
77  
78          this.testSourceDirectory = testSourceDirectory;
79          this.reportsDirectory = reportsDirectory;
80          this.version =  new DefaultArtifactVersion( artifactVersion );
81          this.testMethodPattern = testMethodPattern;
82      }
83  
84      public void execute( TestsToRun testsToRun, ReporterFactory reporterManagerFactory )
85          throws ReporterException, TestSetFailedException
86      {
87  
88          if ( testsToRun.size() == 0 )
89          {
90              return;
91          }
92  
93          if ( testsToRun.size() > 1 )
94          {
95              executeMulti( testsToRun, reporterManagerFactory );
96              return;
97          }
98  
99          RunListener reporter = reporterManagerFactory.createReporter();
100         startTestSuite( reporter, this );
101 
102         TestNGExecutor.run( new Class[]{ (Class) testsToRun.iterator().next() }, this.testSourceDirectory, this.options,
103                             this.version, reporter, this, reportsDirectory, testMethodPattern );
104 
105         finishTestSuite( reporter, this );
106     }
107 
108     public void executeMulti( TestsToRun testsToRun, ReporterFactory reporterFactory )
109         throws ReporterException, TestSetFailedException
110     {
111         Class junitTest;
112         try
113         {
114             junitTest = Class.forName( "junit.framework.Test" );
115         }
116         catch ( ClassNotFoundException e )
117         {
118             junitTest = null;
119         }
120 
121         List testNgTestClasses = new ArrayList();
122         List junitTestClasses = new ArrayList();
123         for ( Iterator it = testsToRun.iterator(); it.hasNext(); )
124         {
125             Class c = (Class) it.next();
126             if ( junitTest != null && junitTest.isAssignableFrom( c ) )
127             {
128                 junitTestClasses.add( c );
129             }
130             else
131             {
132                 testNgTestClasses.add( c );
133             }
134         }
135 
136         File testNgReportsDirectory = reportsDirectory, junitReportsDirectory = reportsDirectory;
137 
138         if ( junitTestClasses.size() > 0 && testNgTestClasses.size() > 0 )
139         {
140             testNgReportsDirectory = new File( reportsDirectory, "testng-native-results" );
141             junitReportsDirectory = new File( reportsDirectory, "testng-junit-results" );
142         }
143 
144         RunListener reporterManager = new SynchronizedReporterManager( reporterFactory.createReporter() );
145         startTestSuite( reporterManager, this );
146 
147         Class[] testClasses = (Class[]) testNgTestClasses.toArray( new Class[testNgTestClasses.size()] );
148 
149         TestNGExecutor.run( testClasses, this.testSourceDirectory, this.options, this.version, reporterManager, this,
150                             testNgReportsDirectory, testMethodPattern );
151 
152         if ( junitTestClasses.size() > 0 )
153         {
154             testClasses = (Class[]) junitTestClasses.toArray( new Class[junitTestClasses.size()] );
155 
156             Map junitOptions = new HashMap();
157             for ( Iterator it = this.options.keySet().iterator(); it.hasNext(); )
158             {
159                 Object key = it.next();
160                 junitOptions.put( key, options.get( key ) );
161             }
162 
163             junitOptions.put( "junit", Boolean.TRUE );
164 
165             TestNGExecutor.run( testClasses, this.testSourceDirectory, junitOptions, this.version, reporterManager,
166                                 this, junitReportsDirectory, testMethodPattern );
167         }
168 
169         finishTestSuite( reporterManager, this );
170     }
171 
172     // single class test
173     public void execute( String testSetName, ReporterManagerFactory reporterManagerFactory, ClassLoader classLoader )
174         throws ReporterException, TestSetFailedException
175     {
176         if ( testSets == null )
177         {
178             throw new IllegalStateException( "You must call locateTestSets before calling execute" );
179         }
180         TestNGTestSet testSet = (TestNGTestSet) testSets.get( testSetName );
181 
182         if ( testSet == null )
183         {
184             throw new TestSetFailedException( "Unable to find test set '" + testSetName + "' in suite" );
185         }
186 
187         RunListener reporter = reporterManagerFactory.createReporter();
188         startTestSuite( reporter, this );
189 
190         TestNGExecutor.run( new Class[]{ testSet.getTestClass() }, this.testSourceDirectory, this.options, this.version,
191                             reporter, this, reportsDirectory, testMethodPattern );
192 
193         finishTestSuite( reporter, this );
194     }
195 
196     public static void startTestSuite( RunListener reporter, Object suite )
197     {
198         ReportEntry report = new SimpleReportEntry( suite.getClass().getName(), getSuiteName( suite ) );
199 
200         try
201         {
202             reporter.testSetStarting( report );
203         }
204         catch ( ReporterException e )
205         {
206             // TODO: remove this exception from the report manager
207         }
208     }
209 
210     public static void finishTestSuite( RunListener reporterManager, Object suite )
211         throws ReporterException
212     {
213         ReportEntry report = new SimpleReportEntry( suite.getClass().getName(), getSuiteName( suite ) );
214 
215         reporterManager.testSetCompleted( report );
216     }
217 
218     public String getSuiteName()
219     {
220         String result = (String) options.get( "suitename" );
221         if ( result == null )
222         {
223             result = "TestSuite";
224         }
225         return result;
226     }
227 
228     private static String getSuiteName( Object suite )
229     {
230         String result;
231         if ( suite instanceof TestNGDirectoryTestSuite )
232         {
233             return ( (TestNGDirectoryTestSuite) suite ).getSuiteName();
234         }
235         else if ( suite instanceof TestNGXmlTestSuite )
236         {
237             return ( (TestNGXmlTestSuite) suite ).getSuiteName();
238         }
239         else
240         {
241             result = "TestSuite";
242         }
243 
244         return result;
245     }
246 
247     public Map locateTestSets( ClassLoader classLoader )
248         throws TestSetFailedException
249     {
250         if ( testSets != null )
251         {
252             throw new IllegalStateException( "You can't call locateTestSets twice" );
253         }
254         testSets = new TreeMap();
255 
256         final TestsToRun testsToRun =
257             surefireDirectoryScanner.locateTestClasses( classLoader, new NonAbstractClassFilter() );
258         Class[] locatedClasses = testsToRun.getLocatedClasses();
259 
260         for ( int i = 0; i < locatedClasses.length; i++ )
261         {
262             Class testClass = locatedClasses[i];
263             TestNGTestSet testSet = new TestNGTestSet( testClass );
264 
265             if ( testSets.containsKey( testSet.getName() ) )
266             {
267                 throw new TestSetFailedException( "Duplicate test set '" + testSet.getName() + "'" );
268             }
269             testSets.put( testSet.getName(), testSet );
270 
271         }
272 
273         return Collections.unmodifiableSortedMap( testSets );
274     }
275 
276 }