1、TestNG简介
TestNG是一个强大的测试框架,深受JUnit和NUnit启发的测试框架,并且引入了一些新功能,使其功能更强大,更易于使用。它突破了以前一些框架的限制,为开发人员和测试人员提供了方便强大的编写和测试。它支持所有的测试活动包括单元测试、集成测试和UI系统测试,NG指Next Generation,被视为是Junit的升级版。
如此强大的TestNG常用来搭建接口自动化框架和UI自动化框架,为了更好的使用和理解TestNG,接下来就通过上一篇中提到的反射造一个轮子。
2、实现TestNG Hello World案例
用过的TestNG的同学,对于Hello World 案例一定不陌生,没用的也不用担心,所谓TestNG Hello World案例非常简单,TestNG核心是通过testng.xml配置测试类信息,然后执行测试类中带有@Test的方法。
举个例子:
testng.xml 内容如下:
<?xml version="1.0" encoding="UTF-8"?> <suite name="suite1"> <test name="test1"> <classes> <class name="com.lemon.testng.TestNGDemo"> </class> </classes> </test> </suite>
TestNGDemo 内容如下:
public class TestNGDemo { @Test public void test1() { System.out.println("TestNGDemo.test1"); } @Test public void test2() { System.out.println("TestNGDemo.test2"); } @Test public void test3() { System.out.println("TestNGDemo.test3"); } }
当我们运行testng.xml时,就会去执行test1、test2、test3方法,这就是TestNG Hello World案例。
实现这个功能需要用到xml解析和反射两个技术,不算太难。
接下来就动起手来吧。
1、解析xml,使用dom4j技术。
List<String> classNames = new ArrayList<String>(); //1、创建SAXReader对象。 SAXReader reader = new SAXReader(); //2、指定xml的位置 File file = new File("testng2.xml"); //2.1、读取xml获得document对象。 Document doc = reader.read(file); //3、获取根元素 Element rootElement = doc.getRootElement(); //4、获取根元素下面的子元素及其属性。 List<Element> elements = rootElement.elements(); //4.1、遍历所有test子元素 for (Element element : elements) { //4.2、遍历所有classes子元素 List<Element> classesElements = element.elements(); for (Element classesElement : classesElements) { //4.3、遍历所有class子元素 List<Element> classElements = classesElement.elements(); for (Element classElement : classElements) { //4.4、获取name属性 String className = classElement.attribute("name").getData().toString(); //4.5、把所有的name存储到集合中 classNames.add(className); } } }
2、反射
for (String className : classNames) { Map<String,Method> methods = new TreeMap<>(); //1、获取测试类(TestNGDemo)字节码对象 Class<?> clazz = Class.forName(className); //2、创建测试类对象 Object o = clazz.newInstance(); //3、获取测试类所有方法 Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { //3.1、判断方法是否包含@Test注解 if(declaredMethod.isAnnotationPresent(Test.class)) { //3.2、包含@Test注解的方法加入集合中。 methods.put(declaredMethod.getName(),declaredMethod); } } //4、执行测试方法 methods.forEach((k,v)->{ //4.1、打印测试方法相关信息 System.out.println(v.getDeclaringClass().getName() + ":" + v.getName()); try { //4.2、反射调用@Test测试方法 v.invoke(o); } catch (Exception e) { e.printStackTrace(); } }); }
3、输出结果
com.lemon.testng.TestNGDemo:test1 TestNGDemo.test1 com.lemon.testng.TestNGDemo:test2 TestNGDemo.test2 com.lemon.testng.TestNGDemo:test3 TestNGDemo.test3
4、总结
上面的例子虽然简单,没有实现诸如方法依赖、优先级、前置条件等功能,却窥一斑而知全豹。TestNG大部分功能都是基于反射实现,这样设计的框架才具备通用性,像常用的一些工具类、中间件中也大量使用反射就是这个原因。
好了,轮子造完了,是不是对反射更有感觉了呢?欢迎留言讨论。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




