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.surefire.report.CategorizedReportEntry;
23  import org.apache.maven.surefire.report.PojoStackTraceWriter;
24  import org.apache.maven.surefire.report.ReportEntry;
25  import org.apache.maven.surefire.report.RunListener;
26  import org.apache.maven.surefire.report.SimpleReportEntry;
27  
28  import org.testng.ISuite;
29  import org.testng.ISuiteListener;
30  import org.testng.ITestContext;
31  import org.testng.ITestListener;
32  import org.testng.ITestResult;
33  
34  import static org.apache.maven.surefire.report.SimpleReportEntry.ignored;
35  import static org.apache.maven.surefire.report.SimpleReportEntry.withException;
36  
37  /**
38   * Listens for and provides and adaptor layer so that
39   * TestNG tests can report their status to the current
40   * {@link org.apache.maven.surefire.report.RunListener}.
41   *
42   * @author jkuhnert
43   */
44  public class TestNGReporter
45      implements ITestListener, ISuiteListener
46  {
47      private final RunListener reporter;
48  
49      /**
50       * Constructs a new instance that will listen to
51       * test updates from a {@link org.testng.TestNG} class instance.
52       * <br>
53       * <br>It is assumed that the requisite {@link org.testng.TestNG#addListener(ITestListener)}
54       * method call has already associated with this instance <i>before</i> the test
55       * suite is run.
56       *
57       * @param reportManager Instance to report suite status to
58       */
59      public TestNGReporter( RunListener reportManager )
60      {
61          this.reporter = reportManager;
62      }
63  
64      @Override
65      public void onTestStart( ITestResult result )
66      {
67          String group = groupString( result.getMethod().getGroups(), result.getTestClass().getName() );
68          String userFriendlyTestName = getUserFriendlyTestName( result );
69          reporter.testStarting( new CategorizedReportEntry( getSource( result ), userFriendlyTestName, group ) );
70      }
71  
72      private String getSource( ITestResult result )
73      {
74          return result.getTestClass().getName();
75      }
76  
77      @Override
78      public void onTestSuccess( ITestResult result )
79      {
80          ReportEntry report = new SimpleReportEntry( getSource( result ), getUserFriendlyTestName( result ) );
81          reporter.testSucceeded( report );
82      }
83  
84      @Override
85      public void onTestFailure( ITestResult result )
86      {
87          ReportEntry report = withException( getSource( result ), getUserFriendlyTestName( result ),
88                  new PojoStackTraceWriter( result.getTestClass().getRealClass().getName(),
89                          result.getMethod().getMethodName(),
90                          result.getThrowable() ) );
91  
92          reporter.testFailed( report );
93      }
94  
95      private static String getUserFriendlyTestName( ITestResult result )
96      {
97          // This is consistent with the JUnit output
98          return result.getName() + "(" + result.getTestClass().getName() + ")";
99      }
100 
101     @Override
102     public void onTestSkipped( ITestResult result )
103     {
104         Throwable t = result.getThrowable();
105         String reason = t == null ? null : t.getMessage();
106         ReportEntry report = ignored( getSource( result ), getUserFriendlyTestName( result ), reason );
107         reporter.testSkipped( report );
108     }
109 
110     @Override
111     public void onTestFailedButWithinSuccessPercentage( ITestResult result )
112     {
113         ReportEntry report = withException( getSource( result ), getUserFriendlyTestName( result ),
114                 new PojoStackTraceWriter( result.getTestClass().getRealClass().getName(),
115                         result.getMethod().getMethodName(),
116                         result.getThrowable() ) );
117 
118         reporter.testSucceeded( report );
119     }
120 
121     @Override
122     public void onStart( ITestContext context )
123     {
124 
125     }
126 
127     @Override
128     public void onFinish( ITestContext context )
129     {
130 
131     }
132 
133 
134     @Override
135     public void onStart( ISuite suite )
136     {
137 
138     }
139 
140     @Override
141     public void onFinish( ISuite suite )
142     {
143 
144     }
145 
146     /**
147      * Creates a string out of the list of testng groups in the
148      * form of <pre>"group1,group2,group3"</pre>.
149      *
150      * @param groups       The groups being run
151      * @param defaultValue The default to use if no groups
152      * @return a string describing the groups
153      */
154     private static String groupString( String[] groups, String defaultValue )
155     {
156         String retVal;
157         if ( groups != null && groups.length > 0 )
158         {
159             StringBuilder str = new StringBuilder();
160             for ( int i = 0; i < groups.length; i++ )
161             {
162                 str.append( groups[i] );
163                 if ( i + 1 < groups.length )
164                 {
165                     str.append( "," );
166                 }
167             }
168             retVal = str.toString();
169         }
170         else
171         {
172             retVal = defaultValue;
173         }
174         return retVal;
175     }
176 
177     public void onConfigurationFailure( ITestResult result )
178     {
179         onTestFailure( result );
180     }
181 
182     public void onConfigurationSkip( ITestResult result )
183     {
184         onTestSkipped( result );
185     }
186 
187     public void onConfigurationSuccess( ITestResult result )
188     {
189         // DGF Don't record configuration successes as separate tests
190         //onTestSuccess( result );
191     }
192 
193 }