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.ITestClass;
import org.testng.ITestNGMethod;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import org.testng.collections.Sets;
import org.testng.internal.thread.graph.IWorker;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

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);
                    if (System.getProperty("experimental") != null) {
                        Collection> instances = createInstances(methodInstances);
                        for (List inst : instances) {
                            TestMethodWorker worker = createTestMethodWorker(arguments, inst, params, c);
                            result.add(worker);
                        }
                    }
                    else {
                        // 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) {
        List result = Lists.newArrayList();
        for (IMethodInstance mi : methodInstances) {
            if (mi.getMethod().getTestClass().getRealClass() == c) {
                result.add(mi);
            }
        }
        return result;
    }

    private static TestMethodWorker createTestMethodWorker(Arguments attributes,
            List methodInstances, Map params,
            Class c) {
        return new TestMethodWorker(attributes.getInvoker(),
                findClasses(methodInstances, c),
                attributes.getTestContext().getCurrentXmlTest().getSuite(),
                params,
                attributes.getConfigMethods(),
                attributes.getClassMethodMap(),
                attributes.getTestContext(),
                attributes.getListeners());
    }

    private List methodsToMultipleMethodInstances(ITestNGMethod... methods) {
        List vResult = Lists.newArrayList();
        for (ITestNGMethod m : methods) {
            vResult.add(new MethodInstance(m));
        }

        return vResult;
    }

    private static Collection> createInstances(List methodInstances) {
        Map> map = Maps.newHashMap();
        for (IMethodInstance imi : methodInstances) {
            Object o = imi.getInstance();
            List l = map.get(o);
            if (l == null) {
                l = Lists.newArrayList();
                map.put(o, l);
            }
            l.add(imi);
        }
        return map.values();
    }

    private static boolean isSequential(org.testng.annotations.ITestAnnotation test, XmlTest xmlTest) {
        return test != null && (test.getSequential() || 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