View Javadoc

1   package org.apache.maven.surefire.junit;
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.PojoStackTraceWriter;
23  import org.apache.maven.surefire.report.RunListener;
24  import org.apache.maven.surefire.report.ReportEntry;
25  import org.apache.maven.surefire.report.SimpleReportEntry;
26  import org.apache.maven.surefire.testset.TestSetFailedException;
27  
28  import java.lang.reflect.InvocationTargetException;
29  import java.lang.reflect.Method;
30  import java.lang.reflect.Modifier;
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  public class PojoTestSet
35      implements SurefireTestSet
36  {
37  
38      private static final String TEST_METHOD_PREFIX = "test";
39  
40      private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
41  
42      private final Object testObject;
43  
44      private List testMethods;
45      
46      private Method setUpMethod;
47      
48      private Method tearDownMethod;
49  
50      private final Class testClass;
51  
52      public PojoTestSet( Class testClass )
53          throws TestSetFailedException
54      {
55          if ( testClass == null )
56          {
57              throw new NullPointerException( "testClass is null" );
58          }
59  
60          this.testClass = testClass;
61  
62          try
63          {
64              testObject = testClass.newInstance();
65          }
66          catch ( InstantiationException e )
67          {
68              throw new TestSetFailedException( "Unable to instantiate POJO '" + testClass + "'", e );
69          }
70          catch ( IllegalAccessException e )
71          {
72              throw new TestSetFailedException( "Unable to instantiate POJO '" + testClass + "'", e );
73          }
74      }
75  
76      public void execute( RunListener reportManager, ClassLoader loader )
77          throws TestSetFailedException
78      {
79          if ( reportManager == null )
80          {
81              throw new NullPointerException( "reportManager is null" );
82          }
83  
84          executeTestMethods( reportManager );
85      }
86  
87      private void executeTestMethods( RunListener reportManager )
88      {
89          if ( reportManager == null )
90          {
91              throw new NullPointerException( "reportManager is null" );
92          }
93  
94          if ( testMethods == null )
95          {
96              discoverTestMethods();
97          }
98  
99          boolean abort = false;
100 
101         for ( int i = 0; i < testMethods.size() && !abort; ++i )
102         {
103             abort = executeTestMethod( (Method) testMethods.get( i ), EMPTY_OBJECT_ARRAY, reportManager );
104         }
105     }
106 
107     private boolean executeTestMethod( Method method, Object[] args, RunListener reportManager )
108     {
109         if ( method == null || args == null || reportManager == null )
110         {
111             throw new NullPointerException();
112         }
113 
114         String userFriendlyMethodName = method.getName() + '(';
115 
116         if ( args.length != 0 )
117         {
118             userFriendlyMethodName += "Reporter";
119         }
120 
121         userFriendlyMethodName += ')';
122 
123         ReportEntry report =
124             new SimpleReportEntry( testObject.getClass().getName(), getTestName( userFriendlyMethodName ) );
125 
126         reportManager.testStarting( report );
127 
128         try
129         {
130             setUpFixture();
131         }
132         catch ( Throwable e )
133         {
134             report = new SimpleReportEntry( testObject.getClass().getName(), getTestName( userFriendlyMethodName ),
135                                             new PojoStackTraceWriter( testObject.getClass().getName(), method.getName(),
136                                                                       e ) );
137 
138             reportManager.testFailed( report );
139 
140             // A return value of true indicates to this class's executeTestMethods
141             // method that it should abort and not attempt to execute
142             // any other test methods. The other caller of this method,
143             // TestRerunner.rerun, ignores this return value, because it is
144             // only running one test.
145             return true;
146         }
147 
148         // Make sure that tearDownFixture
149         try
150         {
151             method.invoke( testObject, args );
152 
153             report = new SimpleReportEntry( testObject.getClass().getName(), getTestName( userFriendlyMethodName ) );
154 
155             reportManager.testSucceeded( report );
156         }
157         catch ( InvocationTargetException ite )
158         {
159             Throwable t = ite.getTargetException();
160 
161             report = new SimpleReportEntry( testObject.getClass().getName(), getTestName( userFriendlyMethodName ),
162                                             new PojoStackTraceWriter( testObject.getClass().getName(), method.getName(),
163                                                                       t ) );
164 
165             reportManager.testFailed( report );
166             // Don't return  here, because tearDownFixture should be called even
167             // if the test method throws an exception.
168         }
169         catch ( Throwable t )
170         {
171             report = new SimpleReportEntry( testObject.getClass().getName(), getTestName( userFriendlyMethodName ),
172                                             new PojoStackTraceWriter( testObject.getClass().getName(), method.getName(),
173                                                                       t ) );
174 
175             reportManager.testFailed( report );
176             // Don't return  here, because tearDownFixture should be called even
177             // if the test method throws an exception.
178         }
179 
180         try
181         {
182             tearDownFixture();
183         }
184         catch ( Throwable t )
185         {
186             // Treat any exception from tearDownFixture as a failure of the test.
187             report = new SimpleReportEntry( testObject.getClass().getName(), getTestName( userFriendlyMethodName ),
188                                             new PojoStackTraceWriter( testObject.getClass().getName(), method.getName(),
189                                                                       t ) );
190 
191             reportManager.testFailed( report );
192 
193             // A return value of true indicates to this class's executeTestMethods
194             // method that it should abort and not attempt to execute
195             // any other test methods. The other caller of this method,
196             // TestRerunner.rerun, ignores this return value, because it is
197             // only running one test.
198             return true;
199         }
200 
201         // A return value of false indicates to this class's executeTestMethods
202         // method that it should keep plowing ahead and invoke more test methods.
203         // The other caller of this method,
204         // TestRerunner.rerun, ignores this return value, because it is
205         // only running one test.
206         return false;
207     }
208 
209     private String getTestName( String testMethodName )
210     {
211         if ( testMethodName == null )
212         {
213             throw new NullPointerException( "testMethodName is null" );
214         }
215 
216         return getTestClass().getName() + "." + testMethodName;
217     }
218 
219     private void setUpFixture() throws Throwable
220     {
221     	if (setUpMethod != null) setUpMethod.invoke( testObject, new Object[0] );        
222     }
223 
224     private void tearDownFixture() throws Throwable
225     {
226     	if (tearDownMethod != null) tearDownMethod.invoke( testObject, new Object[0] );        
227     }
228 
229     private void discoverTestMethods()
230     {
231         if ( testMethods == null )
232         {
233             testMethods = new ArrayList();
234 
235             Method[] methods = getTestClass().getMethods();
236 
237             for ( int i = 0; i < methods.length; ++i )
238             {
239                 Method m = methods[i];
240 
241                 if ( isValidTestMethod( m ) )
242                 {
243                     String simpleName = m.getName();
244 
245                     // name must have 5 or more chars
246                     if ( simpleName.length() > 4 )
247                     {
248                         String firstFour = simpleName.substring( 0, 4 );
249 
250                         // name must start with "test"
251                         if ( firstFour.equals( TEST_METHOD_PREFIX ) )
252                         {
253                             testMethods.add( m );
254                         }
255                     }
256                 }
257                 else if (m.getName().equals("setUp") && m.getParameterTypes().length == 0)
258                 {
259                 	setUpMethod = m;
260                 }
261                 else if (m.getName().equals("tearDown") && m.getParameterTypes().length == 0)
262                 {
263                 	tearDownMethod = m;
264                 }
265             }
266         }
267     }
268 
269     private static boolean isValidTestMethod( Method m )
270     {
271         boolean isInstanceMethod = !Modifier.isStatic( m.getModifiers() );
272 
273         boolean returnsVoid = m.getReturnType().equals( void.class );
274 
275         boolean hasNoParams = m.getParameterTypes().length == 0;
276 
277         return isInstanceMethod && returnsVoid && hasNoParams;
278     }
279 
280     public String getName()
281     {
282         return testClass.getName();
283     }
284 
285     public Class getTestClass()
286     {
287         return testClass;
288     }
289 }