java中test的用法详解,testng使用详解(示例代码)

一、testng 介绍

TestNG 是一个测试框架,其灵感来自 JUnit 和 NUnit,但同时引入了一些新的功能,使其功能更强大,使用更方便。

TestNG 设计涵盖所有类型的测试:单元,功能,端到端,集成等,它需要 JDK5 或更高的 JDK 版本。

详细使用说明请参考官方链接:https://testng.org/doc/index.html

在 maven 中引入依赖:

org.testng

testng

6.10

简单示例:

(1)被测试 HelloWorld 类

package study.testng;

public class HelloWorld {

public String hello(){

return "hello world !";

}

}

(2)测试类 TestHelloWorld 类

package study.testng;

import org.testng.Assert;

import org.testng.annotations.Test;

public class TestHelloWorld {

//测试返回结果不为空

@Test

public void tester1(){

HelloWorld hello = new HelloWorld();

String helloworld = hello.hello();

Assert.assertNotNull(helloworld);

}

//测试返回结果为”hello world !“字符串

@Test

public void tester2(){

HelloWorld hello = new HelloWorld();

String helloworld = hello.hello();

System.out.println(helloworld);

Assert.assertEquals(helloworld, "hello world !");

}

}

(3)测试结果

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

hello world !

===============================================

Default Suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

二、@Test注解及常用属性

凡是在类方法中添加了 @Test 注解的就是我们需要测试的方法

1、enable 测试方法是否执行

默认是 true , 如果设置为 false ,则在运行时不会执行这个测试方法;

示例:

package com.ggf.testng.annotation;

import org.testng.annotations.Test;

/**

* @Description: 忽略测试,可以通过@Test的注解的enable属性来配置是否执行用例方法

* enable默认值为 true,需要设置为false才会跳过这个测试用例

* @Author: ggf

* @Date: 2019/12/29

*/

public class IgnoreTest {

@Test

public void ignore1() {

System.out.println("ignore1 run...");

}

@Test(enabled = false)

public void ignore2() {

System.out.println("ignore2 run ...");

}

@Test

public void ignore3() {

System.out.println("ignore3 run ...");

}

}

运行结果:

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

ignore1 run...

ignore3 run ...

===============================================

Default Suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

2、预期异常expectedExeption

@Test(expectedExceptions = ClassName.class)

如果 ClassName 类抛出了异常,测算测试通过,没有异常算测试不通过;

expectedExceptions的值也可以是一个数组:

@Test(expectedExceptions = {ClassName.class, ClassName2.class,... })

示例:

package com.ggf.testng.annotation;

import org.testng.annotations.Test;

/**

* @Description: 异常测试

* @Author: ggf

* @Date: 2019/12/29

*

* 什么时候会用到异常测试??

* 在我们期望结果为某一个异常的时候

* 比如:我们传入了某些不合法的参数,程序抛出了异常

* 也就是说我的期望结果就是这个异常。

*/

public class ExpectedException {

/**

* 运行时异常,我们期望返回一个运行时异常,这条用例才是正确的。

*/

@Test(expectedExceptions = RuntimeException.class, enabled = false)

public void runTimeExceptionFailed() {

System.out.println("没有抛出异常,这条用例不通过!");

}

/**

* 结果抛出了一个运行时异常,和我们的期望一致,测试通过。

*/

@Test(expectedExceptions = RuntimeException.class)

public void runTimeExceptionSuccess() {

System.out.println("程序抛出了运行时异常,测试用例通过!");

throw new RuntimeException();

}

}

运行结果:

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

程序抛出了运行时异常,测试用例通过!

===============================================

Default Suite

Total tests run: 1, Failures: 0, Skips: 0

===============================================

3、依赖方法dependsOnMethods

在被依赖的方法运行完成之后运行当前方法,如果依赖方法测试不通过,那么当前方法也不会继续运行了;依赖的方法可以有多个;

例:@Test(dependsOnMethods = { "methodName1" , “methodName2” })

示例:

package com.ggf.testng.annotation;

import org.testng.annotations.Test;

/**

* @Description: 方法直接的依赖测试

* @Author: ggf

* @Date: 2019/12/29

*/

public class DependTest {

@Test

public void test1() {

System.out.println("test1 run ...");

}

/**

* test2运行时,需要依赖test1的运行

* 如果test1运行失败,会直接忽略test2, test2就不会执行了。

*/

@Test(dependsOnMethods = {"test1"})

public void test2() {

System.out.println("test2 run ...");

}

}

4、分组groups

把在一个标签内的中所有类方法再进行组,在运行时,一个组的方法会一起运行,然后再运行下一个组的方法;

分组的最小维度为方法,当把带分组的@Test(groups = ”groupName”)注解对类使用时,这个测试类中的所有方法都属于这同一个组;

一个方法也可以同时属于多个组,@Test(groups = {“groupName1”, “groupName2”}),那么每组运行时这个方法都会被执行一次;

同一个组里的方法类,如果分别属于两个不同的测试用例()内,那么它们其实可以算两个组,它们会在每个测试用例分别运行,而不会合在一起运行;

示例:

package com.ggf.testng.groups;

import org.testng.annotations.AfterGroups;

import org.testng.annotations.BeforeGroups;

import org.testng.annotations.Test;

import javax.sound.midi.Soundbank;

/**

* @Description: 对测试用例方法进行分组,可以对一组中的数据进行初始化

* @Author: ggf

* @Date: 2019/12/29

*/

public class GroupsOnMethod {

@BeforeGroups(groups = "server")

public void beforeGroupsOnServer() {

System.out.println("服务端组运行前执行的方法。。。");

}

@BeforeGroups(groups = "client")

public void beforeGroupsOnClient() {

System.out.println("客户端组运行前执行的方法。。。");

}

@Test(groups = "server")

public void test1() {

System.out.println("server test1 run ....");

}

@Test(groups = "server")

public void test2() {

System.out.println("server test2 run ....");

}

@Test(groups = "client")

public void test3() {

System.out.println("client test3 run ....");

}

@Test(groups = "client")

public void test4() {

System.out.println("client test4 run ....");

}

@AfterGroups(groups = "server")

public void afterGroupsOnServer() {

System.out.println("服务端组运行之后执行的方法。。。");

}

@AfterGroups(groups = "client")

public void afterGroupsOnClient() {

System.out.println("客户端组运行之后执行的方法。。。");

}

}

运行结果:

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

服务端组运行前执行的方法。。。

server test1 run ....

server test2 run ....

服务端组运行之后执行的方法。。。

客户端组运行前执行的方法。。。

client test3 run ....

client test4 run ....

客户端组运行之后执行的方法。。。

===============================================

Default Suite

Total tests run: 4, Failures: 0, Skips: 0

===============================================

5、超时属性timeOut

@Test(timeOut = 3000) 设置超时时间,单位为毫秒。

示例:

package com.course.testng;

import org.testng.annotations.Test;

public class TimeOutTest {

/**

* 单位为毫秒值,3秒内没有响应,就证明失败了,反之成功

* @throws InterruptedException

*/

@Test(timeOut = 3000)

public void testSuccess() throws InterruptedException {

Thread.sleep(2000);

}

@Test(timeOut = 2000)

public void testFailed() throws InterruptedException {

Thread.sleep(3000);

}

}

运行结果:

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

org.testng.internal.thread.ThreadTimeoutException: Method com.course.testng.TimeOutTest.testFailed() didn't finish within the time-out 2000

===============================================

Default Suite

Total tests run: 2, Failures: 1, Skips: 0

===============================================

6、属性总结

属性名

描述

alwaysRun

设置为 true 时,无论什么情况都会运行

dataProvider

数据提供者的名称

dataProviderClass

如果未指定,将在当前测试方法的类或其父类之一上查找数据提供者。 如果指定了此属性,则数据提供者方法在指定的类上必须是静态的。

dependsOnGroups

依赖的组列表

dependsOnMethods

依赖的方法列表

description

说明

enabled

默认为true,设置为 false 时失效

expectedExceptions

预期测试方法将引发的异常列表。 如果未引发任何异常或与该列表中的异常不同,则此测试将标记为失败。

groups

所属组

invocationCount

调用次数

invocationTimeOut

所有 invocationCount 的累积超时时间。 注意:如果未指定 nvocationCount,则将忽略此属性。

priority

此测试方法的优先级

successPercentage

该方法预期成功的百分比

singleThreaded

如果设置为 rue,则即使当前正在使用 parallel =“ methods” 运行测试,也保证该测试类上的所有方法都可以在同一线程中运行。 此属性只能在类级别使用,如果在方法级别使用,则将被忽略。

timeOut

超时时间

threadPoolSize

此方法的线程池的大小。 该方法将从 invocationCount 指定的多个线程中调用。 注意:如果未指定 invocationCount,则忽略此属性

三、testng常用注解

注解

描述

@BeforeSuite

在该套件的所有测试都运行在注释的方法之前,仅运行一次(套件测试是一起运行的多个测试类)。

@AfterSuite

在该套件的所有测试都运行在注释方法之后,仅运行一次。

@BeforeClass

在调用当前类的第一个测试方法之前运行,注释方法仅运行一次。

@AfterClass

在调用当前类的第一个测试方法之后运行,注释方法仅运行一次。

@BeforeTest

注释的方法将在属于标签内的类的所有测试方法运行之前运行。

@AfterTest

注释的方法将在属于标签内的类的所有测试方法运行之后运行。

@BeforeGroups

配置方法将在之前运行组列表。 此方法保证在调用属于这些组中的任何一个的第一个测试方法之前不久运行。

@AfterGroups

此配置方法将在之后运行组列表。该方法保证在调用属于任何这些组的最后一个测试方法之后不久运行。

@BeforeMethod

注释方法将在每个测试方法之前运行。

@AfterMethod

注释方法将在每个测试方法之后运行。

@Parameters

描述如何将参数传递给@Test方法。

@DataProvider

标记一种方法来提供测试方法的数据。 注释方法必须返回一个Object [] [],其中每个Object []可以被分配给测试方法的参数列表。 要从该DataProvider接收数据的@Test方法需要使用与此注释名称相等的dataProvider名称。

@Factory

将一个方法标记为工厂,返回TestNG将被用作测试类的对象。 该方法必须返回Object []。

@Listeners

定义测试类上的侦听器。

@Test

将类或方法标记为测试的一部分。

示例:

测试类 TestConfig.java

package study.testng;

import org.testng.annotations.AfterGroups;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.AfterSuite;

import org.testng.annotations.AfterTest;

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 TestConfig {

@BeforeSuite

public void beforeSuite() {

System.out.println("测试套件(当前xml中标签)之前运行@BeforeSuite--------------------");

}

@AfterSuite

public void afterSuite() {

System.out.println("测试套件(当前xml中标签)之后运行@AfterSuite--------------------

");

}

@BeforeTest

public void beforeTest() {

System.out.println("测试用例(当前xml中标签)之前运行@BeforeTest----------");

}

@AfterTest

public void afterTest() {

System.out.println("测试用例(当前xml中标签)之后运行@AfterTest----------

");

}

@BeforeMethod

public void beforeMethod() {

System.out.println("当前类每个测试方法(@Test)之前运行@BeforeMethod");

}

@AfterMethod

public void AfterMethod(){

System.out.println("当前类每个测试方法(@Test)之后运行@AfterMethod");

}

@BeforeGroups(value="group1")

public void beforeGroups(){

System.out.println("配置组配group1之前运行@BeforeGroups..................");

}

@AfterGroups(value="group1")

public void afterGroups(){

System.out.println("配置组配group1之前运行@AfterGroups..................");

}

@Test

public void test1(){

System.out.println("runnig TestConfig.test1()");

}

@Test(groups = "group1")

public void test2(){

System.out.println("runnig TestConfig.test2()");

}

@Test(groups = "group1")

public void test3(){

System.out.println("runnig TestConfig.test3()");

}

}

新建一个自定义 xml 配置文件 tester.xml (maven项目将该文件创建在 resource 目录下)

运行结果:

231d1cbcbe0dca5ba0ebd2a62473b9b4.png

从这个结果显示出注释的作用位置。其中 @BeforeGroups 和 @AfterGroups 的作用范围是可以跨类的,但类必须是在同一个测试用例(标签)范围内;

这些标签的运行先后顺序可以总结为:

@BeforeSuite->@BeforeTest->@BeforeClass->{@BeforeMethod->@Test->@AfterMethod}->@AfterClass->@AfterTest->@AfterSuite(其中{}内的与多少个@Test,就循环执行多少次)。

四、testng.xml 配置文件详解

1、配置文件结构(较详细):

2、配置文件标签说明

标签

说明:一个xml文件只能有一个, 是一个xml文件的根级

由 和 组成

标签属性说明:

属性

说明

使用方法

参数值

name

必选项,的名字,将出现在reports里

name="XXX"

suite名字

junit

是否执行Junit模式(识别setup()等)

junit="true"

true和false,默认false

verbose

控制台输出的详细内容等级,0-10级(0无,10最详细)

verbose="5"

0到10

parallel

是否在不同的线程并行进行测试,要与thread-count配套使用

parallel="mehods"

详见表格下内容,默认false

parent-module

和Guice框架有关,只运行一次,创建一个parent injector给所有guice injectors

guice-stage

和Guice框架有关

guice-stage="DEVELOPMENT"

DEVELOPMENT,PRODUCTION,TOOL,默认"DEVELOPMENT"

configfailurepolicy

测试失败后是再次执行还是跳过,值skip和continue

configfailurepolicy="skip"

skip、continue,默认skip

thread-count

与parallel配套使用,线程池的大小,决定并行线程数量

thread-count="10"

整数,默认5

annotations

获取注解,值为javadoc时,使用JavaDoc的注释;否则用JDK5注释

annotations="javadoc"

javadoc

time-out

设置parallel时,终止执行单元之前的等待时间(毫秒)

time-out="10000"

整数,单位毫秒

skipfailedinvocationcounts

是否跳过失败的调用

skipfailedinvocationcounts="true"

true和false,默认false

data-provider-thread-count

并发时data-provider的线程池数量

data-provider-thread-count="5"

整数

object-factory

一个实现IObjectFactory接口的类,实例化测试对象

object-factory="classname"

类名

allow-return-values

是否允许返回函数值

all-return-values="true"

true和false

preserve-order

是否按照排序执行

preserve-order="true"

true和false,默认true

group-by-instances

按照实例分组

group-by-instances="true"

true和false,默认false

parallel 属性详细说明

该参数的值false,methods,tests,classes,instances。默认false

parallel 必须和 thread-count 配套使用,否则相当于无效参数,thread-count 决定了并行测试时开启的线程数量

parallel="mehods" TestNG将并行执行所有的测试方法在不同的线程里

parallel="tests" TestNG将并行执行在同一个下的所有方法在不同线程里

parallel="classes" TestNG将并行执行在相同下的方法在不同线程里

parallel="instances" TestNG将并行执行相同实例下的所有方法在不同的县城里

parent-module 和guice-stage 和 Guice 框架有关,testNG 6对 Guice 框架提供了支持,我没用过这个框架,所以这两个参数没看懂╮(╯▽╰)╭

标签

说明:引入外部的xml文件(地址由path参数决定,path必填项),将引入的xml与当前的xml文件一起使用

声明方法:

标签

说明:一个下可以有多个,可以通过的parallel="tests"来进行并行测试,必须和thread-count配套使用,否则是无效参数

由、、三部分组成

标签属性说明:

参数

说明

使用方法

参数值

name

test的名字,将出现在报告里

name="testname"

test的名字

junit

是否按照Junit模式运行

junit="true"

true和false,默认false

verbose

控制台输出的详细内容等级,0-10级(0无,10最详细),不在报告显示

verbose="5"

0到10

parallel

是否在不同的线程并行进行测试,要与thread-count配套使用

parallel="mehods"

与suite的parallel一致,默认false

thread-count

与parallel配套使用,线程池的大小,决定并行线程数量

thread-count="10"

整数,默认5

annotations

获取注解,值为javadoc时,使用JavaDoc的注释;否则用JDK5注释

annotations="javadoc"

javadoc

time-out

设置parallel时,终止执行单元之前的等待时间(毫秒)

time-out="10000"

整数,单位毫秒

enabled

标记是否执行这个test

enabled="true"

true和false,默认true

skipfailedinvocationcounts

是否跳过失败的调用

skipfailedinvocationcounts="true"

true和false,默认false

preserve-order

是否按照排序执行,如果是true,将按照xml文件中的顺序去执行

preserve-order="true"

true和false,默认true

allow-return-values

是否允许返回函数值

all-return-values="true"

true和false,默认false

标签

说明:提供测试数据,有name和value两个参数

声明方法:

testng.xml 文件中的可以声明在或者级别,在下的会覆盖在下声明的同名变量

标签

说明:要运行的组,可以自定义一个组,可以包括要执行的,还排除要执行的方法。必须和配套使用,从下面的类中找到对应名字的方法

由 和 、 三部分组成。

可以将 group 组成一个新组,包括要执行和不执行的大组;

要执行的方法;

指定了某 group 需要依赖的 group(比如下面的例子,group1 需要依赖 group2 和 group3 先执行)。

声明方法:

标签

说明:方法选择器,要执行的方法写在这里,参数有name和priority。

注释:

1.下必须写要执行的,否则不会执行任何内容,如果填写了 class 没有写 methods,会按照填写的 class 的下的注释 @Test 去执行所有的方法

2.下的如果填写了,那只会执行所填写的方法,没有填写的方法不会去执行

声明方法:

五、testng 中方法参数传递

1、使用 @Parameters 注解从测试配置 xml 文件获取参数

(1)创建测试类:PatamterTest.java

package com.ggf.testng.paramter;

import org.testng.annotations.Parameters;

import org.testng.annotations.Test;

/**

* @Description: testNG的参数化配置,通过xml文件进行方法的赋值操作

* @Author: ggf

* @Date: 2019/12/29

*/

public class PatamterTest {

@Test

@Parameters({"name","age"})

public void showInfo(String name, int age) {

System.out.println("name="+ name + " age=" + age);

}

}

(2)创建配置文件

(3)运行结果:

[TestNG] Running:

D:workspaceestworkestNGDemosrcmainesourcesparamter.xml

name=张三 age=11

===============================================

paramterTest

Total tests run: 1, Failures: 0, Skips: 0

===============================================

2、使用@DataProvider传送参数,@DataProvider可以传递一些比较复杂的参数

示例:

package com.ggf.testng.paramter;

import org.testng.annotations.DataProvider;

import org.testng.annotations.Test;

import java.util.HashMap;

import java.util.Map;

/**

* @Description: 主要是对DataProvider注解的学习,通过这个注解的标识,来给测试类进行赋值。

* @Author: ggf

* @Date: 2019/12/29

* 首先定义一个数据源的方法,通过@DataProvider注解来标识。

* 然后定义一个测试方法,通过@Test(dataProvider="")属性来获取数据

*/

public class DataProviderTest {

/**

* 数据源,是方法提供数据,返回必须是一个二维数组

* @DataProvider(name = "data") 通过该注解来标识这个为数据源,name为数据源的名称。

* @return 返回一个二维数组

*/

@DataProvider(name = "data")

public Object[][] providerData() {

Object[][] data = new Object[][] {

{"zhangsan",12},

{"lisi",22},

{"wangwu",32}

};

return data;

}

/**

* 通过dataProvider来获取数据,执行的次数会根据数据源提供数据的数量

* 例如上面的二维数组长度为3,则该方法会执行三次。

* @param name

* @param age

*/

@Test(dataProvider = "data")

public void testDataProvider(String name, int age) {

System.out.println("name=" + name + " age=" + age);

}

}

运行结果:

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

name=zhangsan age=12

name=lisi age=22

name=wangwu age=32

===============================================

Default Suite

Total tests run: 3, Failures: 0, Skips: 0

===============================================

六、testng 多线程测试

1、使用注解实现多线程测试

invocationCount:线程调用的次数,默认1次。

threadPoolSize:线程池大小,和 invocationCount 一起使用,如果没有定义 invocationCount ,定义了threadPoolSize,是没有效果的。

@Test(invocationCount = 10,threadPoolSize = 3)

invocationCount 默认这个属性的值是 1, 即只会执行一次,当从新赋值时,该方法就会执行多次。

这里就是,定义了三个线程,来执行这个方法10次。

示例:

package com.course.testng.multiThread;

import org.testng.annotations.Test;

public class MultiThreadOnAnnotion {

@Test(invocationCount = 10,threadPoolSize = 3)

public void test(){

System.out.println(1);

System.out.printf("Thread Id : %s%n",Thread.currentThread().getId());

}

}

运行结果:

[TestNG] Running:

C:UsersAdministrator.IntelliJIdea2019.2systememp-testng-customsuite.xml

1

1

1

Thread Id : 12

Thread Id : 11

1

Thread Id : 11

Thread Id : 13

1

Thread Id : 12

1

Thread Id : 12

1

Thread Id : 11

1

Thread Id : 12

1

Thread Id : 12

1

Thread Id : 13

===============================================

Default Suite

Total tests run: 10, Failures: 0, Skips: 0

===============================================

从输出结果可以看出,一共有三条线程在执行,一共执行了10次(输出了10个1)

2、使用 xml 配置文件实现多线程测试

(1)创建测试类:MultiThreadOnXml.java

package com.ggf.testng.multithread;

import org.testng.annotations.Test;

/**

* @Description: 使用配置文件来实现testng的多线程

* @Author: ggf

* @Date: 2020/02/01

*/

public class MultiThreadOnXml {

@Test

public void test1() {

System.out.printf("Thread id: %s%n", Thread.currentThread().getId());

}

@Test

public void test2() {

System.out.printf("Thread id: %s%n", Thread.currentThread().getId());

}

@Test

public void test3() {

System.out.printf("Thread id: %s%n", Thread.currentThread().getId());

}

}

(2)配置文件编写

(3) 运行结果

[TestNG] Running:

D:workspaceestworkestNGDemosrcmainesourcesmultithread.xml

Thread id: 11

Thread id: 13

Thread id: 12

===============================================

thread

Total tests run: 3, Failures: 0, Skips: 0

===============================================

输出结果可以看出,有三条线程分别执行了不同的方法。

参考资料:

博客:

https://www.cnblogs.com/aland-1415/p/10475957.html

https://www.cnblogs.com/meitian/p/5221202.html

视频教程:

https://coding.imooc.com/class/204.html