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 java.io.File;
23  import java.lang.reflect.Constructor;
24  import java.lang.reflect.InvocationTargetException;
25  import java.lang.reflect.Method;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.maven.artifact.versioning.ArtifactVersion;
30  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
31  import org.apache.maven.artifact.versioning.VersionRange;
32  import org.apache.maven.surefire.report.RunListener;
33  import org.apache.maven.surefire.testng.conf.Configurator;
34  import org.apache.maven.surefire.testng.conf.TestNG4751Configurator;
35  import org.apache.maven.surefire.testng.conf.TestNG52Configurator;
36  import org.apache.maven.surefire.testng.conf.TestNGMapConfigurator;
37  import org.apache.maven.surefire.testset.TestSetFailedException;
38  import org.apache.maven.surefire.util.NestedRuntimeException;
39  import org.apache.maven.surefire.util.internal.StringUtils;
40  import org.testng.TestNG;
41  
42  /**
43   * Contains utility methods for executing TestNG.
44   *
45   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
46   * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
47   */
48  public class TestNGExecutor
49  {
50      
51     
52      private TestNGExecutor()
53      {
54          // noop
55      }
56  
57      public static void run( Class[] testClasses, String testSourceDirectory, Map options, ArtifactVersion version,
58                              RunListener reportManager, TestNgTestSuite suite, File reportsDirectory, final String methodNamePattern )
59          throws TestSetFailedException
60      {
61          TestNG testng = new TestNG( true );
62          if (!StringUtils.isBlank( methodNamePattern ))
63          {
64              applyMethodNameFiltering( testng, methodNamePattern );
65          } 
66          Configurator configurator = getConfigurator( version );
67          configurator.configure( testng, options );
68          postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
69          testng.setTestClasses( testClasses );
70          testng.run();
71      }
72  
73      private static void applyMethodNameFiltering(TestNG testng, String methodNamePattern)
74          throws TestSetFailedException
75      {
76          // the class is available in the testClassPath
77          String clazzName = "org.apache.maven.surefire.testng.utils.MethodSelector";
78          // looks to need a high value 
79          testng.addMethodSelector( clazzName , 10000 );
80          try
81          {
82              Class clazz = Class.forName( clazzName );
83  
84              Method method = clazz.getMethod( "setMethodName", new Class[]{String.class} );
85              method.invoke( null, new Object[]{methodNamePattern} );
86          }
87          catch ( ClassNotFoundException e )
88          {
89              throw new TestSetFailedException(e.getMessage(), e);
90          }
91          catch ( SecurityException e )
92          {
93              throw new TestSetFailedException(e.getMessage(), e);
94          }
95          catch ( NoSuchMethodException e )
96          {
97              throw new TestSetFailedException(e.getMessage(), e);
98          }
99          catch ( IllegalArgumentException e )
100         {
101             throw new TestSetFailedException(e.getMessage(), e);
102         }
103         catch ( IllegalAccessException e )
104         {
105             throw new TestSetFailedException(e.getMessage(), e);
106         }
107         catch ( InvocationTargetException e )
108         {
109             throw new TestSetFailedException(e.getMessage(), e);
110         }        
111     }
112     
113     public static void run( List suiteFiles, String testSourceDirectory, Map options, ArtifactVersion version,
114                             RunListener reportManager, TestNgTestSuite suite, File reportsDirectory )
115         throws TestSetFailedException
116     {
117         TestNG testng = new TestNG( true );
118         Configurator configurator = getConfigurator( version );
119         configurator.configure( testng, options );
120         postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
121         testng.setTestSuites( suiteFiles );
122         testng.run();
123     }
124 
125     private static Configurator getConfigurator( ArtifactVersion version )
126         throws TestSetFailedException
127     {
128         try
129         {
130             VersionRange range = VersionRange.createFromVersionSpec( "[4.7,5.1]" );
131             if ( range.containsVersion( version ) )
132             {
133                 return new TestNG4751Configurator();
134             }
135             range = VersionRange.createFromVersionSpec( "[5.2]" );
136             if ( range.containsVersion( version ) )
137             {
138                 return new TestNG52Configurator();
139             }
140             range = VersionRange.createFromVersionSpec( "[5.3,)" );
141             if ( range.containsVersion( version ) )
142             {
143                 return new TestNGMapConfigurator();
144             }
145 
146             throw new TestSetFailedException( "Unknown TestNG version " + version );
147         }
148         catch ( InvalidVersionSpecificationException invsex )
149         {
150             throw new TestSetFailedException( "Bug in plugin. Please report it with the attached stacktrace", invsex );
151         }
152     }
153 
154 
155     private static void postConfigure( TestNG testNG, String sourcePath, RunListener reportManager, TestNgTestSuite suite,
156                                        File reportsDirectory )
157         throws TestSetFailedException
158     {
159         // turn off all TestNG output
160         testNG.setVerbose( 0 );
161 
162         TestNGReporter reporter = createTestNGReporter( reportManager, suite );
163         testNG.addListener( (Object) reporter );
164 
165         // FIXME: use classifier to decide if we need to pass along the source dir (onyl for JDK14)
166         if ( sourcePath != null )
167         {
168             testNG.setSourcePath( sourcePath );
169         }
170 
171         testNG.setOutputDirectory( reportsDirectory.getAbsolutePath() );
172     }
173 
174     // If we have access to IResultListener, return a ConfigurationAwareTestNGReporter
175     // But don't cause NoClassDefFoundErrors if it isn't available; just return a regular TestNGReporter instead
176     private static TestNGReporter createTestNGReporter( RunListener reportManager, TestNgTestSuite suite )
177     {
178         try
179         {
180             Class.forName( "org.testng.internal.IResultListener" );
181             Class c = Class.forName( "org.apache.maven.surefire.testng.ConfigurationAwareTestNGReporter" );
182             try
183             {
184                 Constructor ctor = c.getConstructor( new Class[]{ RunListener.class, TestNgTestSuite.class } );
185                 return (TestNGReporter) ctor.newInstance( new Object[]{ reportManager, suite } );
186             }
187             catch ( Exception e )
188             {
189                 throw new NestedRuntimeException( "Bug in ConfigurationAwareTestNGReporter", e );
190             }
191         }
192         catch ( ClassNotFoundException e )
193         {
194             return new TestNGReporter( reportManager );
195         }
196     }
197     
198 }