您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧。小伙伴们,有啥想看的,想问的,欢迎积极留言,前面几篇文章我们详细介绍了测试框架Junit的使用。但是Junit也就诸多局限性。例如:不能分组测试,不支持多线程测试,不支持参数化测试等等。针对局限,这篇文章将介绍另外一种单元测试框架TestNG。
简介
TestNG是一个受Junit和Nunit启发的测试框架,旨在简化广泛的测试需求,从单元测试(单独测试一个类)到集成测试(测试由几个类,几个包甚至几个外部框架组成的整个系统,如应用服务器),所以,相比较于Junit,TestNG更加强大。
特性
TestNG是一个设计用来简化广泛的测试需求的测试框架,涵盖单元测试到集成测试
支持依赖测试方法,并行测试,异常测试,参数化测试,超时测试,分组测试等测试方法
基于Annotation机制,使测试方法更为灵活配置
引入xml配置文件,从而使软件测试不仅仅硬编码到程序中,做到更加灵活
支持多线程测试(并发测试)
支持数据驱动测试(使用@DataProvider)
使用
啥都不说,要想使用TestNG框架,首先还是需要引入TestNG的依赖。
添加TestNG的依赖
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.10</version> </dependency>
快速使用
添加好依赖之后,就是使用了,运行TestNG的方式有很多种:可以直接通过IDEA,Eclipse或者XML文件运行。通过IDEA 运行无需安装插件。
import org.testng.annotations.Test; public class SimpleTest { @Test public void testNgHelloWorld() { System.out.println("hello world"); } }
1.通过IDEA运行
下面以IDEA为例,选中要执行的测试方法,右键,点击 Run 'testNgHelloWorld()' 即可执行该测试方法。
2.通过xml文件运行
TestNG一个重要的特性就是支持XML来执行单元测试,针对上面的测试方法,我们可以定义一个名叫SimpleTest.xml的XML文件来运行该测试方法。
<?xml version="1.0" encoding="UTF-8" ?> <suite name="Suite" parallel="false"> <test name="Test"> <classes> <class name="com.jay.testng.SimpleTest"/> </classes> </test> </suite>
同样选中xml文件,右键即可运行,各个元素的作用后面再介绍。
注解说明
注解名 | 注解说明 |
@BeforeSuite | 在此套件中的所有测试运行之前,将运行带该注解的方法。 |
@AfterSuite | 在此套件中的所有测试运行后,将运行带该注解的方法。 |
@BeforeTest | 在运行属于<test> 标记内的类的任何测试方法之前,将运行带该注解的方法。 |
@AfterTest | 在运行了属于<test> 标记内的类的所有测试方法之后,将运行带该注解的方法。 |
@BeforeGroups | 此配置方法将在之前运行的组列表,保证在调用属于任何这些组的第一个测试方法之前不久运行此方法。 |
@AfterGroups | 此配置方法将在之后运行的组列表,保证在调用属于任何这些组的最后一个测试方法后不久运行此方法。 |
@BeforeClass | 在调用当前类中的第一个测试方法之前,将运行注解的方法 |
@AfterClass | 在运行当前类中的所有测试方法之后,将运行带注解的方法 |
@BeforeMethod | 带该注解的方法将在每个测试方法之前运行。 |
@AfterMethod | 带该注解的方法将在每个测试方法之后运行。 |
@Listeners | 在测试类上定义侦听器 |
@Parameters | 描述如何将参数传递给@Test方法 |
@Test | 将类或方法标记为测试的一部分,定义测试方法 |
举一个栗子
空洞的说明,总是显得很无趣,让人感到索然无味。下面就是举个栗子说明:
public class NewTest { @Test(groups = "group1") public void test1() { System.out.println("test1 from group1"); Assert.assertTrue(true); } @Test(groups = "group1") public void test11() { System.out.println("test11 from group1"); Assert.assertTrue(true); } @Test(groups = "group2") public void test2() { System.out.println("test2 from group2"); Assert.assertTrue(true); } @BeforeTest public void beforeTest() { System.out.println("beforeTest"); } @AfterTest public void afterTest() { System.out.println("afterTest"); } @BeforeClass public void beforeClass() { System.out.println("beforeClass"); } @AfterClass public void afterClass() { System.out.println("afterClass"); } @BeforeSuite public void beforeSuite() { System.out.println("beforeSuite"); } @AfterSuite public void afterSuite() { System.out.println("afterSuite"); } //需要添加group名称才可以正确挂载到该group下 @BeforeGroups(groups = "group1") public void beforeGroups() { System.out.println("beforeGroups"); } @AfterGroups(groups = "group1") public void afterGroups() { System.out.println("afterGroups"); } @BeforeMethod public void beforeMethod() { System.out.println("beforeMethod"); } @AfterMethod public void afterMethod() { System.out.println("afterMethod"); } }
运行结果如下图所示:
从上面的运行结果可以看出,
@BeforeSuite 最先运行,且只运行一次,相当于做测试准备,
@BeforeTest 第二个运行,同样的也做测试准备,
@BeforeClass 在运行测试类的第一个测试方法之前运行,只运行一次。
@BeforeGroups,在运行该分组下第一个测试方法之前运行,只运行一次。
@BeforeMethod在运行测试方法之前运行,有多少个测试方法就会运行多少次。@AfterMethod 在运行测试方法之后运行,有多少个测试方法就会运行多少次。
其余的也是类似的,再次不在赘述。
分组测试
分组测试也是TestNG的一个重要特性。
@Test(groups = {"group3","group5"}) public void test11() { System.out.println("test11 from group3 or group5"); Assert.assertTrue(true); } @Test(groups = "group4") public void test2() { System.out.println("test2 from group4"); Assert.assertTrue(true); }
如上面的test11和test2两个测试方法属于不同的分组,必须一个分组所有的测试方法执行完才会执行下一个分组的测试方法。这样就给了测试很大灵活性,例如我们可以选择性的执行某个分组下的测试方法。如下xml中定义了只执行分组group3下的测试方法。
<suite name="Suite" parallel="false"> <test name="Test"> <groups> <run> <include name="group3"/> </run> </groups> <classes> <class name="com.jay.testng.TestCase5"/> </classes> </test> </suite>
如果要排除某个分组只需要将include改成exclude
依赖测试
在Junit中两个测试方法是相互独立,没有依赖关系。但是,有的场景中是需要两个测试方法有依赖关系的,比如下单和支付接口,必须先下单了才能支付。针对这种场景,TestNG也是支持的,依赖的参数就是dependsOnMethods参数。
@Test(enabled = true) public void testNgLearn1() { System.out.println("this is TestNG test case1"); Assert.assertTrue(true); } @Test(dependsOnMethods = {"testNgLearn1"}) public void testNgLearn2() { System.out.println("this is TestNG test case2"); Assert.assertTrue(true); }
如上图,testNgLearn2方法依赖了testNgLearn1方法。其中,enabled为true,表示启动该测试方法,如果为false则表示忽略该测试方法。 运行结果是:
参数化测试
有时候需要传递不同的参数来对被测试方法进行测试,TestNG同样是支持的。有两种方式可以实现,一种是通过@Parameters的方式,一种是通过@DataProvider的方式
通过@Parameters传递参数
@Test(enabled = true) @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); }
如上,testNgLearn1方法有param1和param2两个参数,要想运行该测试方法,传入这两个参数,还需要一个XML文件,定义一个名为Suite3.xml 的xml文件。
<?xml version="1.0" encoding="UTF-8" ?> <suite name="Suite" parallel="false"> <test name="Test"> <parameter name="param1" value="101111"/> <parameter name="param2" value="10"/> <classes> <class name="com.jay.testng.TestCase3"/> </classes> </test> </suite>
运行的结果是:
通过@DataProvider传递参数
通过@DataProvider传递参数,需要注意的是参数的类型需要保持一致,如下图,传递了三组参数。将方法标记为测试方法提供数据,带注解的方法必须返回一个Object[][],其中每个Object[]都可以分配测试方法的参数列表,想要从此DataProvider接收数据的@Test方法需要使用dataProvider,名称等于此注解的名称。
@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); }
异常测试
异常测试跟Junit类似,同样也是在@Test注解的expectedExceptions属性中定义异常类,如下图所示:
@Test(expectedExceptions = ArithmeticException.class) public void divisionWithException() { int i = 1 / 0; System.out.println("After division the value of i is:" + i); }
总结
本文详细介绍了TestNG的一些基本概念和基本的特性,总体来说TestNG比Junit更强更好用,拥有更多的特性,其中最主要的几个特性就是:参数化测试,支持XML文件运行测试,支持分组测试,还有就是支持多线程测试。关于多线程测试,后面一篇文章会详细介绍。
结尾想说的
学习的路漫漫,其修远兮!!!!,欢迎大家积极留言,一起学习,一起进步。