package org.testng.internal;

import static org.testng.internal.TestNGMethodFinder.MethodType.*;

import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import org.testng.ITestMethodFinder;
import org.testng.ITestNGMethod;
import org.testng.annotations.IConfigurationAnnotation;
import org.testng.annotations.ITestAnnotation;
import org.testng.collections.Lists;
import org.testng.internal.annotations.AnnotationHelper;
import org.testng.internal.annotations.IAnnotationFinder;
import org.testng.xml.XmlTest;

The default strategy for finding test methods: look up annotations @Test in front of methods.
/** The default strategy for finding test methods: look up annotations @Test in front of methods. */
public class TestNGMethodFinder implements ITestMethodFinder { enum MethodType { BEFORE_SUITE, AFTER_SUITE, BEFORE_TEST, AFTER_TEST, BEFORE_CLASS, AFTER_CLASS, BEFORE_TEST_METHOD, AFTER_TEST_METHOD, BEFORE_GROUPS, AFTER_GROUPS } private static final Comparator<ITestNGMethod> NO_COMPARISON = (o1, o2) -> 0; private RunInfo runInfo; private IAnnotationFinder annotationFinder; private final Comparator<ITestNGMethod> comparator; public TestNGMethodFinder(RunInfo runInfo, IAnnotationFinder annotationFinder) { this(runInfo, annotationFinder, NO_COMPARISON); } public TestNGMethodFinder( RunInfo runInfo, IAnnotationFinder annotationFinder, Comparator<ITestNGMethod> comparator) { this.runInfo = runInfo; this.annotationFinder = annotationFinder; this.comparator = comparator; } @Override public ITestNGMethod[] getTestMethods(Class<?> clazz, XmlTest xmlTest) { return AnnotationHelper.findMethodsWithAnnotation( clazz, ITestAnnotation.class, annotationFinder, xmlTest); } @Override public ITestNGMethod[] getBeforeClassMethods(Class cls) { return findConfiguration(cls, BEFORE_CLASS); } @Override public ITestNGMethod[] getAfterClassMethods(Class cls) { return findConfiguration(cls, AFTER_CLASS); } @Override public ITestNGMethod[] getBeforeTestMethods(Class cls) { return findConfiguration(cls, BEFORE_TEST_METHOD); } @Override public ITestNGMethod[] getAfterTestMethods(Class cls) { return findConfiguration(cls, AFTER_TEST_METHOD); } @Override public ITestNGMethod[] getBeforeSuiteMethods(Class cls) { return findConfiguration(cls, BEFORE_SUITE); } @Override public ITestNGMethod[] getAfterSuiteMethods(Class cls) { return findConfiguration(cls, AFTER_SUITE); } @Override public ITestNGMethod[] getBeforeTestConfigurationMethods(Class clazz) { return findConfiguration(clazz, BEFORE_TEST); } @Override public ITestNGMethod[] getAfterTestConfigurationMethods(Class clazz) { return findConfiguration(clazz, AFTER_TEST); } @Override public ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class clazz) { return findConfiguration(clazz, BEFORE_GROUPS); } @Override public ITestNGMethod[] getAfterGroupsConfigurationMethods(Class clazz) { return findConfiguration(clazz, AFTER_GROUPS); } private ITestNGMethod[] findConfiguration(final Class clazz, final MethodType configurationType) { List<ITestNGMethod> vResult = Lists.newArrayList(); Set<Method> methods = ClassHelper.getAvailableMethods(clazz); for (Method m : methods) { IConfigurationAnnotation configuration = AnnotationHelper.findConfiguration(annotationFinder, m); if (null == configuration) { continue; } boolean create; boolean isBeforeSuite = false; boolean isAfterSuite = false; boolean isBeforeTest = false; boolean isAfterTest = false; boolean isBeforeClass = false; boolean isAfterClass = false; boolean isBeforeTestMethod = false; boolean isAfterTestMethod = false; String[] beforeGroups = null; String[] afterGroups = null; switch (configurationType) { case BEFORE_SUITE: create = configuration.getBeforeSuite(); isBeforeSuite = true; break; case AFTER_SUITE: create = configuration.getAfterSuite(); isAfterSuite = true; break; case BEFORE_TEST: create = configuration.getBeforeTest(); isBeforeTest = true; break; case AFTER_TEST: create = configuration.getAfterTest(); isAfterTest = true; break; case BEFORE_CLASS: create = configuration.getBeforeTestClass(); isBeforeClass = true; break; case AFTER_CLASS: create = configuration.getAfterTestClass(); isAfterClass = true; break; case BEFORE_TEST_METHOD: create = configuration.getBeforeTestMethod(); isBeforeTestMethod = true; break; case AFTER_TEST_METHOD: create = configuration.getAfterTestMethod(); isAfterTestMethod = true; break; case BEFORE_GROUPS: beforeGroups = configuration.getBeforeGroups(); create = shouldCreateBeforeAfterGroup(beforeGroups, annotationFinder, clazz, configuration.getInheritGroups()); isBeforeTestMethod = true; break; case AFTER_GROUPS: afterGroups = configuration.getAfterGroups(); create = shouldCreateBeforeAfterGroup(afterGroups, annotationFinder, clazz, configuration.getInheritGroups()); isAfterTestMethod = true; break; default: throw new AssertionError("Unexpected value: " + configurationType); } if (create) { addConfigurationMethod( clazz, vResult, m, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeTestMethod, isAfterTestMethod, beforeGroups, afterGroups, null); /* @@@ */ } } List<ITestNGMethod> excludedMethods = Lists.newArrayList(); boolean unique = configurationType == BEFORE_SUITE || configurationType == AFTER_SUITE; return MethodHelper.collectAndOrderMethods( Lists.newArrayList(vResult), false /* forTests */, runInfo, annotationFinder, unique, excludedMethods, comparator); } private static boolean shouldCreateBeforeAfterGroup(String[] groups, IAnnotationFinder finder, Class<?> clazz, boolean isInheritGroups) { if (!isInheritGroups) { return groups.length > 0; } ITestAnnotation test = AnnotationHelper.findTest(finder, clazz); if (test == null) { return groups.length > 0; } return groups.length > 0 || test.getGroups().length > 0; } private void addConfigurationMethod( Class<?> clazz, List<ITestNGMethod> results, Method method, boolean isBeforeSuite, boolean isAfterSuite, boolean isBeforeTest, boolean isAfterTest, boolean isBeforeClass, boolean isAfterClass, boolean isBeforeTestMethod, boolean isAfterTestMethod, String[] beforeGroups, String[] afterGroups, Object instance) { if (method.getDeclaringClass().isAssignableFrom(clazz)) { ITestNGMethod confMethod = new ConfigurationMethod( new ConstructorOrMethod(method), annotationFinder, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeTestMethod, isAfterTestMethod, beforeGroups, afterGroups, instance); results.add(confMethod); } } }