Coverage Report - org.apache.maven.surefire.common.junit4.JUnit4RunListener
 
Classes in this File Line Coverage Branch Coverage Complexity
JUnit4RunListener
52%
30/57
29%
7/24
2,071
 
 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 org.apache.maven.surefire.report.ReportEntry;
 23  
 import org.apache.maven.surefire.report.RunListener;
 24  
 import org.apache.maven.surefire.report.SimpleReportEntry;
 25  
 import org.apache.maven.surefire.report.StackTraceWriter;
 26  
 import org.apache.maven.surefire.testset.TestSetFailedException;
 27  
 import org.junit.runner.Description;
 28  
 import org.junit.runner.Result;
 29  
 import org.junit.runner.notification.Failure;
 30  
 
 31  
 import java.util.regex.Matcher;
 32  
 import java.util.regex.Pattern;
 33  
 
 34  
 public class JUnit4RunListener
 35  
     extends org.junit.runner.notification.RunListener
 36  
 {
 37  1
     private static final Pattern PARENS = Pattern.compile( "^" + ".+" //any character
 38  
                                                                + "\\(("
 39  
                                                                // then an open-paren (start matching a group)
 40  
                                                                + "[^\\\\(\\\\)]+" //non-parens
 41  
                                                                + ")\\)" + "$" );
 42  
 
 43  
     protected final RunListener reporter;
 44  
 
 45  
     /**
 46  
      * This flag is set after a failure has occurred so that a <code>testSucceeded</code> event is not fired.
 47  
      * This is necessary because JUnit4 always fires a <code>testRunFinished</code> event-- even if there was a failure.
 48  
      */
 49  2
     private final ThreadLocal<Boolean> failureFlag = new InheritableThreadLocal<Boolean>();
 50  
 
 51  2
     private final JUnit4Reflector jUnit4Reflector = new JUnit4Reflector();
 52  
 
 53  
     /**
 54  
      * Constructor.
 55  
      *
 56  
      * @param reporter the reporter to log testing events to
 57  
      */
 58  
     public JUnit4RunListener( RunListener reporter )
 59  2
     {
 60  2
         this.reporter = reporter;
 61  2
     }
 62  
 
 63  
     // Testrun methods are not invoked when using the runner
 64  
 
 65  
     /**
 66  
      * Called when a specific test has been skipped (for whatever reason).
 67  
      *
 68  
      * @see org.junit.runner.notification.RunListener#testIgnored(org.junit.runner.Description)
 69  
      */
 70  
     public void testIgnored( Description description )
 71  
         throws Exception
 72  
     {
 73  0
         final String reason = jUnit4Reflector.getAnnotatedIgnoreValue( description );
 74  0
         final SimpleReportEntry report =
 75  
             SimpleReportEntry.ignored( getClassName( description ), description.getDisplayName(), reason );
 76  0
         reporter.testSkipped( report );
 77  0
     }
 78  
 
 79  
     /**
 80  
      * Called when a specific test has started.
 81  
      *
 82  
      * @see org.junit.runner.notification.RunListener#testStarted(org.junit.runner.Description)
 83  
      */
 84  
     public void testStarted( Description description )
 85  
         throws Exception
 86  
     {
 87  4
         reporter.testStarting( createReportEntry( description ) );
 88  4
         failureFlag.remove();
 89  4
     }
 90  
 
 91  
     /**
 92  
      * Called when a specific test has failed.
 93  
      *
 94  
      * @see org.junit.runner.notification.RunListener#testFailure(org.junit.runner.notification.Failure)
 95  
      */
 96  
     @SuppressWarnings( { "ThrowableResultOfMethodCallIgnored" } )
 97  
     public void testFailure( Failure failure )
 98  
         throws Exception
 99  
     {
 100  1
         String testHeader = failure.getTestHeader();
 101  1
         if ( isInsaneJunitNullString( testHeader ) )
 102  
         {
 103  0
             testHeader = "Failure when constructing test";
 104  
         }
 105  1
         ReportEntry report = SimpleReportEntry.withException( getClassName( failure.getDescription() ), testHeader,
 106  
                                                               createStackTraceWriter( failure ) );
 107  
 
 108  1
         if ( failure.getException() instanceof AssertionError )
 109  
         {
 110  1
             this.reporter.testFailed( report );
 111  
         }
 112  
         else
 113  
         {
 114  0
             this.reporter.testError( report );
 115  
         }
 116  1
         failureFlag.set( Boolean.TRUE );
 117  1
     }
 118  
 
 119  
     protected StackTraceWriter createStackTraceWriter( Failure failure )
 120  
     {
 121  1
         return new JUnit4StackTraceWriter( failure );
 122  
     }
 123  
 
 124  
     @SuppressWarnings( { "UnusedDeclaration" } )
 125  
     public void testAssumptionFailure( Failure failure )
 126  
     {
 127  0
         this.reporter.testAssumptionFailure( createReportEntry( failure.getDescription() ) );
 128  0
         failureFlag.set( Boolean.TRUE );
 129  0
     }
 130  
 
 131  
 
 132  
     /**
 133  
      * Called after a specific test has finished.
 134  
      *
 135  
      * @see org.junit.runner.notification.RunListener#testFinished(org.junit.runner.Description)
 136  
      */
 137  
     public void testFinished( Description description )
 138  
         throws Exception
 139  
     {
 140  4
         Boolean failure = failureFlag.get();
 141  4
         if ( failure == null )
 142  
         {
 143  3
             reporter.testSucceeded( createReportEntry( description ) );
 144  
         }
 145  4
     }
 146  
 
 147  
     protected SimpleReportEntry createReportEntry( Description description )
 148  
     {
 149  7
         return new SimpleReportEntry( getClassName( description ), description.getDisplayName() );
 150  
     }
 151  
 
 152  
     public String getClassName( Description description )
 153  
     {
 154  8
         String name = extractClassName( description );
 155  8
         if ( name == null || isInsaneJunitNullString( name ) )
 156  
         {
 157  
             // This can happen upon early failures (class instantiation error etc)
 158  0
             Description subDescription = description.getChildren().get( 0 );
 159  0
             if ( subDescription != null )
 160  
             {
 161  0
                 name = extractClassName( subDescription );
 162  
             }
 163  0
             if ( name == null )
 164  
             {
 165  0
                 name = "Test Instantiation Error";
 166  
             }
 167  
         }
 168  8
         return name;
 169  
     }
 170  
 
 171  
     private boolean isInsaneJunitNullString( String value )
 172  
     {
 173  9
         return "null".equals( value );
 174  
     }
 175  
 
 176  
     public static String extractClassName( Description description )
 177  
     {
 178  8
         String displayName = description.getDisplayName();
 179  8
         Matcher m = PARENS.matcher( displayName );
 180  8
         if ( !m.find() )
 181  
         {
 182  0
             return displayName;
 183  
         }
 184  8
         return m.group( 1 );
 185  
     }
 186  
 
 187  
     public static String extractMethodName( Description description )
 188  
     {
 189  0
         String displayName = description.getDisplayName();
 190  0
         int i = displayName.indexOf( "(" );
 191  0
         if (i >= 0 ) return displayName.substring( 0, i );
 192  0
         return displayName;
 193  
     }
 194  
 
 195  
 
 196  
     public static void rethrowAnyTestMechanismFailures( Result run )
 197  
         throws TestSetFailedException
 198  
     {
 199  0
         if ( run.getFailureCount() > 0 )
 200  
         {
 201  0
             for ( Failure failure : run.getFailures() )
 202  
             {
 203  0
                 if ( isFailureInsideJUnitItself( failure ) )
 204  
                 {
 205  0
                     final Throwable exception = failure.getException();
 206  0
                     throw new TestSetFailedException( exception );
 207  
                 }
 208  0
             }
 209  
         }
 210  0
     }
 211  
 
 212  
     private static boolean isFailureInsideJUnitItself( Failure failure )
 213  
     {
 214  0
         return failure.getDescription().getDisplayName().equals( "Test mechanism" );
 215  
     }
 216  
 }