当通过testng.xml或命令行把测试类传递给TestNG时,TestNG会调用这些测试类的无参构造方法,将这些类实例化,然后执行在每个类中的测试方法。
如果假设某个测试类中构造方法是有参的,那么运行时,TestNG会报出TestNGException
异常,因为无法初始化这个类(该类没有无参构造方法),报错见下。
org.testng.TestNGException:
Can't invoke public void testNGtest.TestFactory.testInitialChar() throws java.io.IOException: either make it static or add a no-args constructor to your class
这个时候就需要使用TestNG的@Factory注解了。
被@Factory注解的方法必须是返回一个对象数组的方法。而且这些返回的对象数组中的对象必须包含TestNG annotation的类的实例。
我们可以把@Factory方法和@Test方法放在同一个类中,因为一方面@Factory方法只会被调用一次,另一方面@Factory方法优先于@Test方法和配置方法被调用,只有当所有的@Factory方法被调用之后,TestNG才执行@Test方法和配置方法。
现在用一个简单的例子来验证@Factory方法的一些特性与熟悉@Factory方法的基础使用方法。
比如我们要循环登陆两个网站,循环进行登陆和登出:
代码如下:
package com.demo.test.testng;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class FactoryTest {
private String host;
private int port;
public FactoryTest(String host, int port)
{
this.host=host;
this.port=port;
}
@Test
public void login()
{
System.out.println("login, host:"+host+";port"+port);
}
@Test(dependsOnMethods="login")
public void logout()
{
System.out.println("logout, host:"+host+";port"+port);
}
@Factory
public static Object[] create()
{
List<FactoryTest> list = new ArrayList<FactoryTest>();
list.add(new FactoryTest("10.10.10.1", 8080));
list.add(new FactoryTest("10.10.10.2", 8080));
return list.toArray();
}
}
运行结果:
login, host:10.10.10.2;port8080
login, host:10.10.10.1;port8080
logout, host:10.10.10.2;port8080
logout, host:10.10.10.1;port8080
===============================================
Suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================
等等,好像有什么不对,怎么先进行了两个login呢?这时候就需要做个xml加个设定了,如下:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="none">
<test name="Test" group-by-instances="true">
<classes>
<class name="com.demo.test.testng.FactoryTest">
</class>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
再运行这个xml,结果如下:
login, host:10.10.10.2;port8080
logout, host:10.10.10.2;port8080
login, host:10.10.10.1;port8080
logout, host:10.10.10.1;port8080
===============================================
Suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================
嗯,正常了,添加部分为group-by-instances="true"
,可以添加在<suite>
标签也可以在<test>
标签。
备注
实际上,这个带有@Factory
注解的方法也可以写到其他类中,只是如果写到其他类中,就需要在xml中将这个类加入进去,运行xml的时候会先运行这个带@Factory
注解的方法。