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