junit 5 tags support (IDEA-163481)
[idea/community.git] / plugins / junit5_rt / src / com / intellij / junit5 / JUnit5IdeaTestRunner.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.junit5;
17
18 import com.intellij.rt.execution.junit.IDEAJUnitListener;
19 import com.intellij.rt.execution.junit.IDEAJUnitListenerEx;
20 import com.intellij.rt.execution.junit.IdeaTestRunner;
21 import org.junit.platform.engine.TestExecutionResult;
22 import org.junit.platform.launcher.*;
23 import org.junit.platform.launcher.core.LauncherFactory;
24
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Set;
28
29 public class JUnit5IdeaTestRunner implements IdeaTestRunner {
30   private TestPlan myTestPlan;
31   private List<JUnit5TestExecutionListener> myExecutionListeners = new ArrayList<>();
32   private ArrayList myListeners;
33   private Launcher myLauncher;
34
35   @Override
36   public void createListeners(ArrayList listeners, int count) {
37     myListeners = listeners;
38     do {
39       myExecutionListeners.add(new JUnit5TestExecutionListener());
40     }
41     while (--count > 0);
42     myLauncher = LauncherFactory.create();
43   }
44
45   @Override
46   public int startRunnerWithArgs(String[] args, String name, int count, boolean sendTree) {
47     try {
48       JUnit5TestExecutionListener listener = myExecutionListeners.get(0);
49       listener.initializeIdSuffix(!sendTree);
50       final String[] packageNameRef = new String[1];
51       final LauncherDiscoveryRequest discoveryRequest = JUnit5TestRunnerUtil.buildRequest(args, packageNameRef);
52       myTestPlan = myLauncher.discover(discoveryRequest);
53       List<TestExecutionListener> listeners = new ArrayList<>();
54       listeners.add(listener);
55       for (Object listenerClassName : myListeners) {
56         final IDEAJUnitListener junitListener = (IDEAJUnitListener)Class.forName((String)listenerClassName).newInstance();
57         listeners.add(new MyCustomListenerWrapper(junitListener));
58       }
59       if (sendTree) {
60         int i = 0;
61         do {
62           JUnit5TestExecutionListener currentListener = myExecutionListeners.get(i);
63           if (i > 0) {
64             currentListener.initializeIdSuffix(i);
65           }
66           currentListener.sendTree(myTestPlan, packageNameRef[0]);
67         }
68         while (++ i < myExecutionListeners.size());
69       }
70       else {
71         listener.setTestPlan(myTestPlan);
72       }
73
74       myLauncher.execute(discoveryRequest, listeners.toArray(new TestExecutionListener[0]));
75
76       return listener.wasSuccessful() ? 0 : -1;
77     }
78     catch (Exception e) {
79       System.err.println("Internal Error occurred.");
80       e.printStackTrace(System.err);
81       return -2;
82     }
83     finally {
84       if (count > 0) myExecutionListeners.remove(0);
85     }
86   }
87
88   @Override
89   public Object getTestToStart(String[] args, String name) {
90     final LauncherDiscoveryRequest discoveryRequest = JUnit5TestRunnerUtil.buildRequest(args, new String[1]);
91     Launcher launcher = LauncherFactory.create();
92     myTestPlan = launcher.discover(discoveryRequest);
93     final Set<TestIdentifier> roots = myTestPlan.getRoots();
94     if (roots.isEmpty()) return null;
95     return roots.stream()
96       .filter(identifier -> !myTestPlan.getChildren(identifier).isEmpty())
97       .findFirst()
98       .orElse(null);
99   }
100
101   @Override
102   public List getChildTests(Object description) {
103     return new ArrayList<>(myTestPlan.getChildren((TestIdentifier)description));
104   }
105
106   @Override
107   public String getStartDescription(Object child) {
108     final TestIdentifier testIdentifier = (TestIdentifier)child;
109     final String className = JUnit5TestExecutionListener.getClassName(testIdentifier);
110     final String methodSignature = JUnit5TestExecutionListener.getMethodSignature(testIdentifier);
111     if (methodSignature != null) {
112       return className + "," + methodSignature;
113     }
114     return className != null ? className : (testIdentifier).getDisplayName();
115   }
116
117   @Override
118   public String getTestClassName(Object child) {
119     return child.toString();
120   }
121
122   private static class MyCustomListenerWrapper implements TestExecutionListener {
123     private final IDEAJUnitListener myJunitListener;
124
125     public MyCustomListenerWrapper(IDEAJUnitListener junitListener) {
126       myJunitListener = junitListener;}
127
128     @Override
129     public void executionStarted(TestIdentifier testIdentifier) {
130       if (testIdentifier.isTest()) {
131         final String className = JUnit5TestExecutionListener.getClassName(testIdentifier);
132         final String methodName = JUnit5TestExecutionListener.getMethodName(testIdentifier);
133         myJunitListener.testStarted(className, methodName);
134       }
135     }
136
137     @Override
138     public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
139       if (testIdentifier.isTest()) {
140         final String className = JUnit5TestExecutionListener.getClassName(testIdentifier);
141         final String methodName = JUnit5TestExecutionListener.getMethodName(testIdentifier);
142         if (myJunitListener instanceof IDEAJUnitListenerEx) {
143           ((IDEAJUnitListenerEx)myJunitListener).testFinished(className, methodName, testExecutionResult.getStatus() == TestExecutionResult.Status.SUCCESSFUL);
144         }
145         else {
146           myJunitListener.testFinished(className, methodName);
147         }
148       }
149     }
150   }
151 }