Home | History | Annotate | Download | only in junit
      1 package org.testng.junit;
      2 
      3 import java.util.*;
      4 import java.util.regex.Pattern;
      5 import org.junit.runner.Description;
      6 import org.junit.runner.JUnitCore;
      7 import org.junit.runner.Request;
      8 import org.junit.runner.Result;
      9 import org.junit.runner.manipulation.Filter;
     10 import org.junit.runner.notification.Failure;
     11 import org.junit.runner.notification.RunListener;
     12 import org.testng.*;
     13 import org.testng.collections.Lists;
     14 import org.testng.internal.ITestResultNotifier;
     15 import org.testng.internal.InvokedMethod;
     16 import org.testng.internal.TestResult;
     17 
     18 /**
     19  * A JUnit TestRunner that records/triggers all information/events necessary to
     20  * TestNG.
     21  *
     22  * @author Lukas Jungmann
     23  */
     24 public class JUnit4TestRunner implements IJUnitTestRunner {
     25 
     26     private ITestResultNotifier m_parentRunner;
     27     private List<ITestNGMethod> m_methods = Lists.newArrayList();
     28     private List<ITestListener> m_listeners = Lists.newArrayList();
     29     private Collection<IInvokedMethodListener> m_invokeListeners = Lists.newArrayList();
     30 
     31     public JUnit4TestRunner() {
     32     }
     33 
     34     public JUnit4TestRunner(ITestResultNotifier tr) {
     35         m_parentRunner = tr;
     36         m_listeners = m_parentRunner.getTestListeners();
     37     }
     38 
     39     /**
     40      * Needed from TestRunner in order to figure out what JUnit test methods
     41      * were run.
     42      *
     43      * @return the list of all JUnit test methods run
     44      */
     45     @Override
     46     public List<ITestNGMethod> getTestMethods() {
     47         return m_methods;
     48     }
     49 
     50     @Override
     51     public void setTestResultNotifier(ITestResultNotifier notifier) {
     52         m_parentRunner = notifier;
     53         m_listeners = m_parentRunner.getTestListeners();
     54     }
     55 
     56     public void setInvokedMethodListeners(Collection<IInvokedMethodListener> listeners) {
     57         m_invokeListeners = listeners;
     58     }
     59 
     60     /**
     61      * A
     62      * <code>start</code> implementation that ignores the
     63      * <code>TestResult</code>
     64      *
     65      * @param testClass the JUnit test class
     66      */
     67     @Override
     68     public void run(Class testClass, String... methods) {
     69         start(testClass, methods);
     70     }
     71 
     72     /**
     73      * Starts a test run. Analyzes the command line arguments and runs the given
     74      * test suite.
     75      */
     76     public Result start(final Class testCase, final String... methods) {
     77         try {
     78             JUnitCore core = new JUnitCore();
     79             core.addListener(new RL());
     80             Request r = Request.aClass(testCase);
     81             return core.run(r.filterWith(new Filter() {
     82 
     83                 @Override
     84                 public boolean shouldRun(Description description) {
     85                     if (description == null) {
     86                         return false;
     87                     }
     88                     if (methods.length == 0) {
     89                         //run everything
     90                         return true;
     91                     }
     92                     for (String m: methods) {
     93                         Pattern p = Pattern.compile(m);
     94                         if (p.matcher(description.getMethodName()).matches()) {
     95                             return true;
     96                         }
     97                     }
     98                     return false;
     99                 }
    100 
    101                 @Override
    102                 public String describe() {
    103                     return "TestNG method filter";
    104                 }
    105             }));
    106         } catch (Throwable t) {
    107             throw new TestNGException("Failure in JUnit mode for class " + testCase.getName(), t);
    108         }
    109     }
    110 
    111     private class RL extends RunListener {
    112 
    113         private Map<Description, ITestResult> runs = new WeakHashMap<>();
    114         private List<Description> notified = new LinkedList<>();
    115 
    116         @Override
    117         public void testAssumptionFailure(Failure failure) {
    118             notified.add(failure.getDescription());
    119             ITestResult tr = runs.get(failure.getDescription());
    120             tr.setStatus(TestResult.SKIP);
    121             tr.setEndMillis(Calendar.getInstance().getTimeInMillis());
    122             tr.setThrowable(failure.getException());
    123             m_parentRunner.addSkippedTest(tr.getMethod(), tr);
    124             for (ITestListener l : m_listeners) {
    125                 l.onTestSkipped(tr);
    126             }
    127         }
    128 
    129         @Override
    130         public void testFailure(Failure failure) throws Exception {
    131             if (isAssumptionFailed(failure)) {
    132                 this.testAssumptionFailure(failure);
    133                 return;
    134             }
    135             notified.add(failure.getDescription());
    136             ITestResult tr = runs.get(failure.getDescription());
    137             tr.setStatus(TestResult.FAILURE);
    138             tr.setEndMillis(Calendar.getInstance().getTimeInMillis());
    139             tr.setThrowable(failure.getException());
    140             m_parentRunner.addFailedTest(tr.getMethod(), tr);
    141             for (ITestListener l : m_listeners) {
    142                 l.onTestFailure(tr);
    143             }
    144         }
    145 
    146         @Override
    147         public void testFinished(Description description) throws Exception {
    148             ITestResult tr = runs.get(description);
    149             if (!notified.contains(description)) {
    150                 tr.setStatus(TestResult.SUCCESS);
    151                 tr.setEndMillis(Calendar.getInstance().getTimeInMillis());
    152                 m_parentRunner.addPassedTest(tr.getMethod(), tr);
    153                 for (ITestListener l : m_listeners) {
    154                     l.onTestSuccess(tr);
    155                 }
    156             }
    157             m_methods.add(tr.getMethod());
    158         }
    159 
    160         @Override
    161         public void testIgnored(Description description) throws Exception {
    162             ITestResult tr = createTestResult(description);
    163             tr.setStatus(TestResult.SKIP);
    164             tr.setEndMillis(tr.getStartMillis());
    165             m_parentRunner.addSkippedTest(tr.getMethod(), tr);
    166             m_methods.add(tr.getMethod());
    167             for (ITestListener l : m_listeners) {
    168                 l.onTestSkipped(tr);
    169             }
    170         }
    171 
    172         @Override
    173         public void testRunFinished(Result result) throws Exception {
    174         }
    175 
    176         @Override
    177         public void testRunStarted(Description description) throws Exception {
    178         }
    179 
    180         @Override
    181         public void testStarted(Description description) throws Exception {
    182             ITestResult tr = createTestResult(description);
    183             runs.put(description, tr);
    184             for (ITestListener l : m_listeners) {
    185                 l.onTestStart(tr);
    186             }
    187         }
    188 
    189         private ITestResult createTestResult(Description test) {
    190             JUnit4TestClass tc = new JUnit4TestClass(test);
    191             JUnitTestMethod tm = new JUnit4TestMethod(tc, test);
    192 
    193             TestResult tr = new TestResult(tc,
    194                     test,
    195                     tm,
    196                     null,
    197                     Calendar.getInstance().getTimeInMillis(),
    198                     0,
    199                     null);
    200 
    201             InvokedMethod im = new InvokedMethod(tr.getTestClass(), tr.getMethod(), new Object[0], tr.getStartMillis(), tr);
    202             m_parentRunner.addInvokedMethod(im);
    203             for (IInvokedMethodListener l: m_invokeListeners) {
    204                 l.beforeInvocation(im, tr);
    205             }
    206             return tr;
    207         }
    208     }
    209 
    210     private static boolean isAssumptionFailed(Failure failure) {
    211         if (failure == null) {
    212             return false;
    213         }
    214         //noinspection ThrowableResultOfMethodCallIgnored
    215         final Throwable exception = failure.getException();
    216         //noinspection SimplifiableIfStatement
    217         if (exception == null) {
    218             return false;
    219         }
    220         return "org.junit.internal.AssumptionViolatedException".equals(exception.getClass().getCanonicalName());
    221     }
    222 }
    223