Package org.testng

Source Code of org.testng.TestRunner

package org.testng;


import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.testng.internal.ClassHelper;
import org.testng.internal.ConfigurationGroupMethods;
import org.testng.internal.Constants;
import org.testng.internal.IConfigurationListener;
import org.testng.internal.IInvoker;
import org.testng.internal.IMethodWorker;
import org.testng.internal.ITestResultNotifier;
import org.testng.internal.InvokedMethod;
import org.testng.internal.Invoker;
import org.testng.internal.MethodHelper;
import org.testng.internal.MethodInstance;
import org.testng.internal.ResultMap;
import org.testng.internal.RunInfo;
import org.testng.internal.TestMethodWorker;
import org.testng.internal.TestNGClassFinder;
import org.testng.internal.TestNGMethod;
import org.testng.internal.TestNGMethodFinder;
import org.testng.internal.Utils;
import org.testng.internal.XmlMethodSelector;
import org.testng.internal.annotations.IAnnotationFinder;
import org.testng.internal.thread.ThreadUtil;
import org.testng.junit.IJUnitTestRunner;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlPackage;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

/**
* This class takes care of running one Test.
*
* @author Cedric Beust, Apr 26, 2004
* @author <a href = "mailto:the_mindstorm&#64;evolva.ro">Alexandru Popescu</a>
*/
public class TestRunner implements ITestContext, ITestResultNotifier {
  /* generated */
  private static final long serialVersionUID = 4247820024988306670L;
  private ISuite m_suite;
  protected XmlTest m_xmlTest;
  private String m_testName;
  private boolean m_debug = false;

  transient private List<XmlClass> m_testClassesFromXml= null;
  transient private List<XmlPackage> m_packageNamesFromXml= null;

  transient private IInvoker m_invoker= null;
  transient private IAnnotationFinder m_annotationFinder= null;

  /** ITestListeners support. */
  transient private List<ITestListener> m_testListeners = new ArrayList<ITestListener>();
  transient private List<IConfigurationListener> m_configurationListeners= new ArrayList<IConfigurationListener>();

  private IConfigurationListener m_confListener= new ConfigurationListener();
 
  /**
   * All the test methods we found, associated with their respective classes.
   * Note that these test methods might belong to different classes.
   * We pick which ones to run at runtime.
   */
  private ITestNGMethod[] m_allTestMethods = new ITestNGMethod[0];

  // Information about this test run

  private Date m_startDate = null;
  private Date m_endDate = null;

  /** A map to keep track of Class <-> IClass. */
  transient private Map<Class, ITestClass> m_classMap= new HashMap<Class, ITestClass>();

  /** Where the reports will be created. */
  private String m_outputDirectory= Constants.getDefaultValueFor(Constants.PROP_OUTPUT_DIR);

  // The XML method selector (groups/methods included/excluded in XML)
  private XmlMethodSelector m_xmlMethodSelector = new XmlMethodSelector();

  private static int m_verbose = 1;

  //
  // These next fields contain all the configuration methods found on this class.
  // At initialization time, they just contain all the various @Configuration methods
  // found in all the classes we are going to run.  When comes the time to run them,
  // only a subset of them are run:  those that are enabled and belong on the same class as
  // (or a parent of) the test class.
  //
  private ITestNGMethod[] m_beforeClassMethods = {};
  private ITestNGMethod[] m_afterClassMethods = {};
  /** */
  private ITestNGMethod[] m_beforeSuiteMethods = {};
  private ITestNGMethod[] m_afterSuiteMethods = {};
  private ITestNGMethod[] m_beforeXmlTestMethods = {};
  private ITestNGMethod[] m_afterXmlTestMethods = {};
  private List<ITestNGMethod> m_excludedMethods = new ArrayList<ITestNGMethod>();
  private ConfigurationGroupMethods m_groupMethods = null;

  // Meta groups
  private Map<String, List<String>> m_metaGroups = new HashMap<String, List<String>>();

  // All the tests that were run along with their result
  private IResultMap m_passedTests = new ResultMap();
  private IResultMap m_failedTests = new ResultMap();
  private IResultMap m_failedButWithinSuccessPercentageTests = new ResultMap();
  private IResultMap m_skippedTests = new ResultMap();

  private RunInfo m_runInfo= new RunInfo();
 
  // The host where this test was run, or null if run locally
  private String m_host;

  public TestRunner(ISuite suite,
                    XmlTest test,
                    String outputDirectory,
                    IAnnotationFinder finder) {
    init(suite, test, outputDirectory, finder);
  }

  public TestRunner(ISuite suite, XmlTest test, IAnnotationFinder finder) {
    init(suite, test, suite.getOutputDirectory(), finder);
  }

  public TestRunner(ISuite suite, XmlTest test) {
    init(suite, test, suite.getOutputDirectory(), suite.getAnnotationFinder(test.getAnnotations()));
  }

  private void init(ISuite suite,
                    XmlTest test,
                    String outputDirectory,
                    IAnnotationFinder annotationFinder)
  {
    m_xmlTest= test;
    m_suite = suite;
    m_testName = test.getName();
    m_host = suite.getHost();
    m_testClassesFromXml= test.getXmlClasses();

    m_packageNamesFromXml= test.getXmlPackages();   
    if(null != m_packageNamesFromXml) {
      for(XmlPackage xp: m_packageNamesFromXml) {
        m_testClassesFromXml.addAll(xp.getXmlClasses());
      }
    }

    m_annotationFinder= annotationFinder;
    m_invoker= new Invoker(this, this, m_suite.getSuiteState(), m_annotationFinder);

    setVerbose(test.getVerbose());

    if (suite.getParallel() != null) {
      log(3, "Running the tests in '" + test.getName() + "' with parallel mode:" + suite.getParallel());
    }

    setOutputDirectory(outputDirectory);

    // Finish our initialization
    init();
  }

  public IInvoker getInvoker() {
    return m_invoker;
  }

  public ITestNGMethod[] getBeforeSuiteMethods() {
    return m_beforeSuiteMethods;
  }

  public ITestNGMethod[] getAfterSuiteMethods() {
    return m_afterSuiteMethods;
  }

  public ITestNGMethod[] getBeforeTestConfigurationMethods() {
    return m_beforeXmlTestMethods;
  }

  public ITestNGMethod[] getAfterTestConfigurationMethods() {
    return m_afterXmlTestMethods;
  }

  private void init() {
    initMetaGroups(m_xmlTest);
    initRunInfo(m_xmlTest);

    // Init methods and class map
    // JUnit behavior is different and doesn't need this initialization step
    if(!m_xmlTest.isJUnit()) {
      initMethods();
    }

    addConfigurationListener(m_confListener);
  }

  /**
   * Initialize meta groups
   */
  private void initMetaGroups(XmlTest xmlTest) {
    Map<String, List<String>> metaGroups = xmlTest.getMetaGroups();

    for (String name : metaGroups.keySet()) {
      addMetaGroup(name, metaGroups.get(name));
    }
  }

  private void initRunInfo(final XmlTest xmlTest) {
    // Groups
    m_xmlMethodSelector.setIncludedGroups(createGroups(m_xmlTest.getIncludedGroups()));
    m_xmlMethodSelector.setExcludedGroups(createGroups(m_xmlTest.getExcludedGroups()));
    m_xmlMethodSelector.setExpression(m_xmlTest.getExpression());

    // Methods
    m_xmlMethodSelector.setXmlClasses(m_xmlTest.getXmlClasses());
   
    m_runInfo.addMethodSelector(m_xmlMethodSelector, 10);
   
    // Add user-specified method selectors (only class selectors, we can ignore
    // script selectors here)
    if (null != xmlTest.getMethodSelectors()) {
      for (org.testng.xml.XmlMethodSelector selector : xmlTest.getMethodSelectors()) {
        if (selector.getClassName() != null) {
          IMethodSelector s = ClassHelper.createSelector(selector);
         
          m_runInfo.addMethodSelector(s, selector.getPriority());
        }
      }
    }
  }

  private void initMethods() {

    //
    // Calculate all the methods we need to invoke
    //
    List<ITestNGMethod> beforeClassMethods = new ArrayList<ITestNGMethod>();
    List<ITestNGMethod> testMethods = new ArrayList<ITestNGMethod>();
    List<ITestNGMethod> afterClassMethods = new ArrayList<ITestNGMethod>();
    List<ITestNGMethod> beforeSuiteMethods = new ArrayList<ITestNGMethod>();
    List<ITestNGMethod> afterSuiteMethods = new ArrayList<ITestNGMethod>();
    List<ITestNGMethod> beforeXmlTestMethods = new ArrayList<ITestNGMethod>();
    List<ITestNGMethod> afterXmlTestMethods = new ArrayList<ITestNGMethod>();

    ITestClassFinder testClassFinder= new TestNGClassFinder(Utils.xmlClassesToClasses(m_testClassesFromXml),
                                             null,
                                             m_xmlTest,
                                             m_annotationFinder);
    ITestMethodFinder testMethodFinder= new TestNGMethodFinder(m_runInfo, m_annotationFinder);
   
    m_runInfo.setTestMethods(testMethods);
   
    //
    // Initialize TestClasses
    //
    IClass[] classes = testClassFinder.findTestClasses();
   
    for (IClass ic : classes) {

      // Create TestClass
      ITestClass tc = new TestClass(ic,
                                   m_testName,
                                   testMethodFinder,
                                   m_annotationFinder,
                                   m_runInfo);
      m_classMap.put(ic.getRealClass(), tc);
    }
   
    //
    // Calculate groups methods
    //
    Map<String, List<ITestNGMethod>> beforeGroupMethods= MethodHelper.findGroupsMethods(m_classMap.values(), true);
    Map<String, List<ITestNGMethod>> afterGroupMethods= MethodHelper.findGroupsMethods(m_classMap.values(), false);

    //
    // Walk through all the TestClasses, store their method
    // and initialize them with the correct ITestClass
    //
    for (ITestClass tc : m_classMap.values()) {
      fixMethodsWithClass(tc.getBeforeClassMethods(), tc, beforeClassMethods);
      fixMethodsWithClass(tc.getBeforeTestMethods(), tc, null); // HINT: does not link back to beforeTestMethods
      fixMethodsWithClass(tc.getTestMethods(), tc, testMethods);
      fixMethodsWithClass(tc.getAfterTestMethods(), tc, null);
      fixMethodsWithClass(tc.getAfterClassMethods(), tc, afterClassMethods);
      fixMethodsWithClass(tc.getBeforeSuiteMethods(), tc, beforeSuiteMethods);
      fixMethodsWithClass(tc.getAfterSuiteMethods(), tc, afterSuiteMethods);
      fixMethodsWithClass(tc.getBeforeTestConfigurationMethods(), tc, beforeXmlTestMethods);
      fixMethodsWithClass(tc.getAfterTestConfigurationMethods(), tc, afterXmlTestMethods);
      fixMethodsWithClass(tc.getBeforeGroupsMethods(), tc,
          MethodHelper.uniqueMethodList(beforeGroupMethods.values()));
      fixMethodsWithClass(tc.getAfterGroupsMethods(), tc,
          MethodHelper.uniqueMethodList(afterGroupMethods.values()));
    }

    //
    // Sort the methods
    //
    m_beforeSuiteMethods = MethodHelper.collectAndOrderMethods(beforeSuiteMethods,
                                                              false,
                                                              m_runInfo,
                                                              m_annotationFinder,
                                                              true /* unique */,
                                                              m_excludedMethods);

    m_beforeXmlTestMethods = MethodHelper.collectAndOrderMethods(beforeXmlTestMethods,
                                                                false,
                                                                m_runInfo,
                                                                m_annotationFinder,
                                                                true, // CQ added by me
                                                                m_excludedMethods);

    m_beforeClassMethods = MethodHelper.collectAndOrderMethods(beforeClassMethods,
                                                              false,
                                                              m_runInfo,
                                                              m_annotationFinder,
                                                              m_excludedMethods);

    m_allTestMethods = MethodHelper.collectAndOrderMethods(testMethods,
                                                          true,
                                                          m_runInfo,
                                                          m_annotationFinder,
                                                          m_excludedMethods);

    m_afterClassMethods = MethodHelper.collectAndOrderMethods(afterClassMethods,
                                                             false,
                                                             m_runInfo,
                                                             m_annotationFinder,
                                                             m_excludedMethods);

    m_afterXmlTestMethods = MethodHelper.collectAndOrderMethods(afterXmlTestMethods,
                                                               false,
                                                               m_runInfo,
                                                               m_annotationFinder,
                                                               true, // CQ added by me
                                                               m_excludedMethods);

    m_afterSuiteMethods = MethodHelper.collectAndOrderMethods(afterSuiteMethods,
                                                             false,
                                                             m_runInfo,
                                                             m_annotationFinder,
                                                             true /* unique */,
                                                             m_excludedMethods);
    // shared group methods
    m_groupMethods = new ConfigurationGroupMethods(m_allTestMethods, beforeGroupMethods, afterGroupMethods);
  }

  private static void ppp(String s) {
    if (true) {
      System.out.println("[TestRunner] " + s);
    }
  }

  private void fixMethodsWithClass(ITestNGMethod[] methods,
                                   ITestClass testCls,
                                   List<ITestNGMethod> methodList) {
    for (ITestNGMethod itm : methods) {
      itm.setTestClass(testCls);

      if (methodList != null) {
        methodList.add(itm);
      }
    }
  }

  public Collection<ITestClass> getIClass() {
    return m_classMap.values();
  }

  /**
   * FIXME: not used
   */
  private IClass findIClass(IClass[] classes, Class cls) {
    for (IClass c : classes) {
      if (c.getRealClass().equals(cls)) {
        return c;
      }
    }

    return null;
  }

  public void setTestName(String name) {
    m_testName = name;
  }

  public void setOutputDirectory(String od) {
  if (od == null) { m_outputDirectory = null; return; } //for maven2
    File file = new File(od);
    file.mkdirs();
    m_outputDirectory= file.getAbsolutePath();
  }

  private void addMetaGroup(String name, List<String> groupNames) {
    m_metaGroups.put(name, groupNames);
  }

  /**
   * Calculate the transitive closure of all the MetaGroups
   *
   * @param groups
   * @param unfinishedGroups
   * @param result           The transitive closure containing all the groups found
   */
  private void collectGroups(String[] groups,
                             List<String> unfinishedGroups,
                             Map<String, String> result) {
    for (String gn : groups) {
      List<String> subGroups = m_metaGroups.get(gn);
      if (null != subGroups) {

        for (String sg : subGroups) {
          if (null == result.get(sg)) {
            result.put(sg, sg);
            unfinishedGroups.add(sg);
          }
        }
      }
    }
  }

  private Map<String, String> createGroups(List<String> groups) {
    return createGroups((String[]) groups.toArray(new String[groups.size()]));
  }

  private Map<String, String> createGroups(String[] groups) {
    Map<String, String> result= new HashMap<String, String>();

    // Groups that were passed on the command line
    for (String group : groups) {
      result.put(group, group);
    }

    // See if we have any MetaGroups and
    // expand them if they match one of the groups
    // we have just been passed
    List<String> unfinishedGroups = new ArrayList<String>();

    if (m_metaGroups.size() > 0) {
      collectGroups(groups, unfinishedGroups, result);

      // Do we need to loop over unfinished groups?
      while (unfinishedGroups.size() > 0) {
        String[] uGroups = (String[]) unfinishedGroups.toArray(new String[unfinishedGroups.size()]);
        unfinishedGroups = new ArrayList<String>();
        collectGroups(uGroups, unfinishedGroups, result);
      }
    }

    //    Utils.dumpMap(result);
    return result;
  }

  /**
   * The main entry method for TestRunner.
   *
   * This is where all the hard work is done:
   * - Invoke configuration methods
   * - Invoke test methods
   * - Catch exceptions
   * - Collect results
   * - Invoke listeners
   * - etc...
   */
  public void run() {
    beforeRun();

    try {
      XmlTest test= getTest();
      if(test.isJUnit()) {
        privateRunJUnit(test);
      }
      else {
        privateRun(test);
      }
    }
    finally {
      afterRun();
    }
  }

  /** Before run preparements. */
  private void beforeRun() {
    //
    // Log the start date
    //
    m_startDate = new Date(System.currentTimeMillis());

    // Log start
    logStart();

    // Invoke listeners
    fireEvent(true /*start*/);
   
    // invoke @BeforeTest
    ITestNGMethod[] testConfigurationMethods= getBeforeTestConfigurationMethods();
    if(null != testConfigurationMethods && testConfigurationMethods.length > 0) {
      m_invoker.invokeConfigurations(null,
                                     testConfigurationMethods,
                                     m_xmlTest.getSuite(),
                                     m_xmlTest.getParameters(),
                                     null /* instance */);
    }
  }

  private void privateRunJUnit(XmlTest xmlTest) {
    final Class[] classes= Utils.xmlClassesToClasses(m_testClassesFromXml);
    final List<ITestNGMethod> runMethods= new ArrayList<ITestNGMethod>();
    List<IMethodWorker> workers= new ArrayList<IMethodWorker>();
    // FIXME: directly referincing JUnitTestRunner which uses JUnit classes
    // may result in an class resolution exception under different JVMs
    // The resolution process is not specified in the JVM spec with a specific implementation,
    // so it can be eager => failure
    workers.add(new IMethodWorker() {
      /**
       * @see org.testng.internal.IMethodWorker#getMaxTimeOut()
       */
      public long getMaxTimeOut() {
        return 0;
      }
     
      /**
       * @see java.lang.Runnable#run()
       */
      public void run() {   
        for(Class tc: classes) {
          IJUnitTestRunner tr= ClassHelper.createTestRunner(TestRunner.this);
          try {
            tr.run(tc);
          }
          catch(Exception ex) {
            ex.printStackTrace();
          }
          finally {
            runMethods.addAll(tr.getTestMethods());
          }
        }
      }
    });

    runWorkers(workers, "" /* JUnit does not support parallel */);
    m_allTestMethods= runMethods.toArray(new ITestNGMethod[runMethods.size()]);
  }
 
  public void privateRun(XmlTest xmlTest) {
    Map<String, String> params = xmlTest.getParameters();

    //
    // Calculate the lists of tests that can be run in sequence and in parallel
    //
    List<List<ITestNGMethod>> sequentialList= new ArrayList<List<ITestNGMethod>>();
    List<ITestNGMethod> parallelList= new ArrayList<ITestNGMethod>();

    computeTestLists(sequentialList, parallelList);
   
    log(3, "Found " + (sequentialList.size() + parallelList.size()) + " applicable methods");
   
    //
    // Find out all the group methods
    //
//    m_groupMethods = findGroupMethods(m_classMap.values());

    //
    // Create the workers
    //
    List<TestMethodWorker> workers = new ArrayList<TestMethodWorker>();
   
    // These two variables are used throughout the workers to keep track
    // of what beforeClass/afterClass methods have been invoked
    Map<ITestClass, ITestClass> beforeClassMethods = new HashMap<ITestClass, ITestClass>();
    Map<ITestClass, ITestClass> afterClassMethods = new HashMap<ITestClass, ITestClass>();
   
    ClassMethodMap cmm = new ClassMethodMap(m_allTestMethods);
   
    // All the sequential tests are place in one worker, guaranteeing they
    // will be invoked sequentially
    if (sequentialList.size() > 0) {
      for (List<ITestNGMethod> sl : sequentialList) {
       
        workers.add(new TestMethodWorker(m_invoker,
                                         methodsToMethodInstances(sl),
                                         m_xmlTest.getSuite(),
                                         params,
                                         beforeClassMethods,
                                         afterClassMethods,
                                         m_allTestMethods,
                                         m_groupMethods,
                                         cmm,
                                         this));
      }
    }

    // All the parallel tests are placed in a separate worker, so they can be
    // invoked in parallel
    if (parallelList.size() > 0) {
      for (ITestNGMethod tm : parallelList) {
//        MethodInstance mi = new MethodInstance(tm, tm.getTestClass().getInstances(true));
        MethodInstance[] methodInstances = methodsToMultipleMethodInstances(Arrays.asList(new ITestNGMethod[] {tm}));
        for (MethodInstance mi : methodInstances) {
          workers.add(new TestMethodWorker(m_invoker,
                                           new MethodInstance[] { mi },
                                           m_xmlTest.getSuite(),
                                           params,
                                           beforeClassMethods,
                                           afterClassMethods,
                                           m_allTestMethods,
                                           m_groupMethods,
                                           cmm,
                                           this));
        }
      }
    }

    runWorkers(workers, xmlTest.getParallel());
  }

  private MethodInstance[] methodsToMultipleMethodInstances(List<ITestNGMethod> sl) {
    List<MethodInstance> vResult = new ArrayList<MethodInstance>();
    for (ITestNGMethod m : sl) {
      Object[] instances = m.getTestClass().getInstances(true);
      for (Object instance : instances) {
        vResult.add(new MethodInstance(m, new Object[] { instance }));
      }
    }
   
    MethodInstance[] result = vResult.toArray(new MethodInstance[vResult.size()]);
    return result;
  }

  private MethodInstance[] methodsToMethodInstances(List<ITestNGMethod> sl) {
    MethodInstance[] result = new MethodInstance[sl.size()];
    for (int i = 0; i < result.length; i++) {
      result[i] = new MethodInstance(sl.get(i), sl.get(i).getTestClass().getInstances(true));
    }
   
    return result;
  }

  //
  // Invoke the workers
  //
  private void runWorkers(List<? extends IMethodWorker> workers, String parallelMode) {
    if (XmlSuite.PARALLEL_METHODS.equals(parallelMode)
        || "true".equalsIgnoreCase(parallelMode)
//        || XmlSuite.PARALLEL_TESTS.equals(parallelMode)
        )
    {
      //
      // Parallel run
      //
      // Default timeout for individual methods:  10 seconds
      long maxTimeOut = m_xmlTest.getTimeOut(10 * 1000);
      for (IMethodWorker tmw : workers) {
        long mt= tmw.getMaxTimeOut();
        if (mt > maxTimeOut) {
          maxTimeOut= mt;
        }
      }

      ThreadUtil.execute(workers, m_xmlTest.getThreadCount(), maxTimeOut, false);
    }
    else {
      //
      // Sequential run
      //
      for (IMethodWorker tmw : workers) {
        tmw.run();
      }
    }
  }
 
  private void afterRun() {
    // invoke @AfterTest
    ITestNGMethod[] testConfigurationMethods= getAfterTestConfigurationMethods();
    if(null != testConfigurationMethods && testConfigurationMethods.length > 0) {
      m_invoker.invokeConfigurations(null,
                                     testConfigurationMethods,
                                     m_xmlTest.getSuite(),
                                     m_xmlTest.getParameters(),
                                     null /* instance */);
    }

    //
    // Log the end date
    //
    m_endDate = new Date(System.currentTimeMillis());
   
    if (getVerbose() >= 3) {
      dumpInvokedMethods();
    }

    // Invoke listeners
    fireEvent(false /*stop*/);

    // Statistics
//    logResults();
  }
 
  /**
   * @param regexps
   * @param group
   * @return true if the map contains at least one regexp that matches the
   * given group
   */
  private boolean containsString(Map<String, String> regexps, String group) {
    for (String regexp : regexps.values()) {
      boolean match = Pattern.matches(regexp, group);
      if (match) {
        return true;
      }
    }
   
    return false;
  }

  /**
   * Creates the
   * @param sl the sequential list of methods
   * @param parallelList the list of methods that can be run in parallel
   */
  private void computeTestLists(List<List<ITestNGMethod>> sl,
                                List<ITestNGMethod> parallelList)
  {

    Map<String, String> groupsDependedUpon= new HashMap<String, String>();
    Map<String, String> methodsDependedUpon= new HashMap<String, String>();
   
    Map<String, List<ITestNGMethod>> sequentialAttributeList = new HashMap<String, List<ITestNGMethod>>();
    List<ITestNGMethod> sequentialList = new ArrayList<ITestNGMethod>();

    for (int i= m_allTestMethods.length - 1; i >= 0; i--) {
      ITestNGMethod tm= m_allTestMethods[i];
     
      //
      // If the class this method belongs to has @Test(sequential = true), we
      // put this method in the sequential list right away
      //
      Class cls = tm.getMethod().getDeclaringClass();
      org.testng.internal.annotations.ITest test =
        (org.testng.internal.annotations.ITest) m_annotationFinder.
          findAnnotation(cls, org.testng.internal.annotations.ITest.class);
      if (test != null) {
        if (test.getSequential()) {
          String className = cls.getName();
          List<ITestNGMethod> list = sequentialAttributeList.get(className);
          if (list == null) {
            list = new ArrayList<ITestNGMethod>();
            sequentialAttributeList.put(className, list);
          }
          list.add(0, tm);
          continue;
        }
      }
     
      //
      // Otherwise, determine if it depends on other methods/groups or if
      // it is depended upon
      //
      String[] currentGroups = tm.getGroups();
      String[] currentGroupsDependedUpon= tm.getGroupsDependedUpon();
      String[] currentMethodsDependedUpon= tm.getMethodsDependedUpon();

      String thisMethodName = tm.getMethod().getDeclaringClass().getName() + "." +
        tm.getMethod().getName();
      if (currentGroupsDependedUpon.length > 0) {
        for (String gdu : currentGroupsDependedUpon) {
          groupsDependedUpon.put(gdu, gdu);
        }

        sequentialList.add(0, tm);
      }
      else if (currentMethodsDependedUpon.length > 0) {
        for (String cmu : currentMethodsDependedUpon) {
          methodsDependedUpon.put(cmu, cmu);
        }
        sequentialList.add(0, tm);
      }
      // Is there a method that depends on the current method?
      else if (containsString(methodsDependedUpon, thisMethodName)) {
        sequentialList.add(0, tm);
      }
      else if (currentGroups.length > 0) {
        boolean isSequential= false;

        for (String group : currentGroups) {
          if (containsString(groupsDependedUpon, group)) {
            sequentialList.add(0, tm);
            isSequential = true;

            break;
          }
        }
        if (!isSequential) {
          parallelList.add(0, tm);
        }
      }
      else {
        parallelList.add(0, tm);
      }
    }
   
    //
    // Put all the sequential methods in the output argument
    //
    if(sequentialList.size() > 0) {
      sl.add(sequentialList);
    }
   
    for (List<ITestNGMethod> l : sequentialAttributeList.values()) {
      sl.add(l);
    }
   
    //
    // Finally, sort the parallel methods by classes
    //

    Collections.sort(parallelList, TestNGMethod.SORT_BY_CLASS);

    if (getVerbose() >= 2) {
      log(3, "WILL BE RUN IN RANDOM ORDER:");
      for (ITestNGMethod tm : parallelList) {
        log(3, "  " + tm);
      }

      log(3, "WILL BE RUN SEQUENTIALLY:");
      for (List<ITestNGMethod> l : sl) {
        for (ITestNGMethod tm : l) {
          log(3, "  " + tm);
        }
        log(3, "====");
      }
     
      log(3, "===");
    }
  }

  /**
   * Logs the beginning of the {@link #beforeRun()} .
   */
  private void logStart() {
    log(3,
        "Running test " + m_testName + " on " + m_classMap.size() + " " + " classes, "
        + " included groups:[" + mapToString(m_xmlMethodSelector.getIncludedGroups())
        + "] excluded groups:[" + mapToString(m_xmlMethodSelector.getExcludedGroups()) + "]");

    if (getVerbose() >= 3) {
      for (ITestClass tc : m_classMap.values()) {
        ((TestClass) tc).dump();
      }
    }
  }

  /**
   * Trigger the start/finish event.
   *
   * @param isStart <tt>true</tt> if the event is for start, <tt>false</tt> if the
   *                event is for finish
   */
  private void fireEvent(boolean isStart) {
    for (ITestListener itl : m_testListeners) {
      if (isStart) {
        itl.onStart(this);
      }
      else {
        itl.onFinish(this);
      }
    }
  }

  /////
  // ITestContext
  //
  public String getName() {
    return m_testName;
  }

  /**
   * @return Returns the startDate.
   */
  public Date getStartDate() {
    return m_startDate;
  }

  /**
   * @return Returns the endDate.
   */
  public Date getEndDate() {
    return m_endDate;
  }

  public IResultMap getPassedTests() {
    return m_passedTests;
  }

  public IResultMap getSkippedTests() {
    return m_skippedTests;
  }

  public IResultMap getFailedTests() {
    return m_failedTests;
  }

  public IResultMap getFailedButWithinSuccessPercentageTests() {
    return m_failedButWithinSuccessPercentageTests;
  }

  public String[] getIncludedGroups() {
    Map<String, String> ig= m_xmlMethodSelector.getIncludedGroups();
    String[] result= (String[]) ig.values().toArray((new String[ig.size()]));

    return result;
  }

  public String[] getExcludedGroups() {
    Map<String, String> eg= m_xmlMethodSelector.getExcludedGroups();
    String[] result= (String[]) eg.values().toArray((new String[eg.size()]));

    return result;
  }

  public String getOutputDirectory() {
    return m_outputDirectory;
  }

  /**
   * @return Returns the suite.
   */
  public ISuite getSuite() {
    return m_suite;
  }

  public ITestNGMethod[] getAllTestMethods() {
    return m_allTestMethods;
  }

 
  public String getHost() {
    return m_host;
  }

  public Collection<ITestNGMethod> getExcludedMethods() {
    Map<ITestNGMethod, ITestNGMethod> vResult =
      new HashMap<ITestNGMethod, ITestNGMethod>();
   
    for (ITestNGMethod m : m_excludedMethods) {
      vResult.put(m, m);
    }
   
    return vResult.keySet();
  }

  /**
   * @see org.testng.ITestContext#getFailedConfigurations()
   */
  public IResultMap getFailedConfigurations() {
    return m_failedConfigurations;
  }

  /**
   * @see org.testng.ITestContext#getPassedConfigurations()
   */
  public IResultMap getPassedConfigurations() {
    return m_passedConfigurations;
  }

  /**
   * @see org.testng.ITestContext#getSkippedConfigurations()
   */
  public IResultMap getSkippedConfigurations() {
    return m_skippedConfigurations;
  }
 
  //
  // ITestContext
  /////
 
  /////
  // ITestResultNotifier
  //

  public void addPassedTest(ITestNGMethod tm, ITestResult tr) {
    synchronized(m_passedTests) {
      m_passedTests.addResult(tr, tm);
    }
  }

  public Set<ITestResult> getPassedTests(ITestNGMethod tm) {
    return m_passedTests.getResults(tm);
  }

  public void addSkippedTest(ITestNGMethod tm, ITestResult tr) {
    synchronized(m_skippedTests) {
      m_skippedTests.addResult(tr, tm);
    }
  }

  public void addInvokedMethod(InvokedMethod im) {
    synchronized(m_invokedMethods) {
      m_invokedMethods.add(im);
    }
  }

  public void addFailedTest(ITestNGMethod testMethod, ITestResult result) {
    logFailedTest(testMethod, result, false /* withinSuccessPercentage */);
  }

  public void addFailedButWithinSuccessPercentageTest(ITestNGMethod testMethod,
                                                      ITestResult result) {
    logFailedTest(testMethod, result, true /* withinSuccessPercentage */);
  }

  public XmlTest getTest() {
    return m_xmlTest;
  }

  public List<ITestListener> getTestListeners() {
    return m_testListeners;
  }

  public List<IConfigurationListener> getConfigurationListeners() {
    return m_configurationListeners;
  }
  //
  // ITestResultNotifier
  /////

//  public ITestNGMethod[] getTestMethods() {
//    return m_allTestMethods;
//  }

  private void logFailedTest(ITestNGMethod method,
                             ITestResult tr,
                             boolean withinSuccessPercentage) {
    if (withinSuccessPercentage) {
      synchronized(m_failedButWithinSuccessPercentageTests) {
        m_failedButWithinSuccessPercentageTests.addResult(tr, method);
      }
    }
    else {
      synchronized(m_failedTests) {
        m_failedTests.addResult(tr, method);
      }
    }
  }

  private String mapToString(Map m) {
    StringBuffer result= new StringBuffer();
    for (Object o : m.values()) {
      result.append(o.toString()).append(" ");
    }

    return result.toString();
  }

  private void log(int level, String s) {
    Utils.log("TestRunner", level, s);
  }

  public static int getVerbose() {
    return m_verbose;
  }

  public void setVerbose(int n) {
    m_verbose = n;
  }

  private void log(String s) {
    Utils.log("TestRunner", 2, s);
  }

  /////
  // Listeners
  //
  public void addListener(Object listener) {
    if(listener instanceof ITestListener) {
      addTestListener((ITestListener) listener);
    }
    if(listener instanceof IConfigurationListener) {
      addConfigurationListener((IConfigurationListener) listener);
    }
  }
 
  public void addTestListener(ITestListener il) {
    m_testListeners.add(il);
  }

  public void addConfigurationListener(IConfigurationListener icl) {
    m_configurationListeners.add(icl);
  }
  //
  // Listeners
  /////

  private List<InvokedMethod> m_invokedMethods = new ArrayList<InvokedMethod>();

  private void dumpInvokedMethods() {
    System.out.println("\n*********** INVOKED METHODS\n");
    for (InvokedMethod im : m_invokedMethods) {
      if (im.isTestMethod()) {
        System.out.print("\t\t");
      }
      else if (im.isConfigurationMethod()) {
        System.out.print("\t");
      }
      else {
        continue;
      }
      System.out.println("" + im);
    }
    System.out.println("\n***********\n");
  }

  /**
   * @return
   */
  public List<ITestNGMethod> getInvokedMethods() {
    List<ITestNGMethod> result= new ArrayList<ITestNGMethod>();
    for (InvokedMethod im : m_invokedMethods) {
      ITestNGMethod tm= im.getTestMethod();
      tm.setDate(im.getDate());
      result.add(tm);
    }

    return result;
  }

  private IResultMap m_passedConfigurations= new ResultMap();
  private IResultMap m_skippedConfigurations= new ResultMap();
  private IResultMap m_failedConfigurations= new ResultMap();
 
  private class ConfigurationListener implements IConfigurationListener {
    public void onConfigurationFailure(ITestResult itr) {
      synchronized(m_failedConfigurations) {
        m_failedConfigurations.addResult(itr, itr.getMethod());
      }
    }

    public void onConfigurationSkip(ITestResult itr) {
      synchronized(m_skippedConfigurations) {
        m_skippedConfigurations.addResult(itr, itr.getMethod());
      }
    }

    public void onConfigurationSuccess(ITestResult itr) {
      synchronized(m_passedConfigurations) {
        m_passedConfigurations.addResult(itr, itr.getMethod());
      }
    }
  }
} // TestRunner
TOP

Related Classes of org.testng.TestRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.