testng.xml
使用maven工程时,我们可以在工程中添加testng.xml来运行。运行xml,可以使用IDE工具(eclipse、Intellij's IDEA),命令行,ant。使用eclipse需要安装插件,使用IDEA时,直接右键运行
image.png
使用命令行(需要把TestNG加入到class path中)具体命令查看help
java org.testng.TestNG testng1.xml [testng2.xml testng3.xml ...]
testng.xml是依赖testng-1.0.dtd,所以在xml的开头需要把dtd文件加进去,把依赖加进去以后在写xml文件时,IDE才会调起方法
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
image.png
例子
使用class名配置运行
--只有一个test
image.png
--有多个test
image.png
使用package名配置运行
image.png
使用group名配置运行,xml文件中不仅要加上group注解,也需要加上classes,group是在classes的范围内挑选所需要的group
修改下代码
public class Demo1 { @Test(groups = "g1") public void test1(){ System.out.println("测试01"); } @Test(groups = "g2") public void test11(){ System.out.println("测试11"); } } public class Demo3 { @Test(groups = "g1") public void test3(){ System.out.println("测试03"); } @Test(groups = "g2") public void test33(){ System.out.println("测试33"); } } |
下面是大头了
group
TestNG允许使用group进行分组,一个test不仅属于一个group,可以属于多个group:@Test(groups={"g1","g2"}),在testng.xml中可以配置不同group运行,group可以放在<suite>下,也可以放在<test>下,作用范围的差别:如果<suite>指明g1,<test>指明g2,则g1、g2都会运行的,可以使用include(包含)也可以使用exclude(排除)
下面的例子是运行group名为g1和g2
public class Demo1 { @Test(groups = {"g1","g2"}) public void test1(){ System.out.println("测试01"); } @Test(groups = "g2") public void test11(){ System.out.println("测试11"); } @Test public void test111(){ System.out.println("测试111"); } } |
public class Demo3 { @Test(groups = "g1") public void test3(){ System.out.println("测试03"); } @Test(groups = "g2") public void test33(){ System.out.println("测试33"); } } |
group名可以使用.,同时在指定要运行哪些group时,也可以使用通配符 星号 (使用通配符 星号,一定要加上. dot star)
public class Demo1 { @Test(groups = {"windows.g1","linux.g2"}) public void test1(){ System.out.println("测试01"); } @Test(groups = "linux.g2") public void test11(){ System.out.println("测试11"); } @Test public void test111(){ System.out.println("测试111"); } } |
public class Demo3 { @Test(groups = "windows.g1") public void test3(){ System.out.println("测试03"); } @Test(groups = "linux.g2") public void test33(){ System.out.println("测试33"); } } |
当有些test case不运行了以后,我们可以在group中多加一个标签,然后在testng.xml的group中排除该标签,这些case就不会跑起来了。如果有的case没有加上group注解,是不会被运行起来的
public class Demo1 { @Test(groups = {"checkintest","broken"}) public void test1(){ System.out.println("测试01"); } @Test(groups = "checkintest") public void test11(){ System.out.println("测试11"); } @Test public void test111(){ System.out.println("测试111"); } } |
dependencies
有时候有些case是需要依赖其他case的,这个时候就可以用dependencies注解
默认情况下,被依赖的类需要运行成功,依赖的类才会运行,而且被依赖的类一定会在依赖类之前运行
如下图,test22运行在test2之前
dependsOnMethods
image.png
如果怕失败了,依赖类不运行,可以多加个alwaysRun=true,无论如何都要运行的,被依赖类如果失败了,依赖类是不运行(skipped)而不是失败
image.png
image.png
dependsOnGroups
image.png
在testng.xml中也可以使用dependsOnGroup。目前实践结果是,只能放在<test>下,放在<suite>会报错:org.testng.TestNGException: java.lang.NullPointerException。而且
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="suite01" verbose="1"> <test name="test"> <groups> <dependencies> <group name="ss" depends-on="yy"></group> </dependencies> </groups> <classes> <class name="com.tyoko.demo.TestNGDemo1"></class> </classes> </test> </suite> |
运行结果是被依赖的方法先运行,然后按照书写顺序运行,最后是依赖的类
image.png
并发
parallel="methods",运行所有方法在各自的线程,依赖方法也是运行在不同的线程,但是如果你有指定的话会按照你指定的执行
parallel=”tests",将相同<test>中的case运行在同一个线程,不同的<test>分开不同线程运行。如果在同个<test>中有非线程安全的类的话,可以使用group以保证在同个线程内运行所有case
parallel=“classes",同个类中的方法运行在同个线程中,不同类的方法运行在不同线程中
parallel="instances",同个实例的方法运行在同个线程,不同实例则运行在不同线程中
image.png
参数化
parameters
在方法上使用Parameters({""})注解,在testng.xml中添加<parameter name="" value=""/>
name必须一致,方法则会去读取xml文件中设置的值。一般用于配置数据库信息时使用。在<suite><test>中都可以设置,有作用域差别
@Parameters({ "first-name" }) @Test public void testSingleString(String firstName) { System.out.println("Invoked testString " + firstName); assert "Cedric".equals(firstName); } |
<suite name="My suite"> <parameter name="first-name" value="Cedric"/> <test name="Simple example"> <-- ... --> |
dataProviders
返回值是Object[][],二维数组,设置了name后,方法上的注解dataProvider="name"使用name,如果未设置name,可以使用方法名。
@DataProvider(name = "test1") public Object[][] createData1() { return new Object[][] { { "Cedric", new Integer(36) }, { "Anne", new Integer(37)}, }; } //This test method declares that its data should be supplied by the Data Provider //named "test1" @Test(dataProvider = "test1") public void verifyData1(String n1, Integer n2) { System.out.println(n1 + " " + n2); } |
实际使用时,可以把数据写在同一个类中(静态方法),再去获取数据
public class BaseFactory { @DataProvider(name = "getData") public static Object[][] createData(){ return new Object[][]{ {"wanger",18}, {"lisi",16} }; } } |
一堆的before、after,可以添加以下注解:alwaysRun(不可以使用在beforeGroup) dependsOnGroups dependsOnMethods enables groups inheritGroups(=true,该方法属于指定的group,注解在class级别)
@BeforeSuite
@AfterSuite
@BeforeTest
@AfterTest
@BeforeGroups
@AfterGroups
@BeforeClass
@AfterClass
@BeforeMethod
@AfterMethod
实践结果是@BeforeMethod@AfterMethod@BeforeClass@AfterClass可以写在同一个类中。@BeforeTest@AfterTest另起一个类,不然在多个类中都写了@BeforeTest@AfterTest会同时运行多个,造成结果失败
@BeforeGroups@AfterGroups一定要加上是在哪写group中使用的 public class GroupFactory { @BeforeGroups(groups = {"yy"}) public void beforeGroup(){ System.out.println("Before group"); } @AfterGroups(groups = {"yy"}) public void afterGroup(){ System.out.println("After group"); } } |
image.png
@BeforeSuite@AfterSuite就直接新起一个类来写要操作的方法
public class SuiteFactory { @BeforeSuite public void beforeSuite(){ System.out.println("Before Suite"); } @AfterSuite public void afterSuite(){ System.out.println("After Suite"); } } |