package org.test4j.testng.utility; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; @SuppressWarnings({ "unchecked", "rawtypes" }) public final class TestNgUtil { /** * 运行testng的单个测试方法 * * @param clazz * 测试类 * @param method * 方法名称 * @param isThrowException * 是否抛出测试异常消息 * @return */ public static boolean run(String clazz, String method, boolean isThrowException) { TestNG tng = getTestRunner(clazz, method, isThrowException); TestListenerAdapter listener = new TestListenerAdapter(); tng.addListener(listener); tng.run(); int success = listener.getPassedTests().size(); int failure = listener.getFailedTests().size(); if (isThrowException) { for (ITestResult rt : listener.getFailedTests()) { throw new RuntimeException(rt.getThrowable()); } } return success == 1 && failure == 0; } /** * 构造单个方法的testng runner * * @param clazz * @param method * @param isThrowException * @return */ public static TestNG getTestRunner(String clazz, String method, boolean isThrowException) { TestNG tng = new TestNG(); XmlSuite suite = new XmlSuite(); XmlTest test = new XmlTest(suite); test.setName("run testng"); XmlClass xmlClazz = new XmlClass(clazz); try { /** * 为了兼容testng 5.11(以下版)和5.12(以上版),采用了try catch */ List includes = xmlClazz.getIncludedMethods(); try { // 下列代码其实就是includes.add(new XmlInclude(method)); <br> // 采用反射构造是为了在testNg5.11下也可以编译通过 Class xmlInclude = Class.forName("org.testng.xml.XmlInclude"); Constructor constructor = xmlInclude.getConstructor(String.class); includes.add(constructor.newInstance(method)); } catch (Throwable e) { includes.add(method); } xmlClazz.getExcludedMethods().add(method + ".+"); } catch (Throwable e) { } test.getXmlClasses().add(xmlClazz); List<XmlSuite> suites = new ArrayList<XmlSuite>(); suites.add(suite); tng.setXmlSuites(suites); return tng; } /** * 判断一个方法是否为单元测试方法<br> * <br> * <br> * o method前面直接标注了@Test <br> * o 否则,如果class未标注@Test或者方法为非public类型或静态方法,则不是test method<br> * o 否则,如果class即标注了@Test + public非静态方法 + 且没有其它标注,则是test method<br> * o 如果有标注,则判断标注的用途 * * @param testClass * @param method * @return */ public static boolean isTestMethod(Class testClass, Method method) { boolean methodHasTestAnnotation = method.isAnnotationPresent(Test.class); if (methodHasTestAnnotation) { return true; } boolean clazHasTestAnnotation = testClass.isAnnotationPresent(Test.class); Class superClaz = testClass.getSuperclass(); while (superClaz != Object.class && clazHasTestAnnotation == false) { clazHasTestAnnotation = superClaz.isAnnotationPresent(Test.class); superClaz = superClaz.getSuperclass(); } int modifier = method.getModifiers(); if (clazHasTestAnnotation == false || Modifier.isPublic(modifier) == false) { return false; } Annotation[] annotations = method.getDeclaredAnnotations(); if (annotations == null || annotations.length == 0) { return true; } for (Annotation annotation : annotations) { Class claz = annotation.annotationType(); if (NOT_TEST_ANNOTATIONS.contains(claz)) { return false; } } return true; } private final static Set<Class> NOT_TEST_ANNOTATIONS = new HashSet<Class>() { private static final long serialVersionUID = 7752423831360820098L; { this.add(BeforeSuite.class); this.add(BeforeTest.class); this.add(BeforeGroups.class); this.add(BeforeClass.class); this.add(BeforeMethod.class); this.add(AfterSuite.class); this.add(AfterTest.class); this.add(AfterGroups.class); this.add(AfterClass.class); this.add(AfterMethod.class); this.add(DataProvider.class); this.add(Factory.class); } }; }