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