View Javadoc
1   package org.apache.maven.surefire.common.junit4;
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.util.Collection;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.maven.surefire.testset.TestSetFailedException;
30  
31  import org.junit.runner.Description;
32  import org.junit.runner.notification.Failure;
33  
34  import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createRequest;
35  import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
36  import static org.junit.runner.Description.TEST_MECHANISM;
37  
38  /**
39   *
40   * Utility method used among all JUnit4 providers
41   *
42   * @author Qingzhou Luo
43   *
44   */
45  public final class JUnit4ProviderUtil
46  {
47  
48      private JUnit4ProviderUtil()
49      {
50          throw new IllegalStateException( "Cannot instantiate." );
51      }
52  
53      /**
54       * Organize all the failures in previous run into a map between test classes and corresponding failing test methods
55       *
56       * @param allFailures all the failures in previous run
57       * @param testClassLoader ClassLoader used for test classes
58       * @return a map between failing test classes and their corresponding failing test methods
59       */
60      public static Map<Class<?>, Set<String>> generateFailingTests( List<Failure> allFailures,
61                                                                     ClassLoader testClassLoader )
62          throws TestSetFailedException
63      {
64          Map<Class<?>, Set<String>> testClassMethods = new HashMap<Class<?>, Set<String>>();
65          Set<ClassMethod> failingTests = generateFailingTests( allFailures );
66          for ( ClassMethod classMethod: failingTests )
67          {
68              try
69              {
70                  Class testClassObj = Class.forName( classMethod.getClazz(), false, testClassLoader );
71                  Set<String> failingMethods = testClassMethods.get( testClassObj );
72                  if ( failingMethods == null )
73                  {
74                      failingMethods = new HashSet<String>();
75                      testClassMethods.put( testClassObj, failingMethods );
76                  }
77                  failingMethods.add( classMethod.getMethod() );
78              }
79              catch ( ClassNotFoundException e )
80              {
81                  throw new TestSetFailedException( "Unable to create test class '" + classMethod.getClazz() + "'", e );
82              }
83          }
84          return testClassMethods;
85      }
86  
87      /**
88       * Get all test methods from a list of Failures
89       *
90       * @param allFailures the list of failures for a given test class
91       * @return the list of test methods
92       */
93      public static Set<ClassMethod> generateFailingTests( List<Failure> allFailures )
94      {
95          Set<ClassMethod> failingMethods = new HashSet<ClassMethod>();
96  
97          for ( Failure failure : allFailures )
98          {
99              Description description = failure.getDescription();
100             if ( description.isTest() && !isFailureInsideJUnitItself( description ) )
101             {
102                 ClassMethod classMethod = cutTestClassAndMethod( description );
103                 if ( classMethod.isValid() )
104                 {
105                     failingMethods.add( classMethod );
106                 }
107             }
108         }
109         return failingMethods;
110     }
111 
112     public static Description createSuiteDescription( Collection<Class<?>> classes )
113     {
114         return createRequest( classes.toArray( new Class[classes.size()] ) ).getRunner().getDescription();
115     }
116 
117     public static boolean isFailureInsideJUnitItself( Description failure )
118     {
119         return TEST_MECHANISM.equals( failure );
120     }
121 
122     /**
123      * Java Patterns of regex is slower than cutting a substring.
124      * @param description method(class) or method[#](class) or method[#whatever-literals](class)
125      * @return method JUnit test method
126      */
127     public static ClassMethod cutTestClassAndMethod( Description description )
128     {
129         String name = description.getDisplayName();
130         String clazz = null;
131         String method = null;
132         if ( name != null )
133         {
134             // The order is : 1.method and then 2.class
135             // method(class)
136             name = name.trim();
137             if ( name.endsWith( ")" ) )
138             {
139                 int classBracket = name.lastIndexOf( '(' );
140                 if ( classBracket != -1 )
141                 {
142                     clazz = tryBlank( name.substring( classBracket + 1, name.length() - 1 ) );
143                     method = tryBlank( name.substring( 0, classBracket ) );
144                 }
145             }
146         }
147         return new ClassMethod( clazz, method );
148     }
149 
150     private static String tryBlank( String s )
151     {
152         s = s.trim();
153         return isBlank( s ) ? null : s;
154     }
155 
156 }