自动生成testng.xml

工作中接到一个任务,调研是否可以实现rpc服务自动diff功能。本篇是其中的一个子功能,测试类的testng.xml自动实现。

实现原理:
1.实例化XmlSuite类
2.扫描目录下所有的classes文件,然后遍历class的所有方法是否包含@Test注解
3.步骤2中的必要信息放到XmlSuite中
4.保存XmlSuite到指定位置

主要方法:

/**
 * 生成testng.xml
 * @return
 */
public Boolean createTestNGXML() {
	String prefix = "Test";
    String classesDir = "D:/opt/cases";
    XmlSuite suite = new XmlSuite();
    XmlTest xmlTest = new XmlTest(suite);
    List<XmlClass> xmlClasses = new ArrayList<>();

    // testng.xml全名
    suite.setFileName(prefix + "_testng.xml");
    // 不设置这个suite.toXml()会报NPT
    suite.setJunit(false);
    suite.setName(prefix);
    xmlTest.setName(prefix);

    try {
        // 新建classloader实例
        URLClassLoader loader = URLClassLoader.newInstance(new URL[] {}, getClass().getClassLoader());
        // 测试用例class所在目录加到classloader的classpath中
        TestNGUtil.addPath(loader, new File(classesDir).toURI().toURL());

        // 循环遍历所有的class文件
        Collection<File> classFiles = FileUtils.listFiles(new File(classesDir), new WildcardFileFilter("*.class"),
                TrueFileFilter.INSTANCE);
        for (File f : classFiles) {
            // 包含$说明为内部类
            if (f.getName().contains("$")) {
                continue;
            }
            XmlClass xmlClass = new XmlClass();
            List<XmlInclude> includes = new ArrayList<>();

            // 只要class名称不要后缀
            String clazzName = f.getName().replace(".class", "");
            xmlClass.setName(clazzName);

            Class<?> clazz = Class.forName(clazzName, false, loader);
            // 遍历所有方法,找到包含@Test标注的方法
            for (Method m : clazz.getMethods()) {
                if (hasTestAnnotation(m)) {
                    XmlInclude xmlInclude = new XmlInclude(m.getName());
                    includes.add(xmlInclude);
                }
            }
            xmlClass.setIncludedMethods(includes);
            xmlClasses.add(xmlClass);
        }

        xmlTest.setXmlClasses(xmlClasses);

        // 保存到文件系统中
        FileUtils.write(new File(classesDir + "/" + suite.getFileName()), suite.toXml(), Charset.defaultCharset());
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

/**
 * 判断当前方法是否包含@Test标注
 * 
 * @param m
 * @return
 */
private Boolean hasTestAnnotation(Method m) {
    List<Annotation> annotations = Arrays.asList(m.getAnnotations());
    for (Annotation annotation : annotations) {
        if (annotation.annotationType().getName().equals(Test.class.getName())) {
            return Boolean.TRUE;
        }
    }
    return Boolean.FALSE;
}

额外的类TestNgUtil.java

/**
     * addURL为protected方法,需要借助于reflect包才能实现动态添加class到classpath中
     * 
     * @param urlClassLoader
     * @param url
     * @throws Exception
     */
    public static void addPath(ClassLoader urlClassLoader, URL url) throws Exception {
        Class<URLClassLoader> urlClass = URLClassLoader.class;
        Method method = urlClass.getDeclaredMethod("addURL", new Class[] { URL.class });
        method.setAccessible(true);
        method.invoke(urlClassLoader, new Object[] { url });
    }

import信息

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.testng.annotations.Test;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import com.aaa.qa.utils.TestNGUtil;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值