1 package org.apache.maven.surefire.junitcore; 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 /* 23 * JBoss, Home of Professional Open Source 24 * Copyright 2009, Red Hat Middleware LLC, and individual contributors 25 * by the @authors tag. See the copyright.txt in the distribution for a 26 * full listing of individual contributors. 27 * 28 * Licensed under the Apache License, Version 2.0 (the "License"); 29 * you may not use this file except in compliance with the License. 30 * You may obtain a copy of the License at 31 * http://www.apache.org/licenses/LICENSE-2.0 32 * Unless required by applicable law or agreed to in writing, software 33 * distributed under the License is distributed on an "AS IS" BASIS, 34 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 * See the License for the specific language governing permissions and 36 * limitations under the License. 37 */ 38 39 import junit.framework.Assert; 40 import junit.framework.TestCase; 41 import org.junit.BeforeClass; 42 import org.junit.Test; 43 import org.junit.runner.Result; 44 import org.junit.runner.notification.Failure; 45 46 /** 47 * TestCase that expose "No tests were executed!" on Test failure using Maven Surefire 2.6-SNAPSHOT 48 * and the JUnit 4.8 Runner. 49 * {@code 50 * * <br> 51 * ------------------------------------------------------- 52 * T E S T S 53 * ------------------------------------------------------- 54 * <br> 55 * Results: 56 * <br> 57 * Tests run: 0, Failures: 0, Errors: 0, Skipped: 0 58 * <br> 59 * [INFO] ------------------------------------------------------------------------ 60 * [INFO] BUILD FAILURE 61 * [INFO] ------------------------------------------------------------------------ 62 * [INFO] Total time: 11.011s 63 * [INFO] Finished at: Thu Jul 15 13:59:14 CEST 2010 64 * [INFO] Final Memory: 24M/355M 65 * [INFO] ------------------------------------------------------------------------ 66 * [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.5:test 67 * (default-test) on project xxxxxx: No tests were executed! (Set -DfailIfNoTests=false to 68 * ignore this error.) -> [Help 1] 69 * <br> 70 * <br> 71 * <dependency> 72 * <groupId>junit</groupId> 73 * <artifactId>junit</artifactId> 74 * <version>4.8.1</version> 75 * <scope>test</scope> 76 * </dependency> 77 * <br> 78 * <dependency> 79 * <groupId>org.apache.maven.surefire</groupId> 80 * <artifactId>surefire-booter</artifactId> 81 * <version>2.6-SNAPSHOT</version> 82 * <scope>test</scope> 83 * </dependency> 84 * <dependency> 85 * <groupId>org.apache.maven.plugins</groupId> 86 * <artifactId>maven-surefire-plugin</artifactId> 87 * <version>2.6-SNAPSHOT</version> 88 * <scope>test</scope> 89 * </dependency> 90 * <dependency> 91 * <groupId>org.apache.maven.surefire</groupId> 92 * <artifactId>surefire-junit48</artifactId> 93 * <version>2.6-SNAPSHOT</version> 94 * <scope>test</scope> 95 * </dependency> 96 * } 97 * 98 * @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a> 99 * @version $Revision: $ 100 */ 101 public class MavenSurefireJUnit48RunnerTest 102 extends TestCase 103 { 104 105 /* 106 * Assumption: 107 * The ConcurrentReportingRunListener assumes a Test will be Started before it Fails or Finishes. 108 * 109 * Reality: 110 * JUnits ParentRunner is responsible for adding the BeforeClass/AfterClass statements to the 111 * statement execution chain. After BeforeClass is executed, a Statement that delegates to the 112 * abstract method: runChild(T child, RunNotifier notifier) is called. As the JavaDoc explains: 113 * "Subclasses are responsible for making sure that relevant test events are reported through <b>notifier</b>". 114 * When a @BeforeClass fail, the child that should handle the relevant test events(Started, Failed, Finished) 115 * is never executed. 116 * 117 * Result: 118 * When Test Failed event is received in ConcurrentReportingRunListener without a Started event received first, 119 * it causes a NullPointException because there is no ClassReporter setup for that class yet. When this Exception 120 * is thrown from the ConcurrentReportingRunListener, JUnit catches the exception and reports is as a Failed test. 121 * But to avoid a wild loop, it removes the failing Listener before calling Failed test again. Since the 122 * ConcurrentReportingRunListener now is removed from the chain it will never receive the RunFinished event 123 * and the recorded state will never be replayed on the ReportManager. 124 * 125 * The End result: ReporterManager falsely believe no Test were run. 126 * 127 */ 128 @SuppressWarnings( { "unchecked", "ThrowableResultOfMethodCallIgnored" } ) 129 public void testSurefireShouldBeAbleToReportRunStatusEvenWithFailingTests() 130 throws Exception 131 { 132 Result result = new JUnitCoreTester().run( false, FailingTestClassTestNot.class ); 133 134 Assert.assertEquals( "JUnit should report correctly number of test ran(Finished)", 0, result.getRunCount() ); 135 136 for ( Failure failure : result.getFailures() ) 137 { 138 System.out.println( failure.getException().getMessage() ); 139 } 140 141 Assert.assertEquals( "There should only be one Exception reported, the one from the failing TestCase", 1, 142 result.getFailureCount() ); 143 144 Assert.assertEquals( "The exception thrown by the failing TestCase", RuntimeException.class, 145 result.getFailures().get( 0 ).getException().getClass() ); 146 147 } 148 149 /** 150 * Simple TestCase to force a Exception in @BeforeClass. 151 */ 152 public static class FailingTestClassTestNot 153 { 154 @BeforeClass 155 public static void failingBeforeClass() 156 throws Exception 157 { 158 throw new RuntimeException( "Opps, we failed in @BeforeClass" ); 159 } 160 161 @Test 162 public void shouldNeverBeCalled() 163 throws Exception 164 { 165 Assert.assertTrue( true ); 166 } 167 } 168 }