All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testng.internal.ClassBasedParallelWorker Maven / Gradle / Ivy

There is a newer version: 7.10.1
Show newest version
package org.testng.internal;

import org.testng.IMethodInstance;
import org.testng.ITestNGMethod;
import org.testng.collections.Lists;
import org.testng.collections.Sets;
import org.testng.thread.IWorker;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

class ClassBasedParallelWorker extends AbstractParallelWorker {

  @Override
  public List> createWorkers(Arguments arguments) {
    List> result = Lists.newArrayList();
    // Methods that belong to classes with a sequential=true or parallel=classes
    // attribute must all be run in the same worker
    Set> sequentialClasses = Sets.newHashSet();
    for (ITestNGMethod m : arguments.getMethods()) {
      Class cls = m.getRealClass();
      org.testng.annotations.ITestAnnotation test =
          arguments.getFinder().findAnnotation(cls, org.testng.annotations.ITestAnnotation.class);

      // If either sequential=true or parallel=classes, mark this class sequential
      if (isSequential(test, arguments.getTestContext().getCurrentXmlTest())) {
        sequentialClasses.add(cls);
      }
    }

    List methodInstances = Lists.newArrayList();
    for (ITestNGMethod tm : arguments.getMethods()) {
      methodInstances.addAll(methodsToMultipleMethodInstances(tm));
    }

    Set> processedClasses = Sets.newHashSet();
    Map params = null;
    Class prevClass = null;
    for (IMethodInstance im : methodInstances) {
      Class c = im.getMethod().getTestClass().getRealClass();
      if (!c.equals(prevClass)) {
        // Calculate the parameters to be injected only once per Class and NOT for every iteration.
        params = getParameters(im);
        prevClass = c;
      }
      if (sequentialClasses.contains(c)) {
        if (!processedClasses.contains(c)) {
          processedClasses.add(c);
          // Sequential class: all methods in one worker
          TestMethodWorker worker = createTestMethodWorker(arguments, methodInstances, params, c);
          result.add(worker);
        }
      } else {
        // Parallel class: each method in its own worker
        TestMethodWorker worker =
            createTestMethodWorker(arguments, Collections.singletonList(im), params, c);
        result.add(worker);
      }
    }

    return result;
  }

  private static List findClasses(
      List methodInstances, Class c) {
    return methodInstances
        .stream()
        .filter(mi -> mi.getMethod().getTestClass().getRealClass() == c)
        .collect(Collectors.toList());
  }

  private static TestMethodWorker createTestMethodWorker(
      Arguments attributes,
      List methodInstances,
      Map params,
      Class c) {
    IInvoker invoker = attributes.getInvoker();
    ITestInvoker testInvoker = invoker.getTestInvoker();
    IConfigInvoker configInvoker = invoker.getConfigInvoker();
    return new TestMethodWorker(
        testInvoker, configInvoker, findClasses(methodInstances, c),
        params,
        attributes.getConfigMethods(),
        attributes.getClassMethodMap(),
        attributes.getTestContext(),
        attributes.getListeners());
  }

  private List methodsToMultipleMethodInstances(ITestNGMethod... methods) {
    return Arrays.stream(methods).map(MethodInstance::new).collect(Collectors.toList());
  }

  private static boolean isSequential(
      org.testng.annotations.ITestAnnotation test, XmlTest xmlTest) {
    return test != null && test.getSingleThreaded()
        || XmlSuite.ParallelMode.CLASSES.equals(xmlTest.getParallel());
  }

  private static Map getParameters(IMethodInstance im) {
    XmlTest xmlTest = im.getMethod().getXmlTest();
    return im.getMethod().findMethodParameters(xmlTest);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy