View Javadoc
1   package org.apache.maven.plugin.failsafe;
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 java.io.BufferedInputStream;
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.IOException;
26  import java.io.InputStreamReader;
27  import java.io.Reader;
28  import java.util.Collection;
29  
30  import org.apache.maven.execution.MavenSession;
31  import org.apache.maven.plugin.AbstractMojo;
32  import org.apache.maven.plugin.MojoExecutionException;
33  import org.apache.maven.plugin.MojoFailureException;
34  import org.apache.maven.plugin.surefire.SurefireHelper;
35  import org.apache.maven.plugin.surefire.SurefireReportParameters;
36  import org.apache.maven.plugins.annotations.Component;
37  import org.apache.maven.plugins.annotations.LifecyclePhase;
38  import org.apache.maven.plugins.annotations.Mojo;
39  import org.apache.maven.plugins.annotations.Parameter;
40  import org.apache.maven.shared.utils.ReaderFactory;
41  import org.apache.maven.shared.utils.StringUtils;
42  import org.apache.maven.shared.utils.io.IOUtil;
43  import org.apache.maven.surefire.cli.CommandLineOption;
44  import org.apache.maven.surefire.suite.RunResult;
45  
46  /**
47   * Verify integration tests ran using Surefire.
48   *
49   * @author Stephen Connolly
50   * @author Jason van Zyl
51   */
52  @Mojo( name = "verify", defaultPhase = LifecyclePhase.VERIFY, requiresProject = true, threadSafe = true )
53  public class VerifyMojo
54      extends AbstractMojo
55      implements SurefireReportParameters
56  {
57  
58      /**
59       * Set this to 'true' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite
60       * convenient on occasion.
61       *
62       * @since 2.4
63       */
64      @Parameter( property = "skipTests" )
65      private boolean skipTests;
66  
67      /**
68       * Set this to 'true' to skip running integration tests, but still compile them. Its use is NOT RECOMMENDED, but
69       * quite convenient on occasion.
70       *
71       * @since 2.4.3-alpha-2
72       */
73      @Parameter( property = "skipITs" )
74      private boolean skipITs;
75  
76      /**
77       * This old parameter is just like skipTests, but bound to the old property maven.test.skip.exec.
78       *
79       * @since 2.3
80       * @deprecated Use -DskipTests instead.
81       */
82      @Parameter( property = "maven.test.skip.exec" )
83      private boolean skipExec;
84  
85      /**
86       * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, especially if you
87       * enable it using the "maven.test.skip" property, because maven.test.skip disables both running the
88       * tests and compiling the tests.  Consider using the skipTests parameter instead.
89       */
90      @Parameter( property = "maven.test.skip", defaultValue = "false" )
91      private boolean skip;
92  
93      /**
94       * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on
95       * occasion.
96       */
97      @Parameter( property = "maven.test.failure.ignore", defaultValue = "false" )
98      private boolean testFailureIgnore;
99  
100     /**
101      * The base directory of the project being tested. This can be obtained in your unit test by
102      * System.getProperty("basedir").
103      */
104     @Parameter( defaultValue = "${basedir}" )
105     private File basedir;
106 
107     /**
108      * The directory containing generated test classes of the project being tested.
109      * This will be included at the beginning the test classpath.
110      */
111     @Parameter( defaultValue = "${project.build.testOutputDirectory}" )
112     private File testClassesDirectory;
113 
114     /**
115      * Base directory where all reports are written to.
116      */
117     @Parameter( defaultValue = "${project.build.directory}/failsafe-reports" )
118     private File reportsDirectory;
119 
120     /**
121      * The summary file to read integration test results from.
122      *
123      * @noinspection UnusedDeclaration
124      */
125     @Parameter( defaultValue = "${project.build.directory}/failsafe-reports/failsafe-summary.xml", required = true )
126     private File summaryFile;
127 
128     /**
129      * Additional summary files to read integration test results from.
130      *
131      * @noinspection UnusedDeclaration, MismatchedReadAndWriteOfArray
132      * @since 2.6
133      */
134     @Parameter
135     private File[] summaryFiles;
136 
137     /**
138      * Set this to "true" to cause a failure if there are no tests to run.
139      *
140      * @since 2.4
141      */
142     @Parameter( property = "failIfNoTests" )
143     private Boolean failIfNoTests;
144 
145     /**
146      * The character encoding scheme to be applied.
147      *
148      * @noinspection UnusedDeclaration
149      */
150     @Parameter( property = "encoding", defaultValue = "${project.reporting.outputEncoding}" )
151     private String encoding;
152 
153     /**
154      * The current build session instance.
155      */
156     @Component
157     private MavenSession session;
158 
159     private Collection<CommandLineOption> cli;
160 
161     public void execute()
162         throws MojoExecutionException, MojoFailureException
163     {
164         cli = commandLineOptions();
165         if ( verifyParameters() )
166         {
167             logDebugOrCliShowErrors(
168                 StringUtils.capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
169 
170             RunResult summary;
171             try
172             {
173                 final String encoding;
174                 if ( StringUtils.isEmpty( this.encoding ) )
175                 {
176                     getLog().warn( "File encoding has not been set, using platform encoding "
177                             + ReaderFactory.FILE_ENCODING
178                             + ", i.e. build is platform dependent! The file encoding for reports output files "
179                             + "should be provided by the POM property ${project.reporting.outputEncoding}." );
180                     encoding = ReaderFactory.FILE_ENCODING;
181                 }
182                 else
183                 {
184                     encoding = this.encoding;
185                 }
186 
187                 summary = existsSummaryFile() ? readSummary( encoding, summaryFile ) : RunResult.noTestsRun();
188 
189                 if ( existsSummaryFiles() )
190                 {
191                     for ( final File summaryFile : summaryFiles )
192                     {
193                         summary = summary.aggregate( readSummary( encoding, summaryFile ) );
194                     }
195                 }
196             }
197             catch ( IOException e )
198             {
199                 throw new MojoExecutionException( e.getMessage(), e );
200             }
201 
202             SurefireHelper.reportExecution( this, summary, getLog() );
203         }
204     }
205 
206     private RunResult readSummary( String encoding, File summaryFile )
207         throws IOException
208     {
209         FileInputStream fileInputStream = null;
210         BufferedInputStream bufferedInputStream = null;
211         Reader reader = null;
212         try
213         {
214             fileInputStream = new FileInputStream( summaryFile );
215             bufferedInputStream = new BufferedInputStream( fileInputStream );
216             reader = new InputStreamReader( bufferedInputStream, encoding );
217             return RunResult.fromInputStream( bufferedInputStream, encoding );
218         }
219         finally
220         {
221             IOUtil.close( reader );
222             IOUtil.close( bufferedInputStream );
223             IOUtil.close( fileInputStream );
224         }
225     }
226 
227     protected boolean verifyParameters()
228         throws MojoFailureException
229     {
230         if ( isSkip() || isSkipTests() || isSkipITs() || isSkipExec() )
231         {
232             getLog().info( "Tests are skipped." );
233             return false;
234         }
235 
236         if ( !getTestClassesDirectory().exists() )
237         {
238             if ( getFailIfNoTests() != null && getFailIfNoTests() )
239             {
240                 throw new MojoFailureException( "No tests to run!" );
241             }
242         }
243 
244         if ( !existsSummary() )
245         {
246             getLog().info( "No tests to run." );
247             return false;
248         }
249 
250         return true;
251     }
252 
253     protected String getPluginName()
254     {
255         return "failsafe";
256     }
257 
258     protected String[] getDefaultIncludes()
259     {
260         return null;
261     }
262 
263     public boolean isSkipTests()
264     {
265         return skipTests;
266     }
267 
268     public void setSkipTests( boolean skipTests )
269     {
270         this.skipTests = skipTests;
271     }
272 
273     public boolean isSkipITs()
274     {
275         return skipITs;
276     }
277 
278     public void setSkipITs( boolean skipITs )
279     {
280         this.skipITs = skipITs;
281     }
282 
283     @Deprecated
284     public boolean isSkipExec()
285     {
286         return skipExec;
287     }
288 
289     @Deprecated
290     public void setSkipExec( boolean skipExec )
291     {
292         this.skipExec = skipExec;
293     }
294 
295     public boolean isSkip()
296     {
297         return skip;
298     }
299 
300     public void setSkip( boolean skip )
301     {
302         this.skip = skip;
303     }
304 
305     public boolean isTestFailureIgnore()
306     {
307         return testFailureIgnore;
308     }
309 
310     public void setTestFailureIgnore( boolean testFailureIgnore )
311     {
312         this.testFailureIgnore = testFailureIgnore;
313     }
314 
315     public File getBasedir()
316     {
317         return basedir;
318     }
319 
320     public void setBasedir( File basedir )
321     {
322         this.basedir = basedir;
323     }
324 
325     public File getTestClassesDirectory()
326     {
327         return testClassesDirectory;
328     }
329 
330     public void setTestClassesDirectory( File testClassesDirectory )
331     {
332         this.testClassesDirectory = testClassesDirectory;
333     }
334 
335     public File getReportsDirectory()
336     {
337         return reportsDirectory;
338     }
339 
340     public void setReportsDirectory( File reportsDirectory )
341     {
342         this.reportsDirectory = reportsDirectory;
343     }
344 
345     public Boolean getFailIfNoTests()
346     {
347         return failIfNoTests;
348     }
349 
350     public void setFailIfNoTests( boolean failIfNoTests )
351     {
352         this.failIfNoTests = failIfNoTests;
353     }
354 
355     private boolean existsSummaryFile()
356     {
357         return summaryFile != null && summaryFile.isFile();
358     }
359 
360     private boolean existsSummaryFiles()
361     {
362         return summaryFiles != null && summaryFiles.length != 0;
363     }
364 
365     private boolean existsSummary()
366     {
367         return existsSummaryFile() || existsSummaryFiles();
368     }
369 
370     private Collection<CommandLineOption> commandLineOptions()
371     {
372         return SurefireHelper.commandLineOptions( session, getLog() );
373     }
374 
375     private void logDebugOrCliShowErrors( CharSequence s )
376     {
377         SurefireHelper.logDebugOrCliShowErrors( s, getLog(), cli );
378     }
379 
380 }