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