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