(二)TestNG 基础概念和执行时机注解
入门的篇幅会写的比较长,毕竟基础要理解好。在学习TestNG注解前,我们先了解基本的名词,留个印象。
TestNG名词解释:
1.TestNG方法(method):是一个在代码内使用@Test注解标注的方法。下面代码中的isDuckMeal()就是一个测试方法。
@Test
public void isDuckMeal() {
//do sth
}
2.TestNG 组(group):TestNG方法可以加上groups="groupid"的属性来为方法划分组,后续可以在xml文件中来决定运行哪些组。下面的isClean方法就属于groupxxx组。
@Test(groups="groupxxx")
public void isClean(){
//do sth
}
下面的配置在xml中排除了groupxxx组。运行的时候,将不会运行所有属于groupxxx组的方法。
<groups>
<run>
<!--排除全部属于groupxxx组的Test Method-->
<exclude name="groupxxx"/>
</run>
</groups>
3.TestNG类(class):是包含至少一个TesdNG注解的Java类。可以包含多个测试方法。在xml文件中由<class>标签定义了这个Test所涉及的class。
4.TestNG用例(test):是多个TestNG类的组合。在xml文件中由<test>标签定义。
5.TestNG套件(suite):定义了一组业务级粒度的测试动作,它由一个或多个TestNG用例(Test)组成,在xml文件中由<suite>标签定义。
除了@Test注解外,TestNG还提供了丰富的注解满足各种测试场景需求。我们这里先讲最常见的关于执行时机的注解。一下子塞太多也消化不了。
TestNG执行时机注解:在同一个TestNG默认会按照方法的首字母升序执行TestNG Method。
@BeforeSuite:被注解的方法在所属套件(suite)内会最先运行。
@AfterSuite:被注解的方法在所属套件(suite)内会在最后运行。
@BeforeTest:被注解的方法会在所属的类所属的Test用例下最先运行。
@AfterTest:被注解的方法会在这个方法所属的类所属的Test用例下最后运行。
@BeforeClass:被注解的方法会在这个方法所属的类运行时最先运行。
@AfterClass:被注解的方法会在这个方法所属的类运行时最后运行。
@BeforeGroups:被注解的方法会在这个方法所属的组(group,组只属于某个Test,Test之间的组互不干扰)被调用时最先运行。
@AfterGroups:被注解的方法会在这个方法所属的组(group,组只属于某个Test,Test之间的组互不干扰)被调用时最后运行。
@BeforeMethod:被注解的方法会在该方法所属类内每个测试方法运行前运行。
@AfterMethod:被注解的方法会在该方法所属类内每个测试方法运行后运行。
考试考阅读理解的原因来了,上面这些描述,这么绕是不是很容易就被绕晕了,先回顾下前面的名词解释,然后我们结合实际的例子来理解这些注解。我们先来一个简单的例子。先新建一个TestNG类和TestNG配置xml文件。
package com.testng;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class SimpleExample {
@Test
public void simpleTest1(){
System.out.println("simpleTest1");
}
@Test
public void simpleTest2(){
System.out.println("simpleTest2");
}
@BeforeSuite
public void beforeSuiteExample(){
System.out.println("beforeSuite");
}
@BeforeTest
public void beforeTestExample(){
System.out.println("beforeTest");
}
}
这个TestNG配置xml内加了注释,注明了部分注解的运行时机,可以看下留个印象
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<!-- Before suite -->
<suite name="testSuite">
<!-- Before test1 -->
<test name="test1">
<classes>
<!-- Before class1 -->
<class name ="com.testng.SimpleExample" />
<!-- After class1 -->
</classes>
</test>
<!-- After test1 -->
</suite>
<!-- After suite -->
然后在TestNG配置xml文件上,右键,run as -> TestNG Suite(单个类运行也可以不用xml配置,就像上一篇博文的helloworld例子那样,但是单个类测试的场景不是我们主要的学习目标)。运行后,最先会切到Result of Running suite标签可以看到本次运行的套件的结构。TestNG的执行顺序,就是顺着这个结构,穿插着各种before after自上而下的执行下来。
前面说了,@BeforeSuite注解会在这个套件内最先运行,@BeforeTest会在这个Test执行前,最先执行,然后是按方法名首字母字母升序执行类内的TestNG方法。我们看下控制台输出,确实如此。
接下来让我们搞包含全部注解的完整例子。新建两个TestNG类和TestNG xml配置。来观察多种注解多个类,跨类group组的执行顺序。
package com.testng;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class TestNGClass1 {
@BeforeSuite
public void beforeSuite1(){
System.out.println("beforeSuite1 会在所属Suite被调用前运行 我们同属于一个Suite会按xml的顺序执行");
}
@AfterSuite
public void afterSuite1(){
System.out.println("afterSuite1 会在所属Suite运行后运行 我们同属于一个Suite会按xml的顺序执行");
}
@BeforeTest
public void BeforeTest1(){
System.out.println("beforeTest1 会在当前所属的Test运行前运行 我们同属于一个Test会按xml的顺序执行");
}
@AfterTest
public void afterTest1(){
System.out.println("afterTest1 会在当前所属的Test运行后运行 我们同属于一个Test会按xml的顺序执行");
}
@BeforeClass
public void beforeClass1(){
System.out.println("beforeClass1 会在当前所属的class1运行前运行");
}
@AfterClass
public void afterClass1(){
System.out.println("afterClass1 会在当前所属的class1运行后运行");
}
/*这表示这注解的方法会在id为groupsxxx的组的所有方法运行前最先运行*/
@BeforeGroups(groups="groupxxx")
public void beforeGroupsXXX(){
System.out.println("beforeGroupsXXX 会在这个Test内所属的Group被调用前运行");
}
/*这表示这个注解的方法会在id为groupxxx的组的所有方法运行完毕后运行*/
@AfterGroups(groups="groupxxx")
public void afterGroupsXXX(){
System.out.println("afterGroupsXXX 会在这个Test内所属的Group运行后运行");
}
@BeforeMethod
public void beforeMethod1(){
System.out.println("beforeMethod1 会在当前类每个test method被调用前运行");
}
@AfterMethod
public void afterMethod1(){
System.out.println("afterMethod1 会在当前类每个test method运行后运行");
}
@Test(groups="groupxxx")
public void test1001GroupXXX(){
System.out.println("test1001-XXX Test Method");
}
@Test(groups="groupyyy")
public void test1002GroupYYY(){
System.out.println("test1002-YYY Test Method");
}
}
package com.testng;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class TestNGClass2 {
@BeforeSuite
public void beforeSuite2(){
System.out.println("beforeSuite2 会在所属Suite被调用前运行 我们同属于一个Suite会按xml的顺序执行");
}
@AfterSuite
public void afterSuite2(){
System.out.println("afterSuite2 会在所属Suite运行后运行 我们同属于一个Suite会按xml的顺序执行");
}
@BeforeTest
public void BeforeTest2(){
System.out.println("beforeTest2 会在当前所属的Test运行前运行 我们同属于一个Test会按xml的顺序执行");
}
@AfterTest
public void afterTest2(){
System.out.println("afterTest2 会在当前所属的Test运行后运行 我们同属于一个Test会按xml的顺序执行");
}
@BeforeClass
public void beforeClass2(){
System.out.println("beforeClass2 会在当前所属的class2运行前运行");
}
@AfterClass
public void afterClass2(){
System.out.println("afterClass2 会在当前所属的class2运行后运行");
}
@BeforeGroups(groups="groupyyy")
public void beforeGroupsYYY(){
System.out.println("beforeGroupsYYY 会在所属的Group被调用前运行");
}
@AfterGroups(groups="groupyyy")
public void afterGroupsYYY(){
System.out.println("afterGroupsYYY 会在所属的Group运行后运行");
}
@BeforeMethod
public void beforeMethod2(){
System.out.println("beforeMethod2 会在每个test method被调用前运行");
}
@AfterMethod
public void afterMethod2(){
System.out.println("afterMethod2 会在每个test method运行后运行");
}
@Test(groups="groupxxx")
public void test2001GroupXXX(){
System.out.println("test2001-XXX Test Method");
}
@Test(groups="groupyyy")
public void test2002GroupYYY(){
System.out.println("test2002-YYY Test Method");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<!-- Before suite -->
<suite name="testSuite">
<!-- Before test1 -->
<test name="test1">
<classes>
<!-- Before class1 -->
<class name ="com.testng.TestNGClass1" />
<!-- After class1 -->
<!-- Before class2 -->
<class name ="com.testng.TestNGClass2" />
<!-- After class2 -->
</classes>
</test>
<!-- After test1 -->
</suite>
<!-- After suite -->
TestNG会按照xml配置中的顺序,从上往下的执行test用例。这个例子,执行的顺序说明都已在控制台打印。TestNG会按照xml配置中的顺序,从上往下的执行test用例。动手敲一敲,很快就能搞明白这里的调用顺序优先级。我们看下控制台的输出,重点把group的结果标了出来。
下面回顾下,配置xml文件的标签层次,编写TestNG xml文件时就按这个层次来。
|--suite
|--test
|--groups
| |--run
| |--exclide name="groupid"//排除组,支持正则表达式
|--classes
|--class name="classname"
到了这一步,你至少已经能看懂TestNG的注解,知道怎么编写简单的TestNG套件,TestNG也就算入门辣!后面我们再讲TestNG的其他注解的用法。
附上TestNG官网,你想查的都在这里:https://testng.org/doc/documentation-main.html#annotations