2017-08-29 4 views
0

j'ai commencé l'exécution d'un testng.xml par apache communes exécuteur testamentaire libarary par le code suivant:Tuer le processus a commencé par org.apache.commons.executor

DefaultExecuteResultHandler resultHandler; 
     ExecuteWatchdog watchdog; 
     final Executor executor; 

     resultHandler = new DefaultExecuteResultHandler(); 
     watchdog = new ExecuteWatchdog(-1L); 
     executor = new DefaultExecutor(); 
     executor.setStreamHandler(new PumpStreamHandler(new LogOutputStream() { 

     @Override 
     protected void processLine(final String line, @SuppressWarnings("unused") int level) { 
      Display.getDefault().syncExec(new Runnable() { 

       public void run() { 

        if (line.toLowerCase().indexOf("error") > -1) { 

         textArea.append(line+"\n"); 
        } else if (line.toLowerCase().indexOf("warn") > -1) { 
         textArea.append(line+"\n"); 
        } else { 
         textArea.append(line+"\n"); 


        } 
       } 
      }); 
     } 
    })); 

    executor.setExitValue(1); 
    executor.setWatchdog(watchdog); 
    executor.execute(cl, resultHandler); 

Mais je veux donner un bouton d'arrêt pour arrêter ce processus . J'ai essayé:

executor.getWatchdog().destroyProcess(); 

Mais cela ne détruit que le chien de garde. Cependant, le testng.xml que j'ai commencé continue à fonctionner en arrière-plan. Je veux détruire le processus que j'ai donné dans la commande. Est-ce possible?

+0

Pourquoi avez-vous besoin d'utiliser l'exécuteur apache pour essaimer une exécution suite 'TestNG'? Vous êtes mieux d'utiliser les apis TestNG directement dans votre code java non? Aussi s'il vous plaît montrez-nous à quoi ressemble 'cl' a.k.a votre' CommandLine'. –

+0

@KrishnanMahadevan Je veux envoyer la sortie de la console directement à une zone de texte Jframe dont je ne suis pas sûr que ce soit possible via les API TestNG. Aussi je veux l'exécuter comme un fil différent de sorte que l'application principale ne bloque pas. La commande c1 est: cmd.exe/k cd «D: \ MyProject» && D: && java -cp D: \ MyProject \ Utilities \ *; D: \ MyProject \ bin org.testng.TestNG D: \ MyProject \ testng .xml –

Répondre

0

La raison pour laquelle votre solution ne tue pas la JVM générée est peut-être parce que vous appelez cmd.exe et que c'est de là que vous générez probablement la JVM. Donc, quand vous appelez destroyProcess(), je crois que c'est cmd.exe qui est tué mais pas java.exe.

Vous devriez essayer de changer votre ligne de commande à quelque chose comme ci-dessous:

java -cp D:\MyProject\Utilities*;D:\MyProject\bin org.testng.TestNG D:\MyProject\testng.xml 

est ici une solution qui ne fait pas usage de l'exécuteur testamentaire commons Apache pour ce faire, mais gère tout dans une seule machine virtuelle Java et prévoit également un moyen de récupérer la sortie et la sortie d'erreur de TestNG.

Cette solution utilise les API TestNG.

Le principal coureur de test, qui utilise TestNG pour effectuer des tests, dans un autre thread ressemble ci-dessous

import org.testng.TestNG; 

import java.util.Collections; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class SimpleTestRunner { 
    public static void main(String[] args) throws InterruptedException, ExecutionException { 
     System.err.println("***Main Thread running in Thread [" + Thread.currentThread().getId() + "]***"); 
     ExecutorService service = Executors.newCachedThreadPool(); 
     WorkerThread thread = new WorkerThread(SampleTestClass.class); 
     List<Future<ExecutionResults>> allResults = service.invokeAll(Collections.singletonList(thread)); 
     service.shutdown(); 
     ExecutionResults result = allResults.get(0).get(); 
     System.err.println("******Printing the TestNG output******"); 
     System.err.println(result); 
     System.err.println("**************************************"); 
    } 

    public static class WorkerThread implements Callable<ExecutionResults> { 
     private Class<?>[] classes; 

     WorkerThread(Class<?>... classes) { 
      this.classes = classes; 
     } 

     @Override 
     public ExecutionResults call() throws Exception { 
      System.err.println("***Worker Thread running in Thread [" + Thread.currentThread().getId() + "]***"); 
      TestNG testNG = new TestNG(); 
      ExecutionResults results; 
      testNG.setVerbose(2); 
      ConsoleCapturer capturer = new ConsoleCapturer(); 
      testNG.setTestClasses(classes); 
      try { 
       capturer.start(); 
       testNG.run(); 
      } finally { 
       ConsoleCapturer.CapturedData data = capturer.stop(); 
       results = new ExecutionResults(data, testNG.getStatus()); 
      } 
      return results; 
     } 
    } 

    public static class ExecutionResults { 
     private ConsoleCapturer.CapturedData data; 
     private int status; 

     public ExecutionResults(ConsoleCapturer.CapturedData data, int status) { 
      this.data = data; 
      this.status = status; 
     } 

     public ConsoleCapturer.CapturedData getData() { 
      return data; 
     } 

     public int getStatus() { 
      return status; 
     } 

     @Override 
     public String toString() { 
      return "ExecutionResults{" + 
        "data=" + getData() + 
        ", status=" + getStatus() + 
        '}'; 
     } 
    } 
} 

La classe utilitaire qui réoriente tout le contenu de sortie et d'erreur à un fil, de sorte qu'ils puissent être redirigé vers n'importe où, ressemble à ci-dessous:

Cette classe est le plus souvent emprunté du code de la solution Redirect console output to string in java avec quelques improvisations.

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.io.PrintStream; 

/** 
* This class is an improvisation of the solution provided in https://stackoverflow.com/a/30665299/679824 
*/ 
public class ConsoleCapturer { 
    private ByteArrayOutputStream baosOutput, baosError; 
    private PrintStream previousOut, previousError; 
    private boolean capturing; 

    public void start() { 
     if (capturing) { 
      return; 
     } 

     capturing = true; 
     previousOut = System.out; 
     previousError = System.err; 
     baosOutput = new ByteArrayOutputStream(); 
     baosError = new ByteArrayOutputStream(); 

     System.setOut(new PrintStream(new OutputStreamCombiner(previousOut, baosOutput))); 
     System.setErr(new PrintStream(new OutputStreamCombiner(previousError, baosError))); 
    } 

    public CapturedData stop() { 

     if (!capturing) { 
      return new CapturedData(); 
     } 

     System.setOut(previousOut); 
     System.setErr(previousError); 

     String output = baosOutput.toString(); 
     String error = baosError.toString(); 

     try { 
      baosOutput.close(); 
      baosError.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     baosOutput = null; 
     previousOut = null; 
     capturing = false; 

     return new CapturedData(output, error); 
    } 

    private static class OutputStreamCombiner extends OutputStream { 
     private OutputStream[] outputStreams; 

     OutputStreamCombiner(OutputStream... outputStreams) { 
      this.outputStreams = outputStreams; 
     } 

     public void write(int b) throws IOException { 
      for (OutputStream os : outputStreams) { 
       os.write(b); 
      } 
     } 

     public void flush() throws IOException { 
      for (OutputStream os : outputStreams) { 
       os.flush(); 
      } 
     } 

     public void close() throws IOException { 
      for (OutputStream os : outputStreams) { 
       os.close(); 
      } 
     } 
    } 

    public static class CapturedData { 
     private String output; 
     private String error; 

     CapturedData() { 
      this("", ""); 
     } 

     public CapturedData(String output, String error) { 
      this.output = output; 
      this.error = error; 
     } 

     public String getError() { 
      return error; 
     } 

     public String getOutput() { 
      return output; 
     } 

     @Override 
     public String toString() { 
      return "CapturedData{" + 
        "output='" + getOutput() + '\'' + 
        ", error='" + getError() + '\'' + 
        '}'; 
     } 
    } 
} 

La classe de test semble utilisé comme ci-dessous

import org.testng.annotations.Test; 

public class SampleTestClass { 

    @Test 
    public void testMethod() { 
     System.err.println("This goes into the error console"); 
     System.out.println("This goes into the console"); 
    } 
} 

La sortie ressemble ci-dessous

***Main Thread running in Thread [1]*** 
***Worker Thread running in Thread [11]*** 
This goes into the console 
This goes into the error console 
PASSED: testMethod 

=============================================== 
    Command line test 
    Tests run: 1, Failures: 0, Skips: 0 
=============================================== 


=============================================== 
Command line suite 
Total tests run: 1, Failures: 0, Skips: 0 
=============================================== 

******Printing the TestNG output****** 
ExecutionResults{data=CapturedData{output='This goes into the console 
PASSED: testMethod 

=============================================== 
    Command line test 
    Tests run: 1, Failures: 0, Skips: 0 
=============================================== 


=============================================== 
Command line suite 
Total tests run: 1, Failures: 0, Skips: 0 
=============================================== 

', error='This goes into the error console 
'}, status=0} 
************************************** 

Process finished with exit code 0