View Javadoc
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 }