TestNg框架简介:
TestNG,即Testing, Next Generation,下一代测试技术,是一套根据JUnit 和NUnit思想而构建的利用注释来强化测试功能的一个测试框架。TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use。
一.常用注解及解释
@BeforeSuite: 被此注解的方法将在所有测试运行之前运行该方法。
@AfterSuite: 被此注解的方法将在所有测试运行之后运行该方法。
@BeforeTest: 被此注解的方法,将在测试类运行之前运行,只被执行一次。
@AfterTest: 被此注解的方法,将在测试运行之后运行。
@BeforeClass: 被此注解的方法,将在当前类的第一个测试方法调用之前运行
@AfterClass: 被此注解的方法,将在当前类的所有测试方法调用之后运行
@BeforeMethod: 被此注解的方法,将在每个测试方法调用之前运行
@AfterMethod: 被此注解的方法,将在每个测试方法调用之后运行。
@Test: 将类或方法标记为测试的一部分,此标记若放在类上,则该类所有公共方法都将被作为测试方法
@DataProvider: 标记一种方法来提供测试方法的数据。 注释方法必须返回一个Object [] [],其中每个Object []可以被分配给测试方法的参数列表。 要从该DataProvider接收数据的@Test方法需要使用与此注释名称相等的dataProvider名称
@Parameters: 描述如何将参数传递给@Test方法
@Factory: 将一个方法标记为工厂,返回TestNG将被用作测试类的对象。 该方法必须返回Object []
@Listeners: 定义测试类上的侦听器
二.常用断言方法
2.1.Assert类(硬断言)
断言类是Assert.java,里面有多个静态方法被称为硬断言,硬断言就是,如果运行到折行断言失败,即使后面还有其他代码行,也不会继续执行下去。
(1) assertTrue:判断是否为True。
(2) assertFalse:判断是否为false。
(3) assertSame:判断引用地址是否相同。
(4) assertNotSame:判断引用地址是否不相同。
(5) assertNull:判断是否为null。
(6) assertNotNull:判断是否不为null。
(7) assertEquals:判断是否相等,Object类型的对象需要实现haseCode及equals方法。
(8) assertNotEquals:判断是否不相等。
(9) assertEqualsNoOrder:判断忽略顺序是否相等
2.2.SoftAssert(软断言)
SoftAssert的特点
1) 如果一个断言失败,会继续执行这个断言下的其他语句或者断言
2) 也就是一个用例有多个断言,失败了其中一个,不影响其他断言的运行
3) 不要忘记调用assertAll()在该用例的最后一个断言后面
4) 软断言的类,叫SoftAssert.java,这个类是需要创建实例对象,才能调用相关实例方法进行软断言
具体实例方法此处忽略,请参考硬断言方法。
三.TestNG预期异常测试
预期异常测试通过在@Test注解后加入预期的Exception来进行添加,范例如下所示:
@Test(expectedExceptions =
ArithmeticException.class)
public void
divisionWithException() {
int i = 1 / 0;
System.out.println("After division the value of i is :"+ i);
}
测试其他异常一样的,只需要在@Test注解后加入预期的Exception即可,假如出现了该异常,则会判断测试通过。
四.TestNG忽略测试
有时候我们写的用例没准备好,或者该次测试不想运行此用例,那么删掉显然不明智,那么就可以通过注解@Test(enabled = false)
来将其忽略掉,此用例就不会运行了,默认是true。
五.TestNG超时测试
“超时”表示如果单元测试花费的时间超过指定的毫秒数,那么TestNG将会中止它并将其标记为失败。此项常用于性能测试。如下为一个范例:
@Test(timeOut = 3000) // time in
mulliseconds
public void
testThisShouldPass() throws InterruptedException {
Thread.sleep(4000);
}
六、分组测试
分组测试即为使用group,如果你使用xml的话就是里边的<groups>标签,如果是直接在class中,是通过@Test(groups="group2")这种方式来分组,而且@BeforeGroup是需要添加group名称才可以正确挂载到该group下的;
这个group说明可以是在单个的测试方法上,也可以在class上,只要具有同样的group名称都会在同一个group中,同时group名称可以有多个,类似@Test(groups = {"mysql","database"})这种
xml文件配置如下:
<suite name="Suite"
parallel="false">
<test name="Test">
<groups>
<incloud
name="group1"></incloud>
<incloud
name="group2"></incloud>
</groups>
<classes>
<class
name="com.demo.test.testng.NewTest"/>
<class
name="com.demo.test.testng.TestCase1"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
七.分suite测试
测试套件是用于测试软件程序的行为或一组行为的测试用例的集合。 在TestNG中,我们无法在测试源代码中定义一个套件,但它可以由一个XML文件表示,因为套件是执行的功能。 它还允许灵活配置要运行的测试。 套件可以包含一个或多个测试,并由<suite>标记定义。<suite>是testng.xml的根标记。 它描述了一个测试套件,它又由几个<test>部分组成。
下表列出了<suite>接受的所有定义的合法属性。
属性
描述
name
套件的名称,这是一个强制属性
verbose
运行的级别或详细程度,级别为0-10,其中10最详细
parallel
TestNG是否运行不同的线程来运行这个套件,默认为none,其他级别为methods、tests、classes、instances
thread-count 如果启用并行模式(忽略其他方式),则为使用的线程数
annotations 在测试中使用的注释类型
time-out
在本测试中的所有测试方法上使用的默认超时
八.依赖测试
有时,我们可能需要以特定顺序调用测试用例中的方法,或者可能希望在方法之间共享一些数据和状态。 TestNG支持这种依赖关系,因为它支持在测试方法之间显式依赖的声明。
TestNG允许指定依赖关系:
在@Test注释中使用属性dependsOnMethods
在@Test注释中使用属性dependsOnGroups
除此之外依赖还分为hard依赖和soft依赖:
hard依赖:默认为此依赖方式,即其所有依赖的methods或者groups必须全部pass,否则被标识依赖的类或者方法将会被略过,在报告中标识为skip,如后面的范例所示,此为默认的依赖方式;
soft依赖:此方式下,其依赖的方法或者组有不是全部pass也不会影响被标识依赖的类或者方法的运行,注意如果使用此方式,则依赖者和被依赖者之间必须不存在成功失败的因果关系,否则会导致用例失败。此方法在注解中需要加入alwaysRun=true即可,如@Test(dependsOnMethods= {"TestNgLearn1"}, alwaysRun=true);
在TestNG中,我们使用dependOnMethods和dependsOnGroups来实现依赖测试。 且这两个都支持正则表达式,如下面所示:
@Test(groups = { "init" })
public void serverStartedOk() {}
@Test(groups = { "init" })
public void initEnvironment() {}
@Test(dependsOnGroups = { "init.*" })
public void method1() {}
九.参数化测试
TestNG中的另一个有趣的功能是参数化测试。 在大多数情况下,您会遇到业务逻辑需要大量测试的场景。 参数化测试允许开发人员使用不同的值一次又一次地运行相同的测试。
TestNG可以通过两种不同的方式将参数直接传递给测试方法:
使用testng.xml
使用数据提供者
下面分别介绍两种传参方式:
9.1、使用textng.xml传送参数
范例代码如下:
public class TestCase1 {
@Parameters({"param1", "param2"})
public void TestNgLearn1(String param1, int
param2) {
System.out.println("this
is TestNG test case1, and param1 is:"+param1+"; param2
is:"+param2);
Assert.assertFalse(false);
}
}
xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="Test">
<parameter name="param1"
value="1011111" />
<parameter name="param2"
value="10" />
<classes>
<class
name="com.demo.test.testng.TestCase1"/>
</classes>
</test>
</suite>
9.2、使用@DataProvider
传递参数
此处需要注意,传参的类型必须要一致,且带有@DataProvider
注解的函数返回的必然是Object[][]
,此处需要注意。
示例代码如下:
public class TestCase1 {
@DataProvider(name =
"provideNumbers")
public Object[][] provideData() {
return new Object[][] {
{ 10, 20 }, { 100, 110 }, { 200, 210 } };
}
@Test(dataProvider =
"provideNumbers")
public void TestNgLearn1(int param1, int
param2) {
System.out.println("this is TestNG test case1, and param1
is:"+param1+"; param2 is:"+param2);
Assert.assertFalse(false);
}
十、XML配置文件说明
如下分别讲解各个标签:
10.1、suite标签
testNG.xml文件的最外层标签即suite,即测试套件,其下可以有多个<test>和<groups>,其有几个可以添加的属性在第十节的分suite测试中有做说明,这里做下详细说明:
(1)、name属性
此属性属于必须要有的,值可以自行设定,此名字会在testNG的报告中看到;
(2)、verbose属性
此属性为指定testNG报告的详细程度,从0开始到10,其中10为最详细,默认生成的xml此属性值为1;
(3)、parallel属性
此属性是指代运行方式,默认为none,即串行运行方式;并行执行方法包括如下几种,下面做分别说明:
a.methods:方法层级,若为此值,则该suite下所有的测试方法都将进行多线程,即测试用例级别的多线程。如果用例之间有依赖,则执行顺序会按照设定的依赖来运行;
<suite name="My suite" parallel="methods"
thread-count="5">
b.tests:TestNG将在同一线程中运行相同的<Test>标签中的所有方法,每个<test>标签都将处于一个单独的线程中,这允许您将不是线程安全的所有类分组在同一个<test>中,并保证它们都将在同一个线程中运行,同时利用TestNG使用尽可能多的线程运行测试。
<suite name="My suite" parallel="tests"
thread-count="5">
c.classes:类级别并发,即TestNG会将该suite下每个class都将在单独的线程中运行,同一个class下的所有用例都将在同一个线程中运行;
<suite name="My suite" parallel="classes"
thread-count="5">
d.instances:实例级别,即TestNG将在同一线程中运行同一实例中的所有方法,两个不同实例上的两个方法将在不同的线程中运行。
<suite name="My suite" parallel="instances"
thread-count="5">
(4)、thread-count属性
此属性用于指定线程数,按照需要输入,需要parallel参数非none时才可以添加;
(5)、annotations属性
此项为注解的级别,为methods级别和class级别,一般不用设置;
(6)、time-out属性
此属性用于指定超时时间,该suite下所有的用例的超时时间;
(7)、group-by-instances属性
此项用于那些有依赖的方法,且被依赖的对象有多个重载对象,因为如果是依赖方法,且该方法有多个重载方法,则默认是会将所有重载方法都跑完再运行被依赖方法,但有时候我们不想这样,则将此项设置为true即可;
(8)、preserve-order属性
值可输入true或者false,如果为true,则用例执行会按照在xml中的顺序执行,否则会乱序执行,不添加此属性的话默认是按顺序执行的;
10.2、test标签
此标签无特别意义,其下可以包括多个标签,如groups、classes等,如下介绍下几种书写方式:
选择一个包中的全部测试脚本(包含子包)
<test name = "allTestsInAPackage" >
<packages>
<package name =
"whole.path.to.package.* />
</packages>
</test>
选择一个类中的全部测试脚本
<test name = "allTestsInAClass" >
<classes>
<class name="whole.path.to.package.className />
</classes>
</test>
选择一个类中的部分测试脚本
<test name = "aFewTestsFromAClass" >
<classes>
<class name="whole.path.to.package.className >
<methods>
<include name
= "firstMethod" />
<include name
= "secondMethod" />
<include name
= "thirdMethod" />
</methods>
</class>
</classes>
</test>
选择一个包中的某些组
<test name = "includedGroupsInAPackage" >
<groups>
<run>
<include name
= "includedGroup" />
</run>
</groups>
<packages>
<package name =
"whole.path.to.package.* />
</packages>
</test>
排除一个包中的某些组
<test name = "excludedGroupsInAPackage" >
<groups>
<run>
<exclude name
= "excludedGroup" />
</run>
</groups>
<packages>
<package name =
"whole.path.to.package.* />
</packages>
</test>
其可以附带的属性有如下几种,下面对各个属性做单独说明:
(1)、name属性
此属性属于必须要有的,值可以自行设定,此名字会在testNG的报告中看到;
(2)、verbose属性
此属性为指定testNG报告的详细程度,从0开始到10,其中10为最详细,默认生成的xml此属性值为1
(3)、threadPoolSize属性
该属性指定此test的线程池大小,为数字;
@Test(threadPoolSize = 3, invocationCount = 10, timeOut =
10000)
public void testServer() {
}
(4)、invocationCount属性
该属性指定此test的运行次数,为数字,范例如上面的代码所示;
(5)、time-out属性
此属性用于指定超时时间,该suite下所有的用例的超时时间,范例如上面的代码所示;
(6)、group-by-instances属性
此项用于那些有依赖的方法,且被依赖的对象有多个重载对象,因为如果是依赖方法,且该方法有多个重载方法,则默认是会将所有重载方法都跑完再运行被依赖方法,但有时候我们不想这样,则将此项设置为true即可;
<suite name="Factory"
group-by-instances="true">
(7)、preserve-order属性
值可输入true或者false,如果为true,则用例执行会按照在xml中的顺序执行,否则会乱序执行,不添加此属性的话默认是按顺序执行的;
10.3、group标签
此标签必然是在<test>标签下的,用于标识那些组会被用于测试或者被排除在测试之外,其同级必然要包含一个<classes>标签或者<pakages>标签,用于指定groups来自于哪些包或者类;
如下即为包含一个group,排除一个group的例子:
<groups>
<run>
<include name =
"includedGroupName" />
<exclude name =
"excludedGroupName" />
</run>
</groups>
高级应用:
<test name="Regression1">
<groups>
<define name="functest">
<include
name="windows"/>
<include
name="linux"/>
</define>
<define name="all">
<include
name="functest"/>
<include
name="checkintest"/>
</define>
<run>
<include
name="all"/>
</run>
</groups>
<classes>
<class
name="test.sample.Test1"/>
</classes>
</test>
10.4、其他
其他的话就是测试脚本的选择了,有三种方式:
选择一个包
<packages>
<package name = "packageName"
/>
</packages>
选择一个类
<classes>
<class name = "className" />
</classes>
选择一个方法
<classes>
<class name = "className" />
<methods>
<include
name = "methodName" />
</methods>
</class>
</classes>
这里也支持正则表达式,例如:
<test name="Test1">
<classes>
<class name="example1.Test1">
<methods>
<include
name=".*enabledTestMethod.*"/>
<exclude
name=".*brokenTestMethod.*"/>
</methods>
</class>
</classes>
</test>