1   package org.apache.maven.surefire.testng;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  import org.apache.maven.surefire.booter.ProviderParameterNames;
23  import org.apache.maven.surefire.report.RunListener;
24  import org.apache.maven.surefire.testng.conf.Configurator;
25  import org.apache.maven.surefire.testset.TestSetFailedException;
26  import org.apache.maven.surefire.util.NestedRuntimeException;
27  import org.apache.maven.surefire.util.internal.StringUtils;
28  import org.testng.TestNG;
29  
30  import java.io.File;
31  import java.lang.reflect.Constructor;
32  import java.lang.reflect.InvocationTargetException;
33  import java.lang.reflect.Method;
34  import java.util.List;
35  import java.util.Map;
36  
37  
38  
39  
40  
41  
42  
43  public class TestNGExecutor
44  {
45  
46  
47      private TestNGExecutor()
48      {
49          
50      }
51  
52      public static void run( Class[] testClasses, String testSourceDirectory, Map options, RunListener reportManager,
53                              TestNgTestSuite suite, File reportsDirectory, final String methodNamePattern )
54          throws TestSetFailedException
55      {
56          TestNG testng = new TestNG( true );
57  
58          applyGroupMatching( testng, options );
59          if ( !StringUtils.isBlank( methodNamePattern ) )
60          {
61              applyMethodNameFiltering( testng, methodNamePattern );
62          }
63  
64          Configurator configurator = getConfigurator( (String) options.get("testng.configurator" ) );
65          System.out.println( "Configuring TestNG with: " + configurator.getClass().getSimpleName() );
66          configurator.configure( testng, options );
67          postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
68          testng.setTestClasses( testClasses );
69          testng.run();
70      }
71  
72      private static void applyMethodNameFiltering( TestNG testng, String methodNamePattern )
73          throws TestSetFailedException
74      {
75          
76          String clazzName = "org.apache.maven.surefire.testng.utils.MethodSelector";
77          
78          testng.addMethodSelector( clazzName, 10000 );
79          try
80          {
81              Class clazz = Class.forName( clazzName );
82  
83              Method method = clazz.getMethod( "setMethodName", new Class[]{ String.class } );
84              method.invoke( null, methodNamePattern );
85          }
86          catch ( ClassNotFoundException e )
87          {
88              throw new TestSetFailedException( e.getMessage(), e );
89          }
90          catch ( SecurityException e )
91          {
92              throw new TestSetFailedException( e.getMessage(), e );
93          }
94          catch ( NoSuchMethodException e )
95          {
96              throw new TestSetFailedException( e.getMessage(), e );
97          }
98          catch ( IllegalArgumentException e )
99          {
100             throw new TestSetFailedException( e.getMessage(), e );
101         }
102         catch ( IllegalAccessException e )
103         {
104             throw new TestSetFailedException( e.getMessage(), e );
105         }
106         catch ( InvocationTargetException e )
107         {
108             throw new TestSetFailedException( e.getMessage(), e );
109         }
110     }
111 
112     private static void applyGroupMatching( TestNG testng, Map options )
113         throws TestSetFailedException
114     {
115         String groups = (String) options.get( ProviderParameterNames.TESTNG_GROUPS_PROP );
116         String excludedGroups = (String) options.get( ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP );
117 
118         if ( groups == null && excludedGroups == null )
119         {
120             return;
121         }
122 
123         
124         String clazzName = "org.apache.maven.surefire.testng.utils.GroupMatcherMethodSelector";
125         
126         testng.addMethodSelector( clazzName, 9999 );
127         try
128         {
129             Class clazz = Class.forName( clazzName );
130 
131             
132             Method method = clazz.getMethod( "setGroups", new Class[]{ String.class, String.class } );
133             method.invoke( null, groups, excludedGroups );
134         }
135         catch ( ClassNotFoundException e )
136         {
137             throw new TestSetFailedException( e.getMessage(), e );
138         }
139         catch ( SecurityException e )
140         {
141             throw new TestSetFailedException( e.getMessage(), e );
142         }
143         catch ( NoSuchMethodException e )
144         {
145             throw new TestSetFailedException( e.getMessage(), e );
146         }
147         catch ( IllegalArgumentException e )
148         {
149             throw new TestSetFailedException( e.getMessage(), e );
150         }
151         catch ( IllegalAccessException e )
152         {
153             throw new TestSetFailedException( e.getMessage(), e );
154         }
155         catch ( InvocationTargetException e )
156         {
157             throw new TestSetFailedException( e.getMessage(), e );
158         }
159     }
160 
161     public static void run( List<String> suiteFiles, String testSourceDirectory, Map options, RunListener reportManager,
162                             TestNgTestSuite suite, File reportsDirectory )
163         throws TestSetFailedException
164     {
165         TestNG testng = new TestNG( true );
166         Configurator configurator = getConfigurator( (String) options.get("testng.configurator" ) );
167         configurator.configure( testng, options );
168         postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
169         testng.setTestSuites( suiteFiles );
170         testng.run();
171     }
172 
173     private static Configurator getConfigurator( String className )
174     {
175         try
176         {
177             return (Configurator) Class.forName( className ).newInstance();
178         }
179         catch ( InstantiationException e )
180         {
181             throw new RuntimeException( e );
182         }
183         catch ( IllegalAccessException e )
184         {
185             throw new RuntimeException( e );
186         }
187         catch ( ClassNotFoundException e )
188         {
189             throw new RuntimeException( e );
190         }
191     }
192 
193 
194     private static void postConfigure( TestNG testNG, String sourcePath, RunListener reportManager,
195                                        TestNgTestSuite suite, File reportsDirectory )
196         throws TestSetFailedException
197     {
198         
199         testNG.setVerbose( 0 );
200 
201         TestNGReporter reporter = createTestNGReporter( reportManager, suite );
202         testNG.addListener( (Object) reporter );
203 
204         
205         if ( sourcePath != null )
206         {
207             testNG.setSourcePath( sourcePath );
208         }
209 
210         testNG.setOutputDirectory( reportsDirectory.getAbsolutePath() );
211     }
212 
213     
214     
215     private static TestNGReporter createTestNGReporter( RunListener reportManager, TestNgTestSuite suite )
216     {
217         try
218         {
219             Class.forName( "org.testng.internal.IResultListener" );
220             Class c = Class.forName( "org.apache.maven.surefire.testng.ConfigurationAwareTestNGReporter" );
221             try
222             {
223                 Constructor ctor = c.getConstructor( new Class[]{ RunListener.class, TestNgTestSuite.class } );
224                 return (TestNGReporter) ctor.newInstance( reportManager, suite );
225             }
226             catch ( Exception e )
227             {
228                 throw new NestedRuntimeException( "Bug in ConfigurationAwareTestNGReporter", e );
229             }
230         }
231         catch ( ClassNotFoundException e )
232         {
233             return new TestNGReporter( reportManager );
234         }
235     }
236 
237 }