You are viewing a plain text version of this content. The canonical link for it is here.
Posted to surefire-commits@maven.apache.org by ke...@apache.org on 2006/12/20 15:22:32 UTC

svn commit: r489098 - in /maven/surefire/trunk: ./ maven-surefire-plugin/ maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/ maven-surefire-report-plugin/ surefire-booter/ surefire-booter/src/main/java/org/apache/maven/surefire/boote...

Author: kenney
Date: Wed Dec 20 06:22:32 2006
New Revision: 489098

URL: http://svn.apache.org/viewvc?view=rev&rev=489098
Log:
Merged revisions 482819:HEAD from sandbox/surefire-plugin-merge and deleted surefire-plugin-merge

Modified:
    maven/surefire/trunk/maven-surefire-plugin/pom.xml
    maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
    maven/surefire/trunk/maven-surefire-report-plugin/pom.xml
    maven/surefire/trunk/pom.xml
    maven/surefire/trunk/surefire-booter/pom.xml
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java

Modified: maven/surefire/trunk/maven-surefire-plugin/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/pom.xml?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/pom.xml (original)
+++ maven/surefire/trunk/maven-surefire-plugin/pom.xml Wed Dec 20 06:22:32 2006
@@ -20,12 +20,13 @@
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
-    <artifactId>maven-plugins</artifactId>
-    <groupId>org.apache.maven.plugins</groupId>
-    <version>4-SNAPSHOT</version>
+    <artifactId>surefire</artifactId>
+    <groupId>org.apache.maven.surefire</groupId>
+    <version>2.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>maven-surefire-plugin</artifactId>
+  <groupId>org.apache.maven.plugins</groupId>
   <packaging>maven-plugin</packaging>
   <name>Maven Surefire Plugin</name>
   <version>2.3-SNAPSHOT</version>

Modified: maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java (original)
+++ maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java Wed Dec 20 06:22:32 2006
@@ -98,6 +98,7 @@
      */
     private File basedir;
 
+    // FIXME this field is not used
     /**
      * The directory containing generated classes of the project being tested.
      *
@@ -373,27 +374,20 @@
      */
     private boolean disableXmlReport;
 
+    /**
+     * Option to pass dependencies to the system's classloader instead of using an isolated class loader when
+     * forking. Prevents problems with JDKs which implement the service provider lookup mechanism by using
+     * the system's classloader.
+     *
+     * @parameter expression="${surefire.useSystemClassLoader}" default-value="false"
+     */
+    private boolean useSystemClassLoader;
+
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
-        if ( skip || skipExec )
-        {
-            getLog().info( "Tests are skipped." );
-        }
-        else if ( !testClassesDirectory.exists() )
+        if ( verifyParameters() )
         {
-            getLog().info( "No tests to run." );
-        }
-        else
-        {
-            if ( parallel )
-            {
-                if ( threadCount < 1 )
-                {
-                    throw new MojoFailureException( "Must have at least one thread in parallel mode" );
-                }
-            }
-
             SurefireBooter surefireBooter = constructSurefireBooter();
 
             getLog().info( "Surefire report directory: " + reportsDirectory );
@@ -434,6 +428,36 @@
         }
     }
 
+    private boolean verifyParameters()
+        throws MojoFailureException
+    {
+        if ( skip || skipExec )
+        {
+            getLog().info( "Tests are skipped." );
+            return false;
+        }
+        else if ( !testClassesDirectory.exists() )
+        {
+            getLog().info( "No tests to run." );
+            return false;
+        }
+
+        if ( parallel )
+        {
+            if ( threadCount < 1 )
+            {
+                throw new MojoFailureException( "Must have at least one thread in parallel mode" );
+            }
+        }
+
+        if ( useSystemClassLoader && ForkConfiguration.FORK_NEVER.equals( forkMode ) )
+        {
+            getLog().warn( "useSystemClassloader=true setting has no effect when not forking" );
+        }
+
+        return true;
+    }
+
     private SurefireBooter constructSurefireBooter()
         throws MojoExecutionException, MojoFailureException
     {
@@ -476,11 +500,9 @@
             }
             else
             {
-                // only need to discover JUnit if there is no TestNG, it runs the tests for you.
-                if ( junitArtifact != null )
-                {
-                    addProvider( surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null );
-                }
+                // add the JUnit provider as default - it doesn't require JUnit to be present,
+                // since it supports POJO tests.
+                addProvider( surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null );
             }
         }
         catch ( ArtifactNotFoundException e )
@@ -562,15 +584,13 @@
                     testClassesDirectory, includes, excludes, groups, excludedGroups, Boolean.valueOf( parallel ),
                     new Integer( threadCount ), testSourceDirectory.getAbsolutePath()} );
             }
-            else if ( junitArtifact != null )
+            else
             {
+                // fall back to JUnit, which also contains POJO support. Also it can run
+                // classes compiled against JUnit since it has a dependency on JUnit itself.
                 surefireBooter.addTestSuite( "org.apache.maven.surefire.junit.JUnitDirectoryTestSuite",
                                              new Object[]{testClassesDirectory, includes, excludes} );
             }
-            else
-            {
-                throw new MojoExecutionException( "No Java test frameworks found" );
-            }
         }
 
         // ----------------------------------------------------------------------
@@ -646,6 +666,8 @@
         surefireBooter.setChildDelegation( childDelegation );
 
         surefireBooter.setReportsDirectory( reportsDirectory );
+
+        surefireBooter.setUseSystemClassLoader( useSystemClassLoader );
 
         addReporters( surefireBooter, fork.isForking() );
 

Modified: maven/surefire/trunk/maven-surefire-report-plugin/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-report-plugin/pom.xml?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/maven-surefire-report-plugin/pom.xml (original)
+++ maven/surefire/trunk/maven-surefire-report-plugin/pom.xml Wed Dec 20 06:22:32 2006
@@ -2,12 +2,13 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
-    <artifactId>maven-plugins</artifactId>
-    <groupId>org.apache.maven.plugins</groupId>
-    <version>4-SNAPSHOT</version>
+    <artifactId>surefire</artifactId>
+    <groupId>org.apache.maven.surefire</groupId>
+    <version>2.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>maven-surefire-report-plugin</artifactId>
+  <groupId>org.apache.maven.plugins</groupId>
   <packaging>maven-plugin</packaging>
   <name>Maven Surefire Report Plugin</name>
   <version>2.1-SNAPSHOT</version>

Modified: maven/surefire/trunk/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/pom.xml?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/pom.xml (original)
+++ maven/surefire/trunk/pom.xml Wed Dec 20 06:22:32 2006
@@ -59,13 +59,6 @@
   <build>
     <plugins>
       <plugin>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.2</version>
-        <configuration>
-          <childDelegation>true</childDelegation>
-        </configuration>
-      </plugin>
-      <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
           <source>1.3</source>
@@ -75,6 +68,10 @@
     </plugins>
     <pluginManagement>
       <plugins>
+        <plugin>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.3-SNAPSHOT</version>
+        </plugin>
         <plugin>
           <artifactId>maven-release-plugin</artifactId>
           <configuration>

Modified: maven/surefire/trunk/surefire-booter/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/pom.xml?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/surefire-booter/pom.xml (original)
+++ maven/surefire/trunk/surefire-booter/pom.xml Wed Dec 20 06:22:32 2006
@@ -33,6 +33,17 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-archiver</artifactId>
+      <version>1.0-alpha-7</version>
+      <exclusions> <!-- exclude plexus-utils since it's 1.2 and we need 1.1 -->
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-utils</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>3.8.1</version>

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java Wed Dec 20 06:22:32 2006
@@ -16,9 +16,14 @@
  * limitations under the License.
  */
 
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.jar.JarArchiver;
+import org.codehaus.plexus.archiver.jar.Manifest;
+import org.codehaus.plexus.archiver.jar.ManifestException;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -29,6 +34,7 @@
  * Configuration for forking tests.
  *
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a>
  */
 public class ForkConfiguration
 {
@@ -112,7 +118,18 @@
         return systemProperties;
     }
 
+    /**
+     * @throws SurefireBooterForkException
+     * @deprecated use the 2-arg alternative.
+     */
     public Commandline createCommandLine( List classPath )
+        throws SurefireBooterForkException
+    {
+        return createCommandLine( classPath, false );
+    }
+
+    public Commandline createCommandLine( List classPath, boolean useJar )
+        throws SurefireBooterForkException
     {
         Commandline cli = new Commandline();
 
@@ -143,15 +160,84 @@
                 "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" );
         }
 
-        cli.createArgument().setValue( "-classpath" );
+        if ( useJar )
+        {
+            File jarFile;
+            try
+            {
+                jarFile = createJar( classPath );
+            }
+            catch ( IOException e )
+            {
+                throw new SurefireBooterForkException( "Error creating archive file", e );
+            }
+            catch ( ManifestException e )
+            {
+                throw new SurefireBooterForkException( "Error creating manifest", e );
+            }
+            catch ( ArchiverException e )
+            {
+                throw new SurefireBooterForkException( "Error creating archive", e );
+            }
+
+            cli.createArgument().setValue( "-jar" );
+
+            cli.createArgument().setValue( jarFile.getAbsolutePath() );
+        }
+        else
+        {
+            cli.createArgument().setValue( "-classpath" );
 
-        cli.createArgument().setValue( StringUtils.join( classPath.iterator(), File.pathSeparator ) );
+            cli.createArgument().setValue( StringUtils.join( classPath.iterator(), File.pathSeparator ) );
 
-        cli.createArgument().setValue( SurefireBooter.class.getName() );
+            cli.createArgument().setValue( SurefireBooter.class.getName() );
+        }
 
         cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
 
         return cli;
+    }
+
+    /**
+     * Create a jar with just a manifest containing a Main-Class entry for SurefireBooter and a Class-Path entry
+     * for all classpath elements.
+     * @param classPath List&lt;String> of all classpath elements.
+     * @return
+     * @throws IOException
+     * @throws ManifestException
+     * @throws ArchiverException
+     */
+    private static File createJar( List classPath )
+        throws IOException, ManifestException, ArchiverException
+    {
+        JarArchiver jar = new JarArchiver();
+        jar.setCompress( false ); // for speed
+        File file = File.createTempFile( "surefirebooter", ".jar" );
+        file.deleteOnExit();
+        jar.setDestFile( file );
+
+        Manifest manifest = new Manifest();
+
+        // we can't use StringUtils.join here since we need to add a '/' to
+        // the end of directory entries - otherwise the jvm will ignore them.
+        String cp = "";
+        for ( Iterator it = classPath.iterator(); it.hasNext(); )
+        {
+            String el = (String) it.next();
+            cp += " " + el + ( new File( el ).isDirectory() ? "/" : "" );
+        }
+
+        Manifest.Attribute attr = new Manifest.Attribute( "Class-Path", cp.trim() );
+        manifest.addConfiguredAttribute( attr );
+
+        attr =new Manifest.Attribute("Main-Class", SurefireBooter.class.getName() );
+        manifest.addConfiguredAttribute( attr );
+
+        jar.addConfiguredManifest( manifest );
+
+        jar.createArchive();
+
+        return file;
     }
 
     public void setDebug( boolean debug )

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java Wed Dec 20 06:22:32 2006
@@ -68,6 +68,8 @@
 
     private boolean redirectTestOutputToFile = false;
 
+    private boolean useSystemClassLoader = false;
+
     // ----------------------------------------------------------------------
     //
     // ----------------------------------------------------------------------
@@ -109,7 +111,12 @@
 
     public void addReport( String report, Object[] constructorParams )
     {
-        reports.add( new Object[]{report, constructorParams} );
+        reports.add( new Object[]{ report, constructorParams } );
+    }
+
+    public void addTestSuite( String suiteClassName, Object[] constructorParams )
+    {
+        testSuites.add( new Object[]{ suiteClassName, constructorParams } );
     }
 
     public void addClassPathUrl( String path )
@@ -120,11 +127,6 @@
         }
     }
 
-    public void addTestSuite( String suiteClassName, Object[] constructorParams )
-    {
-        testSuites.add( new Object[]{suiteClassName, constructorParams} );
-    }
-
     public void addSurefireClassPathUrl( String path )
     {
         if ( !surefireClassPathUrls.contains( path ) )
@@ -133,6 +135,15 @@
         }
     }
 
+    public void addSurefireBootClassPathUrl( String path )
+    {
+        if ( !surefireBootClassPathUrls.contains( path ) )
+        {
+            surefireBootClassPathUrls.add( path );
+        }
+    }
+
+
     /**
      * When forking, setting this to true will make the test output to be saved in a file
      * instead of showing it on the standard output
@@ -167,6 +178,11 @@
         this.forkConfiguration = forkConfiguration;
     }
 
+    public void setUseSystemClassLoader( boolean useSystemClassLoader )
+    {
+        this.useSystemClassLoader = useSystemClassLoader;
+    }
+
     public boolean run()
         throws SurefireBooterForkException, SurefireExecutionException
     {
@@ -205,7 +221,9 @@
         ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
         try
         {
-            ClassLoader testsClassLoader = createClassLoader( classPathUrls, null, childDelegation, true );
+            ClassLoader testsClassLoader = useSystemClassLoader
+                ? ClassLoader.getSystemClassLoader()
+                : createClassLoader( classPathUrls, null, childDelegation, true );
 
             // TODO: assertions = true shouldn't be required for this CL if we had proper separation (see TestNG)
             ClassLoader surefireClassLoader =
@@ -233,7 +251,7 @@
         {
             throw new SurefireExecutionException( "Unable to instantiate and execute Surefire", e );
         }
-        finally 
+        finally
         {
             Thread.currentThread().setContextClassLoader( oldContextClassLoader );
         }
@@ -246,12 +264,14 @@
 
         //noinspection CatchGenericClass,OverlyBroadCatchBlock
         ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
-        
+
         try
         {
             // The test classloader must be constructed first to avoid issues with commons-logging until we properly
             // separate the TestNG classloader
-            ClassLoader testsClassLoader = createClassLoader( classPathUrls, null, childDelegation, true );
+            ClassLoader testsClassLoader = useSystemClassLoader
+                ? getClass().getClassLoader()//ClassLoader.getSystemClassLoader()
+                : createClassLoader( classPathUrls, null, childDelegation, true );
 
             ClassLoader surefireClassLoader =
                 createClassLoader( surefireClassPathUrls, testsClassLoader, true );
@@ -263,7 +283,6 @@
             Method run = surefireClass.getMethod( "run", new Class[]{List.class, List.class, ClassLoader.class,
                 ClassLoader.class} );
 
-
             Thread.currentThread().setContextClassLoader( testsClassLoader );
 
             Boolean result = (Boolean) run.invoke( surefire, new Object[]{reports, testSuites, surefireClassLoader,
@@ -279,7 +298,7 @@
         {
             throw new SurefireExecutionException( "Unable to instantiate and execute Surefire", e );
         }
-        finally 
+        finally
         {
             Thread.currentThread().setContextClassLoader( oldContextClassLoader );
         }
@@ -407,7 +426,7 @@
         addPropertiesForTypeHolder( reports, properties, "report." );
         addPropertiesForTypeHolder( testSuites, properties, "testSuite." );
 
-        for ( int i = 0; i < classPathUrls.size(); i++ )
+        for ( int i = 0; i < classPathUrls.size() && !useSystemClassLoader; i++ )
         {
             String url = (String) classPathUrls.get( i );
             properties.setProperty( "classPathUrl." + i, url );
@@ -419,13 +438,8 @@
             properties.setProperty( "surefireClassPathUrl." + i, url );
         }
 
-        for ( int i = 0; i < surefireBootClassPathUrls.size(); i++ )
-        {
-            String url = (String) surefireBootClassPathUrls.get( i );
-            properties.setProperty( "surefireBootClassPathUrl." + i, url );
-        }
-
         properties.setProperty( "childDelegation", String.valueOf( childDelegation ) );
+        properties.setProperty( "useSystemClassLoader", String.valueOf( useSystemClassLoader ) );
     }
 
     private File writePropertiesFile( String name, Properties properties )
@@ -503,7 +517,16 @@
             throw new SurefireBooterForkException( "Error creating properties files for forking", e );
         }
 
-        Commandline cli = forkConfiguration.createCommandLine( surefireBootClassPathUrls );
+        List bootClasspath = new ArrayList( surefireBootClassPathUrls.size() + classPathUrls.size() );
+
+        bootClasspath.addAll( surefireBootClassPathUrls );
+
+        if ( useSystemClassLoader )
+        {
+            bootClasspath.addAll( classPathUrls );
+        }
+
+        Commandline cli = forkConfiguration.createCommandLine( bootClasspath, useSystemClassLoader  );
 
         cli.createArgument().setFile( surefireProperties );
 
@@ -775,6 +798,11 @@
                     surefireBooter.childDelegation =
                         Boolean.valueOf( p.getProperty( "childDelegation" ) ).booleanValue();
                 }
+                else if ( "useSystemClassLoader".equals( name ) )
+                {
+                    surefireBooter.useSystemClassLoader =
+                        Boolean.valueOf( p.getProperty( "useSystemClassLoader" ) ).booleanValue();
+                }
             }
 
             String testSet = p.getProperty( "testSet" );
@@ -806,15 +834,6 @@
     public void setChildDelegation( boolean childDelegation )
     {
         this.childDelegation = childDelegation;
-    }
-
-    public void addSurefireBootClassPathUrl( String path )
-    {
-        if ( !surefireBootClassPathUrls.contains( path ) )
-        {
-            surefireBootClassPathUrls.add( path );
-        }
-        addSurefireClassPathUrl( path );
     }
 
     private StreamConsumer getForkingStreamConsumer( boolean showHeading, boolean showFooter,

Modified: maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java?view=diff&rev=489098&r1=489097&r2=489098
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java Wed Dec 20 06:22:32 2006
@@ -155,7 +155,7 @@
 
     // Handler for TestListener.addFailure(Test, Throwable)
     private void handleAddError( Object[] args )
-        throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
+        throws IllegalAccessException, InvocationTargetException
     {
         ReportEntry report =
             new ReportEntry( args[0], args[0].toString(), args[1].toString(), getStackTraceWriter( args ) );
@@ -166,15 +166,25 @@
     }
 
     private JUnitStackTraceWriter getStackTraceWriter( Object[] args )
-        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
+        throws IllegalAccessException, InvocationTargetException
     {
-        Method m = args[0].getClass().getMethod( "getName", EMPTY_CLASS_ARRAY );
-        String testName = (String) m.invoke( args[0], EMPTY_STRING_ARRAY );
+        String testName;
+
+        try
+        {
+            Method m = args[0].getClass().getMethod( "getName", EMPTY_CLASS_ARRAY );
+            testName = (String) m.invoke( args[0], EMPTY_STRING_ARRAY );
+        }
+        catch ( NoSuchMethodException e )
+        {
+            testName = "UNKNOWN";
+        }
+
         return new JUnitStackTraceWriter( args[0].getClass().getName(), testName, (Throwable) args[1] );
     }
 
     private void handleAddFailure( Object[] args )
-        throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
+        throws IllegalAccessException, InvocationTargetException
     {
         ReportEntry report =
             new ReportEntry( args[0], args[0].toString(), args[1].toString(), getStackTraceWriter( args ) );