View Javadoc
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  import org.apache.maven.surefire.api.util.internal.ClassMethod;
23  import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
24  import org.apache.maven.surefire.api.report.ConsoleOutputReceiver;
25  import org.apache.maven.surefire.api.report.RunListener;
26  import org.apache.maven.surefire.api.report.SimpleReportEntry;
27  import org.apache.maven.surefire.api.report.TestSetReportEntry;
28  import org.apache.maven.surefire.api.testset.TestSetFailedException;
29  import org.junit.runner.Description;
30  import org.junit.runner.Result;
31  import org.junit.runner.notification.Failure;
32  
33  import java.util.Collections;
34  import java.util.Map;
35  
36  import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod;
37  import static org.apache.maven.surefire.api.util.internal.ObjectUtils.systemProps;
38  
39  /**
40   * A class to be used when there is no JUnit parallelism (methods or/and class). This allow to workaround JUnit
41   * limitation a la Junit4 provider. Specifically, we can redirect properly the output even if we don't have class
42   * demarcation in JUnit. It works when if there is a JVM instance per test run, i.e. with forkMode=always or perthread.
43   */
44  public class NonConcurrentRunListener
45      extends JUnit4RunListener
46      implements ConsoleOutputReceiver
47  {
48      private Description currentTestSetDescription;
49  
50      private Description lastFinishedDescription;
51  
52      public NonConcurrentRunListener( RunListener reporter )
53          throws TestSetFailedException
54      {
55          super( reporter );
56      }
57  
58      public synchronized void writeTestOutput( String output, boolean newLine, boolean stdout )
59      {
60          // We can write immediately: no parallelism and a single class.
61          ( (ConsoleOutputReceiver) reporter ).writeTestOutput( output, newLine, stdout );
62      }
63  
64      @Override
65      protected SimpleReportEntry createReportEntry( Description description )
66      {
67          ClassMethod classMethod = toClassMethod( description );
68          return new SimpleReportEntry( classMethod.getClazz(), null, classMethod.getMethod(), null );
69      }
70  
71      private TestSetReportEntry createReportEntryForTestSet( Description description, Map<String, String> systemProps )
72      {
73          ClassMethod classMethod = toClassMethod( description );
74          return new SimpleReportEntry( classMethod.getClazz(), null, null, null, systemProps );
75      }
76  
77      private TestSetReportEntry createTestSetReportEntryStarted( Description description )
78      {
79          return createReportEntryForTestSet( description, Collections.<String, String>emptyMap() );
80      }
81  
82      private TestSetReportEntry createTestSetReportEntryFinished( Description description )
83      {
84          return createReportEntryForTestSet( description, systemProps() );
85      }
86  
87      @Override
88      public void testStarted( Description description )
89          throws Exception
90      {
91          finishLastTestSetIfNecessary( description );
92          super.testStarted( description );
93      }
94  
95      private void finishLastTestSetIfNecessary( Description description )
96      {
97          if ( describesNewTestSet( description ) )
98          {
99              currentTestSetDescription = description;
100             if ( lastFinishedDescription != null )
101             {
102                 TestSetReportEntry reportEntry = createTestSetReportEntryFinished( lastFinishedDescription );
103                 reporter.testSetCompleted( reportEntry );
104                 lastFinishedDescription = null;
105             }
106             reporter.testSetStarting( createTestSetReportEntryStarted( description ) );
107         }
108     }
109 
110     private boolean describesNewTestSet( Description description )
111     {
112         if ( currentTestSetDescription != null )
113         {
114             if ( null != description.getTestClass() )
115             {
116                 return !description.getTestClass().equals( currentTestSetDescription.getTestClass() );
117             }
118             else if ( description.isSuite() )
119             {
120                 return description.getChildren().equals( currentTestSetDescription.getChildren() );
121             }
122 
123             return false;
124         }
125 
126         return true;
127     }
128 
129     @Override
130     public void testFinished( Description description )
131         throws Exception
132     {
133         super.testFinished( description );
134         lastFinishedDescription = description;
135     }
136 
137     @Override
138     public void testIgnored( Description description )
139         throws Exception
140     {
141         finishLastTestSetIfNecessary( description );
142 
143         super.testIgnored( description );
144         lastFinishedDescription = description;
145     }
146 
147     @Override
148     public void testFailure( Failure failure )
149         throws Exception
150     {
151         finishLastTestSetIfNecessary( failure.getDescription() );
152 
153         super.testFailure( failure );
154         lastFinishedDescription = failure.getDescription();
155     }
156 
157     @Override
158     public void testAssumptionFailure( Failure failure )
159     {
160         super.testAssumptionFailure( failure );
161         lastFinishedDescription = failure.getDescription();
162     }
163 
164     @Override
165     public void testRunStarted( Description description )
166         throws Exception
167     {
168     }
169 
170     @Override
171     public void testRunFinished( Result result )
172         throws Exception
173     {
174         if ( lastFinishedDescription != null )
175         {
176             reporter.testSetCompleted( createTestSetReportEntryFinished( lastFinishedDescription ) );
177             lastFinishedDescription = null;
178         }
179     }
180 }