Github user bodewig commented on a diff in the pull request:

    https://github.com/apache/ant/pull/60#discussion_r169243988
  
    --- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
    @@ -0,0 +1,508 @@
    +package org.apache.tools.ant.taskdefs.optional.junitlauncher;
    +
    +import org.apache.tools.ant.AntClassLoader;
    +import org.apache.tools.ant.BuildException;
    +import org.apache.tools.ant.Project;
    +import org.apache.tools.ant.Task;
    +import org.apache.tools.ant.types.Path;
    +import org.apache.tools.ant.util.KeepAliveOutputStream;
    +import org.junit.platform.launcher.Launcher;
    +import org.junit.platform.launcher.LauncherDiscoveryRequest;
    +import org.junit.platform.launcher.TestExecutionListener;
    +import org.junit.platform.launcher.TestPlan;
    +import org.junit.platform.launcher.core.LauncherFactory;
    +import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
    +import org.junit.platform.launcher.listeners.TestExecutionSummary;
    +
    +import java.io.Closeable;
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.io.PipedInputStream;
    +import java.io.PipedOutputStream;
    +import java.io.PrintStream;
    +import java.nio.file.Files;
    +import java.nio.file.Paths;
    +import java.util.ArrayList;
    +import java.util.Collection;
    +import java.util.Collections;
    +import java.util.List;
    +import java.util.Optional;
    +import java.util.concurrent.BlockingQueue;
    +import java.util.concurrent.CountDownLatch;
    +import java.util.concurrent.LinkedBlockingQueue;
    +import java.util.concurrent.TimeUnit;
    +
    +/**
    + * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
    + * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
    + * APIs were introduced.
    + * <p>
    + * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
    + * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
    + * result of the execution to present in a way that's been configured on 
this Ant task.
    + * </p>
    + * <p>
    + * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
    + * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
    + * decide and execute the tests.
    + *
    + * @see <a href="https://junit.org/junit5/";>JUnit 5 documentation</a> for 
more details
    + * on how JUnit manages the platform and the test engines.
    + */
    +public class JUnitLauncherTask extends Task {
    +
    +    private Path classPath;
    +    private boolean haltOnFailure;
    +    private String failureProperty;
    +    private final List<TestDefinition> tests = new ArrayList<>();
    +    private final List<ListenerDefinition> listeners = new ArrayList<>();
    +
    +    public JUnitLauncherTask() {
    +    }
    +
    +    @Override
    +    public void execute() throws BuildException {
    +        final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
    +        try {
    +            final ClassLoader executionCL = 
createClassLoaderForTestExecution();
    +            Thread.currentThread().setContextClassLoader(executionCL);
    +            final Launcher launcher = LauncherFactory.create();
    +            final List<TestRequest> requests = buildTestRequests();
    +            for (final TestRequest testRequest : requests) {
    +                try {
    +                    final TestDefinition test = testRequest.getOwner();
    +                    final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
    +                    final List<TestExecutionListener> 
testExecutionListeners = new ArrayList<>();
    +                    // a listener that we always put at the front of list 
of listeners
    +                    // for this request.
    +                    final Listener firstListener = new Listener();
    +                    // we always enroll the summary generating listener, 
to the request, so that we
    +                    // get to use some of the details of the summary for 
our further decision making
    +                    testExecutionListeners.add(firstListener);
    +                    
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
    +                    final PrintStream originalSysOut = System.out;
    +                    final PrintStream originalSysErr = System.err;
    +                    try {
    +                        firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
    +                        firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
    +                        launcher.execute(request, 
testExecutionListeners.toArray(new 
TestExecutionListener[testExecutionListeners.size()]));
    +                    } finally {
    +                        // switch back sysout/syserr to the original
    +                        try {
    +                            System.setOut(originalSysOut);
    +                        } catch (Exception e) {
    +                            // ignore
    +                        }
    +                        try {
    +                            System.setErr(originalSysErr);
    +                        } catch (Exception e) {
    +                            // ignore
    +                        }
    +                    }
    +                    handleTestExecutionCompletion(test, 
firstListener.getSummary());
    +                } finally {
    +                    try {
    +                        testRequest.close();
    +                    } catch (Exception e) {
    +                        // log and move on
    +                        log("Failed to cleanly close test request", e, 
Project.MSG_DEBUG);
    +                    }
    +                }
    +            }
    +        } finally {
    +            
Thread.currentThread().setContextClassLoader(previousClassLoader);
    +        }
    +    }
    +
    +    /**
    +     * @return Creates and returns the a {@link Path} which will be used 
as the classpath of this
    +     * task. This classpath will then be used for execution of the tests
    +     */
    +    public Path createClassPath() {
    +        this.classPath = new Path(getProject());
    --- End diff --
    
    if users specify multiple nested classpath elements, only the last one will 
be used. You may want to return an already created `this.classpath` or move on 
to an `add` method and collect the paths inside of a wrapper `Path`.


---

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org
For additional commands, e-mail: dev-h...@ant.apache.org

Reply via email to