7

Context

I am using ant1-9-0.jar, ant-junit-1.9.0.jar and ant-launcher-1.9.0.jar to run JUnit tests programmatically.

In my code, I have this function that returns the JUnit Task:

/**
 * Generates a JUnit task which runs every single test in a new JVM
 * @return task The JUnit task
 * @throws Exception
 */
public JUnitTask generateRunTestsTask() throws Exception {
    /* New JUnit task */
    JUnitTask task = new JUnitTask();
    task.init();
    
    /* Summary settings */
    JUnitTask.SummaryAttribute sa = new JUnitTask.SummaryAttribute();
    sa.setValue("withOutAndErr");
    task.setPrintsummary(sa);
    
    /* JVM configuration */
    task.setFork(true);
    task.setDir(new File(this.deliveryBinDir));
    task.createJvmarg().setValue("-Duser.dir=" + this.deliveryBinDir);
    
    /* Output to file */
    FormatterElement.TypeAttribute typeFile = new FormatterElement.TypeAttribute();
    typeFile.setValue("xml");
    FormatterElement formatToFile = new FormatterElement();
    formatToFile.setType(typeFile);
    task.addFormatter(formatToFile);
    
    /* Task options */
    task.setHaltonfailure(false);
    task.setShowOutput(true);
    task.setOutputToFormatters(true);
    
    List<String> testSuites = getTestJarList(this.deliveryLibFolder);
    for (String singleSuite : testSuites) {
        JUnitTest test = new JUnitTest(singleSuite);
        /* Sets reports location */
        test.setTodir(this.testReportsFolder);
        task.addTest(test);
    }
    
    return task;
}

The JUnit tests run without problem and the output is successfully stored into .xml files.

Issue

I need to print the output to the console, because I want results in live (not only at the end of the whole process). To do so, I have added a second FormatterElement just below the /** Output to file */ block:

/* Output to screen */
FormatterElement.TypeAttribute typeScreen = new FormatterElement.TypeAttribute();
typeScreen.setValue("plain");
FormatterElement formatToScreen = new FormatterElement();
formatToScreen.setType(typeScreen);
formatToScreen.setUseFile(false);
formatToScreen.setOutput(System.out);
task.addFormatter(formatToScreen);

But my console still doesn't display the logs. I have also tried to remove the formatToFile FormatterElement, without success. Do you have any suggestions?

Notes:

  • these unit tests really need to be forked, it can't be changed,
  • just let me know if you need more code, for example the settings of the Ant Project or the Ant Target,
  • unit tests indeed contain Sysouts,
  • I've reproduced a consistent build.xml file which works,
  • here is the Apache Ant JUnit repository if needed.
Community
  • 1
  • 1
Stéphane Bruckert
  • 21,706
  • 14
  • 92
  • 130
  • Have you tried removing formatToScreen.setOutput(System.out) and using the Default (which should be System.out, but just to be sure. Here is something that may help, source code for FormatterElement. http://grepcode.com/file/repository.springsource.com/org.apache.ant/com.springsource.org.apache.tool.ant.taskdefs.optional.junit/1.7.1/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java#FormatterElement – dseibert Aug 11 '13 at 21:37
  • I have already tried this before. I now removed this call to `setOutput` again, but it doesn't change anything. I also removed `setShowOutput(true)` and `setOutputToFormatters(true)` which are set to `true` by default. – Stéphane Bruckert Aug 12 '13 at 09:38

2 Answers2

4

Stéphane, your code for the junit task seems to be correct for handling the output to the console.

I have check the source code of the Main class of ANT and you need to define a build listener to be able to display the logs.

This is working example to define a default listener for logging purpose:

BuildLogger logger = new DefaultLogger();
logger.setOutputPrintStream(System.out);
logger.setErrorPrintStream(System.err);
logger.setMessageOutputLevel(Project.MSG_INFO);
logger.setEmacsMode(true);
project.addBuildListener(logger); //add build listener to your define project
Delildor
  • 346
  • 4
  • 13
0

Stéphane, the lack of unit test output is probably linked to the presence of this hard-coded subprocess stream handler in JUnitTask.executeAsForked() (see the source code of ant-junit):

    Execute execute = new Execute(
        new JUnitLogStreamHandler(
            this,
            Project.MSG_INFO,
            Project.MSG_WARN),
        watchdog);

The method is private and I don't see an obvious "official" way to pass another stream handler, so if you really want to handle the forked JVM's output differently you can probably take advantage of the fact that ant-junit is open source and create a slightly altered version of it that either uses more verbose settings for the JUnitLogStreamHandler, or even uses your own implementation of ExecuteStreamHandler that handles the output of the child process however you prefer.

  • via reflection you can call private methods, too – AlexWien Aug 13 '13 at 20:32
  • True, Alex. Unfortunately, Stéphane does not merely need to _invoke_ a private method, but rather to alter its content. Specifically, he needs to pass another stream handler to the local Execute variable used to run the forked process. In principle there are options to hot-swap the code ( see http://stackoverflow.com/questions/4553353/change-a-method-at-runtime-via-a-hot-swap-mechanism ), but it is IMO more practical to simply modify the ant-junit library (and then perhaps propose a patch to the library development team, too). –  Aug 13 '13 at 20:42