package org.test4j.junit.filter.acceptor;
import java.lang.reflect.*;
import java.util.*;
import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.test4j.junit.filter.SuiteType;
import org.test4j.junit.filter.finder.FilterCondiction;
import org.test4j.tools.commons.AnnotationHelper;
import org.test4j.tools.commons.ClazzHelper;
/**
* ClassTester implementation to retrieve JUnit38 & 4.x test classes in the
* classpath. You can specify if you want to include jar files in the search and
* you can give a set of regex expression to specify the class names to include.
*
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class TestInClasspathAcceptor implements TestAcceptor {
private final FilterCondiction testerFilter;
public TestInClasspathAcceptor(FilterCondiction testerFilter) {
this.testerFilter = testerFilter;
}
/**
* 测试类是否是指定的测试类型
*/
public boolean isCorrectTestType(Class<?> clazz) {
List<SuiteType> types = testerFilter.getSuiteTypes();
if (types.contains(SuiteType.JUNT4_TEST_CLASSES)) {
if (isJunit4TestClaz(clazz)) {
return true;
}
}
if (types.contains(SuiteType.JUNIT38_TEST_CLASSES)) {
if (isJUnit38TestClaz(clazz)) {
return true;
}
}
if (types.contains(SuiteType.SUITE_TEST_CLASSES)) {
return isJunit4SuiteClaz(clazz);
}
return false;
}
/**
* 是否是junit38类型测试
*
* @param clazz
* @return
*/
private boolean isJUnit38TestClaz(Class<?> clazz) {
return TestCase.class.isAssignableFrom(clazz);
}
/**
* 是否是JUnit4类型测试
*
* @param clazz
* @return
*/
private boolean isJunit4TestClaz(Class<?> clazz) {
try {
for (Method method : clazz.getMethods()) {
if (method.getAnnotation(Test.class) != null) {
return true;
}
}
} catch (NoClassDefFoundError ignore) {
}
return false;
}
/**
* 是否是junit4 suite类型测试
*
* @param clazz
* @return
*/
private boolean isJunit4SuiteClaz(Class<?> clazz) {
RunWith runwith = AnnotationHelper.getClassLevelAnnotation(RunWith.class, clazz);
if (runwith == null) {
return false;
} else {
return Suite.class.isAssignableFrom(runwith.value());
}
}
public boolean isCorrectClazType(Class<?> clazz) {
if (clazz == null || ClazzHelper.isAbstract(clazz) || clazz.isAnonymousClass() || clazz.isInterface()
|| clazz.isLocalClass() || clazz.isEnum() || clazz.isMemberClass() || clazz.isAnnotation()) {
return false;
}
boolean isAcceptedByExcluded = this.acceptedByBaseTypes(clazz, testerFilter.getExcludedBaseTypes(), false);
if (isAcceptedByExcluded) {
return false;
}
boolean isAcceptedByIncluded = this.acceptedByBaseTypes(clazz, testerFilter.getIncludedBaseTypes(), true);
return isAcceptedByIncluded;
}
private boolean acceptedByBaseTypes(Class<?> clazz, Class<?>[] bases, boolean _default) {
if (bases == null || bases.length == 0) {
return _default;
}
for (Class base : bases) {
if (base.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
/**
* 测试类名称是否通过表达式过滤规则
*/
public boolean isAcceptedByPatterns(String className) {
boolean isNegationAccepted = this.acceptedByPatterns(className, testerFilter.getNegationFilters(), false);
if (isNegationAccepted) {
return false;
}
boolean isPositionAccepted = this.acceptedByPatterns(className, testerFilter.getPositiveFilters(), true);
return isPositionAccepted;
}
/**
* @param className
* @param patterns
* @param _default
* 规则为空时的返回值
* @return
*/
private boolean acceptedByPatterns(String className, List<String> patterns, boolean _default) {
if (patterns == null || patterns.isEmpty()) {
return _default;
}
for (String pattern : patterns) {
if (className.matches(pattern)) {
return true;
}
}
return false;
}
public boolean acceptInnerClass() {
return true;
}
public boolean searchInJars() {
return testerFilter.isSearchInJars();
}
}