You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2018/08/23 19:27:46 UTC

[maven-surefire] branch V30_SUREFIRE-1535 updated (3b45831 -> 15ab547)

This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a change to branch V30_SUREFIRE-1535
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git.


    from 3b45831  [SUREFIRE-1535] Surefire unable to run testng suites in parallel - integration test
     add a68e574  [SUREFIRE-1538] Git considers PNG files as changed although there is no change
     add 19ea21e  Use lowercase file extensions for PNG
     add 2beecc6  [SUREFIRE-1552] Nil element "failureMessage" in failsafe-summary.xml should have self closed tag
     add 5fca693  [jenkinsfile] [jdk 1.7] Could not transfer artifact ... SSLException: Received fatal alert: protocol_version
     add 4e22fe7  [jenkinsfile] [jdk 1.7] Could not transfer artifact ... SSLException: Received fatal alert: protocol_version
     add ef078ca  [SUREFIRE-1554] Fix old test resources TEST-*.xml in favor of continuing with SUREFIRE-1550
     add 58b1ce4  [jenkinsfile] every Windows
     add 5a5d80d  SUREFIRE-1555] Elapsed time in XML Report should satisfy pattern in XSD.
     add 429a239  [SUREFIRE-1550] The surefire XSD published on maven site lacks of some rerun element
     new e59ecf7  Merge branch 'master' of https://gitbox.apache.org/repos/asf/maven-surefire into suites_in_parallel
     new 15ab547  Version 3.0 for SUREFIRE-1535

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitattributes                                     |   1 +
 Jenkinsfile                                        |   6 +-
 maven-failsafe-plugin/pom.xml                      |   1 +
 .../failsafe/util/FailsafeSummaryXmlUtils.java     |  29 +++---
 .../surefire/booterclient/BooterSerializer.java    |  62 ++++++++++++-
 .../plugin/surefire/report/ReporterUtils.java      |   5 +-
 .../site/resources/xsd/surefire-test-report.xsd    |  69 +++++++-------
 maven-surefire-report-plugin/pom.xml               |   6 ++
 .../src/site/apt/examples/cross-referencing.apt.vm |   4 +-
 .../src/site/apt/usage.apt.vm                      |   4 +-
 .../{failure-details.PNG => failure-details.png}   | Bin
 .../{surefire-sample1.PNG => surefire-sample1.png} | Bin
 .../{surefire-sample2.PNG => surefire-sample2.png} | Bin
 .../site/resources/images/{xref.PNG => xref.png}   | Bin
 .../report/SurefireSchemaValidationTest.java       | 100 +++++++++++++++++++++
 .../TEST-com.shape.CircleTest.xml                  |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../maven/surefire/booter/PropertiesWrapper.java   |   4 +-
 .../maven/surefire/booter/TypeEncodedValue.java    |  19 +++-
 surefire-its/pom.xml                               |   2 +-
 .../surefire/its/fixture/SurefireLauncher.java     |   2 +
 .../surefire/testng/TestNGDirectoryTestSuite.java  |   4 +-
 .../maven/surefire/testng/TestNGExecutor.java      |  18 ++--
 .../maven/surefire/testng/TestNGProvider.java      |  40 ++++++---
 .../maven/surefire/testng/TestNGXmlTestSuite.java  |   4 +-
 29 files changed, 310 insertions(+), 82 deletions(-)
 rename maven-surefire-report-plugin/src/site/resources/images/{failure-details.PNG => failure-details.png} (100%)
 rename maven-surefire-report-plugin/src/site/resources/images/{surefire-sample1.PNG => surefire-sample1.png} (100%)
 rename maven-surefire-report-plugin/src/site/resources/images/{surefire-sample2.PNG => surefire-sample2.png} (100%)
 rename maven-surefire-report-plugin/src/site/resources/images/{xref.PNG => xref.png} (100%)
 create mode 100644 maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireSchemaValidationTest.java


[maven-surefire] 01/02: Merge branch 'master' of https://gitbox.apache.org/repos/asf/maven-surefire into suites_in_parallel

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch V30_SUREFIRE-1535
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit e59ecf77fe48eb213b4e6f53866e6a40ee51b07b
Merge: 3b45831 429a239
Author: Tibor17 <ti...@apache.org>
AuthorDate: Thu Aug 23 21:16:38 2018 +0200

    Merge branch 'master' of https://gitbox.apache.org/repos/asf/maven-surefire into suites_in_parallel

 .gitattributes                                     |   1 +
 Jenkinsfile                                        |   6 +-
 maven-failsafe-plugin/pom.xml                      |   1 +
 .../failsafe/util/FailsafeSummaryXmlUtils.java     |  29 +++---
 .../plugin/surefire/report/ReporterUtils.java      |   5 +-
 .../site/resources/xsd/surefire-test-report.xsd    |  69 +++++++-------
 maven-surefire-report-plugin/pom.xml               |   6 ++
 .../src/site/apt/examples/cross-referencing.apt.vm |   4 +-
 .../src/site/apt/usage.apt.vm                      |   4 +-
 .../{failure-details.PNG => failure-details.png}   | Bin
 .../{surefire-sample1.PNG => surefire-sample1.png} | Bin
 .../{surefire-sample2.PNG => surefire-sample2.png} | Bin
 .../site/resources/images/{xref.PNG => xref.png}   | Bin
 .../report/SurefireSchemaValidationTest.java       | 100 +++++++++++++++++++++
 .../TEST-com.shape.CircleTest.xml                  |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire-reports/TEST-com.shape.CircleTest.xml |   2 +-
 .../surefire/its/fixture/SurefireLauncher.java     |   2 +
 21 files changed, 183 insertions(+), 56 deletions(-)


[maven-surefire] 02/02: Version 3.0 for SUREFIRE-1535

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch V30_SUREFIRE-1535
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit 15ab5472e21b0cf5667ce52c86443a263c86e52b
Author: Tibor17 <ti...@apache.org>
AuthorDate: Thu Aug 23 21:26:58 2018 +0200

    Version 3.0 for SUREFIRE-1535
---
 .../surefire/booterclient/BooterSerializer.java    | 62 +++++++++++++++++++++-
 .../maven/surefire/booter/PropertiesWrapper.java   |  4 +-
 .../maven/surefire/booter/TypeEncodedValue.java    | 19 ++++++-
 surefire-its/pom.xml                               |  2 +-
 .../surefire/testng/TestNGDirectoryTestSuite.java  |  4 +-
 .../maven/surefire/testng/TestNGExecutor.java      | 18 +++++--
 .../maven/surefire/testng/TestNGProvider.java      | 40 ++++++++++----
 .../maven/surefire/testng/TestNGXmlTestSuite.java  |  4 +-
 8 files changed, 127 insertions(+), 26 deletions(-)

diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
index 9c501db..c5d36c5 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
@@ -38,6 +38,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Properties;
 
 import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CHILD_DELEGATION;
 import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CLASSPATH;
@@ -180,14 +181,71 @@ class BooterSerializer
         return writePropertiesFile( properties, surefireTmpDir, "surefire", debug );
     }
 
+    /**
+     * This method is complementary to
+     * {@link org.apache.maven.surefire.booter.TypeEncodedValue#getDecodedValue(ClassLoader)}.
+     *
+     * @param value a value to encode
+     * @return encoded value
+     */
     private static String getTypeEncoded( Object value )
     {
         if ( value == null )
         {
             return null;
         }
-        String valueToUse = value instanceof Class ? ( (Class<?>) value ).getName() : value.toString();
-        return value.getClass().getName() + "|" + valueToUse;
+        Class<?> type = value.getClass();
+        final String valueToUse;
+        if ( type == Class.class )
+        {
+            valueToUse = ( (Class<?>) value ).getName();
+        }
+        else if ( type == String.class )
+        {
+            valueToUse = (String) value;
+        }
+        else if ( type == File.class )
+        {
+            valueToUse = ( (File) value ).getAbsolutePath();
+        }
+        else if ( type == File[].class )
+        {
+            StringBuilder paths = new StringBuilder();
+            File[] files = (File[]) value;
+            for ( int i = 0; i < files.length; i++ )
+            {
+                paths.append( files[i].getAbsolutePath() );
+                if ( i != files.length - 1 )
+                {
+                    paths.append( '|' );
+                }
+            }
+            valueToUse = paths.toString();
+        }
+        else if ( type == Boolean.class || type == boolean.class
+                || type == Integer.class || type == int.class )
+        {
+            valueToUse = value.toString();
+        }
+        else if ( type == Properties.class )
+        {
+            StringBuilder stream = new StringBuilder();
+            Properties p = (Properties) value;
+            for ( String key : p.stringPropertyNames() )
+            {
+                String val = p.getProperty( key );
+                stream.append( key )
+                        .append( '=' )
+                        .append( val == null ? "" : val )
+                        .append( '\n' );
+            }
+            valueToUse = stream.toString();
+        }
+        else
+        {
+            valueToUse = value.toString();
+        }
+        return type.getCanonicalName() + "|" + valueToUse;
     }
 
     private static String toString( Object o )
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
index d94be71..e6f96b9 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
@@ -106,7 +106,7 @@ public class PropertiesWrapper
     /**
      * Retrieves as single object that is persisted with type encoding
      *
-     * @param key The key for the propery
+     * @param key The key for the property
      * @return The object, of a supported type
      */
     public TypeEncodedValue getTypeEncodedValue( String key )
@@ -114,7 +114,7 @@ public class PropertiesWrapper
         String typeEncoded = getProperty( key );
         if ( typeEncoded != null )
         {
-            int typeSep = typeEncoded.indexOf( "|" );
+            int typeSep = typeEncoded.indexOf( '|' );
             String type = typeEncoded.substring( 0, typeSep );
             String value = typeEncoded.substring( typeSep + 1 );
             return new TypeEncodedValue( type, value );
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java
index 00ad2e9..70b6c97 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java
@@ -22,10 +22,14 @@ package org.apache.maven.surefire.booter;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
+import java.util.StringTokenizer;
 
 import static org.apache.maven.surefire.util.ReflectionUtils.loadClass;
 import static org.apache.maven.surefire.util.internal.StringUtils.ISO_8859_1;
+import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
 
 /**
  * @author Kristian Rosenvold
@@ -41,7 +45,7 @@ public class TypeEncodedValue
         this.value = value;
     }
 
-    public boolean isTypeClass()
+    private boolean isTypeClass()
     {
         return Class.class.getName().equals( type );
     }
@@ -69,6 +73,19 @@ public class TypeEncodedValue
         {
             return new File( value );
         }
+        else if ( type.equals( File[].class.getCanonicalName() ) )
+        {
+            List<File> suites = new ArrayList<File>();
+            for ( StringTokenizer tokenizer = new StringTokenizer( value, "|" ); tokenizer.hasMoreTokens(); )
+            {
+                String file = tokenizer.nextToken();
+                if ( isNotBlank( file ) )
+                {
+                    suites.add( new File( file ) );
+                }
+            }
+            return suites;
+        }
         else if ( type.equals( Boolean.class.getName() ) )
         {
             return Boolean.valueOf( value );
diff --git a/surefire-its/pom.xml b/surefire-its/pom.xml
index 5ee30c9..b89289e 100644
--- a/surefire-its/pom.xml
+++ b/surefire-its/pom.xml
@@ -104,7 +104,7 @@
           <forkMode>once</forkMode>
           <argLine>-server -Xmx64m -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Djava.awt.headless=true</argLine>
           <includes>
-            <include>org/apache/**/*IT*.java</include>
+            <include>org/apache/**/*1535*.java</include>
           </includes>
           <!-- Pass current surefire version to the main suite so that it -->
           <!-- can forward to all integration test projects. SUREFIRE-513 -->
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
index a695ef6..39f1852 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
@@ -50,7 +50,7 @@ final class TestNGDirectoryTestSuite
 
     private final Map<String, String> junitOptions;
 
-    private final String testSourceDirectory;
+    private final File testSourceDirectory;
 
     private final File reportsDirectory;
 
@@ -66,7 +66,7 @@ final class TestNGDirectoryTestSuite
 
     private final int skipAfterFailureCount;
 
-    TestNGDirectoryTestSuite( String testSourceDirectory, Map<String, String> confOptions, File reportsDirectory,
+    TestNGDirectoryTestSuite( File testSourceDirectory, Map<String, String> confOptions, File reportsDirectory,
                               TestListResolver methodFilter, List<CommandLineOption> mainCliOptions,
                               int skipAfterFailureCount )
     {
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
index 0b52c4d..7f2fad3 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
@@ -37,6 +37,7 @@ import org.testng.xml.XmlSuite;
 import org.testng.xml.XmlTest;
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -76,7 +77,7 @@ final class TestNGExecutor
     }
 
     @SuppressWarnings( "checkstyle:parameternumbercheck" )
-    static void run( Iterable<Class<?>> testClasses, String testSourceDirectory,
+    static void run( Iterable<Class<?>> testClasses, File testSourceDirectory,
                             Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
                             RunListener reportManager, File reportsDirectory,
                             TestListResolver methodFilter, List<CommandLineOption> mainCliOptions,
@@ -269,7 +270,7 @@ final class TestNGExecutor
         return xms;
     }
 
-    static void run( List<String> suiteFiles, String testSourceDirectory,
+    static void run( List<String> suiteFiles, File testSourceDirectory,
                             Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
                             RunListener reportManager, File reportsDirectory, int skipAfterFailureCount )
         throws TestSetFailedException
@@ -303,8 +304,9 @@ final class TestNGExecutor
         }
     }
 
-    private static void postConfigure( TestNG testNG, String sourcePath, final RunListener reportManager,
+    private static void postConfigure( TestNG testNG, File sourcePath, final RunListener reportManager,
                                        File reportsDirectory, int skipAfterFailureCount, int verboseLevel )
+            throws TestSetFailedException
     {
         // 0 (default): turn off all TestNG output
         testNG.setVerbose( verboseLevel );
@@ -320,10 +322,16 @@ final class TestNGExecutor
             testNG.addListener( new FailFastListener( createStoppable( reportManager, skipAfterFailureCount ) ) );
         }
 
-        // FIXME: use classifier to decide if we need to pass along the source dir (only for JDK14)
         if ( sourcePath != null )
         {
-            testNG.setSourcePath( sourcePath );
+            try
+            {
+                testNG.setSourcePath( sourcePath.getCanonicalPath() );
+            }
+            catch ( IOException e )
+            {
+                throw new TestSetFailedException( e.getLocalizedMessage(), e );
+            }
         }
 
         testNG.setOutputDirectory( reportsDirectory.getAbsolutePath() );
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
index 14e103a..8b85819 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
@@ -43,6 +43,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
 import static org.apache.maven.surefire.booter.CommandReader.getReader;
 import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
 import static org.apache.maven.surefire.testset.TestListResolver.getEmptyTestListResolver;
@@ -100,22 +102,29 @@ public class TestNGProvider
 
         final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
         final RunListener reporter = reporterFactory.createReporter();
-        /**
+        /*
          * {@link org.apache.maven.surefire.report.ConsoleOutputCapture#startCapture(ConsoleOutputReceiver)}
          * called in prior to initializing variable {@link #testsToRun}
          */
         startCapture( (ConsoleOutputReceiver) reporter );
 
-        RunResult runResult;
+        final RunResult runResult;
         try
         {
-            if ( isTestNGXmlTestSuite( testRequest ) )
+            final Class<?> forkTestSetType = forkTestSet.getClass();
+
+            final boolean isXmlSuite =
+                    forkTestSetType == File.class || forkTestSetType.getComponentType() == File.class;
+
+            final List<File> suiteXmlFiles = isXmlSuite ? toXmlSuiteFiles( forkTestSetType, forkTestSet ) : null;
+
+            if ( suiteXmlFiles != null )
             {
                 if ( commandsReader != null )
                 {
                     commandsReader.awaitStarted();
                 }
-                TestNGXmlTestSuite testNGXmlTestSuite = newXmlSuite();
+                TestNGXmlTestSuite testNGXmlTestSuite = newXmlSuite( suiteXmlFiles );
                 testNGXmlTestSuite.locateTestSets();
                 testNGXmlTestSuite.execute( reporter );
             }
@@ -153,9 +162,13 @@ public class TestNGProvider
         return runResult;
     }
 
-    boolean isTestNGXmlTestSuite( TestRequest testSuiteDefinition )
+    private boolean isTestNGXmlTestSuite( TestRequest testSuiteDefinition )
+    {
+        return isTestNGXmlTestSuite( testSuiteDefinition.getSuiteXmlFiles() );
+    }
+
+    private boolean isTestNGXmlTestSuite( Collection<File> suiteXmlFiles )
     {
-        Collection<File> suiteXmlFiles = testSuiteDefinition.getSuiteXmlFiles();
         return !suiteXmlFiles.isEmpty() && !hasSpecificTests();
     }
 
@@ -195,15 +208,15 @@ public class TestNGProvider
 
     private TestNGDirectoryTestSuite newDirectorySuite()
     {
-        return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties,
+        return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory(), providerProperties,
                                              reporterConfiguration.getReportsDirectory(), getTestFilter(),
                                              mainCliOptions, getSkipAfterFailureCount() );
     }
 
-    private TestNGXmlTestSuite newXmlSuite()
+    private TestNGXmlTestSuite newXmlSuite( List<File> suiteXmlFiles )
     {
-        return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(),
-                                       testRequest.getTestSourceDirectory().toString(),
+        return new TestNGXmlTestSuite( suiteXmlFiles,
+                                       testRequest.getTestSourceDirectory(),
                                        providerProperties,
                                        reporterConfiguration.getReportsDirectory(), getSkipAfterFailureCount() );
     }
@@ -216,7 +229,7 @@ public class TestNGProvider
         {
             try
             {
-                return newXmlSuite().locateTestSets();
+                return newXmlSuite( testRequest.getSuiteXmlFiles() ).locateTestSets();
             }
             catch ( TestSetFailedException e )
             {
@@ -247,4 +260,9 @@ public class TestNGProvider
         TestListResolver filter = optionallyWildcardFilter( testRequest.getTestListResolver() );
         return filter.isWildcard() ? getEmptyTestListResolver() : filter;
     }
+
+    private static List<File> toXmlSuiteFiles( Class<?> forkTestSetType, Object forkTestSet )
+    {
+        return forkTestSetType.isArray() ? asList( (File[]) forkTestSet ) : singletonList( (File) forkTestSet );
+    }
 }
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
index c8abd60..1570a14 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
@@ -42,7 +42,7 @@ final class TestNGXmlTestSuite
 
     private List<String> suiteFilePaths;
 
-    private final String testSourceDirectory;
+    private final File testSourceDirectory;
 
     private final Map<String, String> options;
 
@@ -54,7 +54,7 @@ final class TestNGXmlTestSuite
      * Creates a testng testset to be configured by the specified
      * xml file(s). The XML files are suite definitions files according to TestNG DTD.
      */
-    TestNGXmlTestSuite( List<File> suiteFiles, String testSourceDirectory, Map<String, String> confOptions,
+    TestNGXmlTestSuite( List<File> suiteFiles, File testSourceDirectory, Map<String, String> confOptions,
                         File reportsDirectory, int skipAfterFailureCount )
     {
         this.suiteFiles = suiteFiles;