Bug 44530 - junit task with forkmode=once and xml formatter does not save all system.out
Summary: junit task with forkmode=once and xml formatter does not save all system.out
Status: REOPENED
Alias: None
Product: Ant
Classification: Unclassified
Component: Optional Tasks (show other bugs)
Version: 1.7.0
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-03-04 09:42 UTC by Michael Rosett
Modified: 2011-11-17 00:56 UTC (History)
3 users (show)



Attachments
testcase reproducing the problem using java.util.logging (1.37 KB, application/zip)
2011-04-19 08:15 UTC, willem.verstraeten
Details
JUnitLogFixFormatter.java (3.54 KB, text/plain)
2011-11-17 00:56 UTC, Eric Anderson
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Rosett 2008-03-04 09:42:39 UTC
I am running the junit task with forkmode="once" and the xml formatter.  It seemsthe xml output and subsequent report generation only contain system.out for the first test class that is ran.  If I set showoutput="true" I have the same problem (system.out is not in every xml output) but the console output shows system.out for every test class.  Here's my junit task definition:

<junit fork="true" forkmode="once" showoutput="true">
Comment 1 Peter Reilly 2008-03-22 16:44:28 UTC
I have tested this and do not see the problem
build file:
<project name="x" default="run">
  <target name="run">
    <path id="t.path">
      <path path="build/classes"/>
      <fileset dir="lib" includes="*.jar"/>
    </path>
    <mkdir dir="build/classes"/>
    <mkdir dir="build/test/reports"/>
    <javac srcdir="src" destdir="build/classes"
           target="1.5" source="1.5" debug="yes"
           classpathref="t.path"/>

    <junit fork="true" forkmode="once" showoutput="true">
      <formatter type="brief" usefile="false"/>
      <classpath refid="t.path"/>
      <formatter type="xml"/>
      <batchtest todir="build/test/reports">
        <fileset dir="src" includes="**/*Test.java"/>
      </batchtest>
    </junit>
  </target>
  
  <target name="clean">
    <delete dir="build"/>
  </target>
</project>
and the java files:
peter/T1TEst.java:package peter;

import org.junit.*;

public class T1Test {
    @Test
    public void t1() {
        System.out.println("T1Test::t1");
    }
}
and
package peter;

import org.junit.*;

public class T2Test {
    @Test
    public void t2() {
        System.out.println("T2Test::t2");
    }
}

The xml reports contain the stdout from each test.


I have seen something similar with (shudder) Log4j

At the each of each test, the std output copy is closed
*unless* one uses the follow attribute in the log4j.properties
file.
# attributes for stdout appender
# need to set follow for stdout as it gets moved around in junit tests
log4j.appender.STDOUT.follow=true

Setting to NEEDINFO, it would be nice to have a complete
tar.gz or zip file showing the problem.



Comment 2 willem.verstraeten 2011-04-19 08:15:08 UTC
Created attachment 26906 [details]
testcase reproducing the problem using java.util.logging
Comment 3 willem.verstraeten 2011-04-19 08:15:21 UTC
It is easy to reproduce this with JUL (java.util.logging). JUL also caches a reference to System.err.
Comment 4 Eric Anderson 2011-11-17 00:54:58 UTC
I just implemented a workaround for this bug in my own codebase by using a formatter created for the task (a la org.apache.tools.ant.taskdefs.optional.junit.TearDownOnVmCrash). My workaround is for users of java.util.logging.

The code for the formatter is available at (I'll add it as an attachment as well):
http://code.google.com/p/plexi/source/browse/test/JUnitLogFixFormatter.java

Use it by adding an additional formatter tag to your build.xml:

<junit...
  ...
  <formatter classname="JUnitLogFixFormatter" usefile="false"/>
  ...
</junit>


At the beginning of each test, the code looks at the root Logger and replaces any ConsoleHandlers it finds with a new ConsoleHandler (and copies over the configuration). ConsoleHandler caches System.err during its constructor, so constructing a new instance is required. After the test completes, the original handlers are replaced back into the root Logger.

For my codebase this seems to work, but YMMV.
Comment 5 Eric Anderson 2011-11-17 00:56:28 UTC
Created attachment 27961 [details]
JUnitLogFixFormatter.java

Workaround formatter for java.util.logging users