86427019 2019-12-21
在类里编辑程序时,在@Test后面,摁 alt+回车,选择对应的插件,可以把目前用到的插件自动添加到 pom.xml 文件中,如下面的testng,每摁一次,就多添加一次
当使用的类里,用到的方法没有导入类包时,可以在 类的大括号 后面,摁 alt+回车 ,可以自动导入目前的类中,需要用到的类包,如 import org.testng.annotations.Test;
比如:
运行结果为:
public class BasicAnnotation { //最基本的注解,用来把方法标记为测试的一部分 @Test public void testCase1(){ System.out.println("这是测试用例1"); } @Test public void testCase2(){ System.out.println("这是测试用例2"); } @BeforeMethod public void beforeMethod(){ System.out.println("BeforeMethon这是在测试方法之前运行的"); } @AfterMethod public void afterMethod(){ System.out.println("AfterMethod这是在测试方法之后运行的"); } @BeforeClass public void beforeClass(){ System.out.println("beforeClass这是在类运行之前运行的方法"); } @AfterClass public void afterClass(){ System.out.println("afterClass这是在类运行之后运行的方法"); } }
public class BasicAnnotation { //最基本的注解,用来把方法标记为测试的一部分 @Test public void testCase1(){ System.out.println("这是测试用例1"); } @Test public void testCase2(){ System.out.println("这是测试用例2"); } @BeforeMethod public void beforeMethod(){ System.out.println("BeforeMethon这是在测试方法之前运行的"); } @AfterMethod public void afterMethod(){ System.out.println("AfterMethod这是在测试方法之后运行的"); } @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测试套件,在当前测试套件下所有类运行结束之后运行一次,包含该套件下所有类"); } }
Resources里面,存放的是@test的配置文件XML
4、新建XML配置文件
5、编辑相关文件
SuiteConfig.java package com.units.mytest.suite; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; public class SuiteConfig { @BeforeSuite public void beforeSuite(){ System.out.println("before suite运行啦"); } @AfterSuite public void aftersuite(){ System.out.println("after suite 运行啦"); } @BeforeTest public void beforeTest(){ System.out.println("运行beforeTest"); } @AfterTest public void afterTest(){ System.out.println("运行aftertest"); } }
LoginTest.java package com.units.mytest.suite; import org.testng.annotations.Test; public class LoginTest { @Test public void loginTaoBao(){ System.out.println("淘宝登陆成功"); } }
PayTest.java package com.units.mytest.suite; import org.testng.annotations.Test; public class PayTest { @Test public void paySuccess(){ System.out.println("支付宝支付成功"); } }
suite.xml
,在每个类标签里都放入SuiteConfig,说明该配置类里的方法对每个类都有效,里面的方法是公共方法。<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="test"> <test name="login"> <classes> <class name="com.units.mytest.suite.SuiteConfig"/> <class name="com.units.mytest.suite.LoginTest"/> </classes> </test> <test name="pay"> <classes> <class name="com.units.mytest.suite.SuiteConfig"/> <class name="com.units.mytest.suite.PayTest"/> </classes> </test> </suite>
public class IgnoreTest { @Test public void ignore1(){ System.out.println("ignore1 执行"); } @Test(enabled = false) public void ignore2(){ System.out.println("ignore2 执行"); } @Test(enabled = true) public void ignore3(){ System.out.println("ignore3 执行"); } }
public class GroupsOnMethod { @Test(groups = "server") //组名 public void test1(){ System.out.println("这是服务端组的测试方法11111"); } @Test(groups = "server") public void test2(){ System.out.println("这是服务端组的测试方法22222"); } @Test(groups = "client") public void test3(){ System.out.println("这是服务端组的测试方法33333"); } @Test(groups = "client") public void test4(){ System.out.println("这是服务端组的测试方法44444"); } @BeforeGroups("server") public void beforeGroupsOnServer(){ System.out.println("这是服务端组运行之前运行的方法!!!!!"); } @AfterGroups("server") public void afterGroupsOnServer(){ System.out.println("这是服务端组运行之后运行的方法!!!!!"); } @BeforeGroups("client") public void beforeGroupsOnClient(){ System.out.println("这是客户端组运行之前运行的方法!!!!!"); } @AfterGroups("client") public void afterGroupsOnClient(){ System.out.println("这是客户端组运行之后运行的方法!!!!!"); } }
1、新建三个类
2、类的内容如下:
GroupsOnClass1.java @Test(groups = "stu") public class GroupsOnClass1 { public void stu1(){ System.out.println("GroupsOnClass1中的stu1运行"); } public void stu2(){ System.out.println("GroupsOnClass1中的stu2运行"); } }
GroupsOnClass2.java Test(groups = "stu") public class GroupsOnClass2 { public void stu1(){ System.out.println("GroupsOnClass222中的stu1运行"); } public void stu2(){ System.out.println("GroupsOnClass222中的stu2运行"); } }
GroupsOnClass3.java @Test(groups = "teacher") public class GroupsOnClass3 { public void teacher1(){ System.out.println("GroupsOnClass3中的teacher1运行"); } public void teacher2(){ System.out.println("GroupsOnClass3中的teacher2运行"); } }
其中,前面两个类属于stu组,第三个类属于teacher组
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="suitename"> <test name="runAll"> <!—执行所有的测试类--> <classes> <class name="com.units.mytest.groups.GroupsOnClass1"/> <class name="com.units.mytest.groups.GroupsOnClass2"/> <class name="com.units.mytest.groups.GroupsOnClass3"/> </classes> </test> <test name="onlyRunStu"> <groups> <run> <include name="stu"/> <!—仅执行组类名为stu的测试类--> </run> </groups> <classes> <class name="com.units.mytest.groups.GroupsOnClass1"/> <class name="com.units.mytest.groups.GroupsOnClass2"/> <class name="com.units.mytest.groups.GroupsOnClass3"/> </classes> </test> </suite>
public class ExpectedException { /*什么时候会用到异常测试? * 在我们期望结果为某一个异常的时候 * 比如:我们传入了某些不合法的参数,程序抛出了异常 * 也就是说我的语句结果就是这个异常。 * */ // 这是一个测试结果会失败的异常测试 @Test(expectedExceptions = RuntimeException.class) //期望结果为运行时异常 public void runTimeExceptionFailed(){ System.out.println("这是一个失败的异常测试"); } // 这是一个成功的异常测试 @Test(expectedExceptions = RuntimeException.class) public void runTimeExceptionSuccess(){ System.out.println("这是一个成功的异常测试"); throw new RuntimeException(); //强制抛出一个运行时异常 } }
- hard依赖:默认为此依赖方式,即其所有依赖的methods或者groups必须全部pass,否则被标识依赖的类或者方法将会被略过,在报告中标识为skip,如后面的范例所示,此为默认的依赖方式;
- soft依赖:此方式下,其依赖的方法或者组有不是全部pass也不会影响被标识依赖的类或者方法的运行,注意如果使用此方式,则依赖者和被依赖者之间必须不存在成功失败的因果关系,否则会导致用例失败。此方法在注解中需要加入alwaysRun=true即可.
dependsOnMethods
package unittests; import java.lang.reflect.Method; import org.testng.annotations.*; public class Test11 { @DataProvider(name = "dp") //提供参数化数据 public Object[][] createData(Method m){ // 打印测试方法名 System.out.println(m.getName()); return new Object[][]{new Object[]{"qctest"}}; } @Test(dataProvider = "dp", dependsOnMethods = { "test2" }) public void test1(String s){ } @Test(dataProvider = "dp") public void test2(String s){ //test2运行失败情况 int a = 1/0; } }
上面程序,test1 的运行依赖 test2 的运行。此时会先运行test2,然后再运行test1。
注意:这种依赖,如果被依赖者运行失败,那么依赖者将不被执行,报告中被标记为 SKIP。结果如下
test2 FAILED: test2("qctest") java.lang.ArithmeticException: / by zero ………… SKIPPED: test1 java.lang.Throwable: Method Test11.test1(java.lang.String)[pri:0, instance:] depends on not successfully finished methods ………… =============================================== Default test Tests run: 2, Failures: 1, Skips: 1 ===============================================
alwaysRun=true
解决上例中被依赖者运行失败,不执行依赖者的问题,如下:package unittests; import java.lang.reflect.Method; import org.testng.annotations.*; public class Test12 { @DataProvider(name = "dp") public Object[][] createData(Method m){ // 打印测试方法名 System.out.println(m.getName()); return new Object[][]{new Object[]{"qctest"}}; } //alwaysRun=true时,若被依赖者运行失败,则依赖者会继续运行 @Test(dataProvider = "dp", dependsOnMethods = { "test2" }, alwaysRun=true) public void test1(String s){ } @Test(dataProvider = "dp") public void test2(String s){ int a = 1/0; } }
运行结果如下,不管被依赖者运行失败与否,依赖者都会被执行:
[RemoteTestNG] detected TestNG version 6.14.3 test2 test1 PASSED: test1("qctest") FAILED: test2("qctest")
dependsOnGroups
(dependsOnGroups 和 dependsOnMethods 都可接收正则表达式)package unittests; import java.lang.reflect.Method; import org.testng.annotations.*; public class Test13 { @DataProvider(name = "dp") public Object[][] createData(Method m){ // 打印测试方法名 System.out.println(m.getName()); return new Object[][]{new Object[]{"qctest"}}; } @Test(dataProvider = "dp", dependsOnGroups = { "init" }, alwaysRun=true) public void test1(String s){ } @Test(dataProvider = "dp", groups = "init") public void test2(String s){ int a = 1/0; } }
执行结果如下,init组里的所有方法先执行,然后再执行test1方法:
[RemoteTestNG] detected TestNG version 6.14.3 test2 test1 PASSED: test1("qctest") FAILED: test2("qctest")
默认的,依赖方法按组分类,如果方法 test1 和方法 test2 都是同一个测试类的测试方法,
test1依赖test2,那么当该类的多个实例被调用时,会先执行完所有test2,再执行test1。(即该类被多次实例化调用时,都是先执行完所有实例化类的test2,然后才执行test1),如下:
Test14.java package unittests; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import unittests.Test14_2; public class Test14 { @Factory(dataProvider = "dp") public Object[] f(int n) { //结果为一维数组 Object[] result = new Object[n]; for(int i=0; i<n; i++){ //每遍历一次,即实例化一次Test14_2,并把结果存储在result的数组中 result[i] = new Test14_2(); } //返回result整个数组 return result; } //参数化的数据保存在该方法中 @DataProvider public Object[][] dp() { return new Object[][]{ new Object[] { 5 } }; } }
Test14_2.java package unittests; import org.testng.annotations.Test; public class Test14_2 { @Test(dependsOnMethods = "test2") public void test1() { System.out.println("test1"); } @Test public void test2(){ System.out.println("test2"); } }
xmltest14.xml <!-- 从同一个 XML 文件运行的并行 data provider 共享相同的线程池,线程池大小默认为 10. 可通过修改 XML 文件中的<suite>标签来修改。 <suite name="Suite1" data-provider-thread-count="20" > ... 如果想在不同的线程池中运行多个 data provider,需要从 xml 文件中运行它们。 --> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="suite" verbose="1"> <test name="MyTest1"> <classes> <class name="unittests.Test14" /> </classes> </test> </suite>
以testng的方式运行xmltest14.xml,执行类包Test14,结果如下,先执行完所有test2,才执行test1:
[RemoteTestNG] detected TestNG version 6.14.3 test2 test2 test2 test2 test2 test1 test1 test1 test1 test1 =============================================== suite Total tests run: 10, Failures: 0, Skips: 0 ===============================================
解决方法:xml 文件中增加 group-by-instances="true" 比如: <suite name="Factory" group-by-instances="true"> 或者 <test name="Factory" group-by-instances="true">
修改后的具体内容如下 xmltest14_2.xml
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="suite" verbose="1" group-by-instances="true"> <test name="MyTest1"> <classes> <class name="unittests.Test14" /> </classes> </test> </suite>
以testng的方式运行xmltest14_2.xml,执行类包Test14,结果如下,test2和test1轮回输出:
[RemoteTestNG] detected TestNG version 6.14.3 test2 test1 test2 test1 test2 test1 test2 test1 test2 test1 =============================================== suite Total tests run: 10, Failures: 0, Skips: 0 ===============================================
注:TestNG中@Factory与@DataProvider的功能大相径庭,但是在多次执行的问题上常常理不清。
首先,必须明确,使用@DataProvider修饰的方法,只负责提供测试数据,而且是测试执行前就确定了的静态数据。该方法必须被其他测试方法引用才意义。
其次,必须强调,使用@DataProvider修饰的方法,其返回的数据类型必须为Object[][]。为什么必须是二维数组呢?其中的一维表示单位测试数据,而另一维表示可以提供多组独立的测试数据,供逐一使用。
@DataProvider public Object[][] dataMethod() { ? ?return new Object[][] { { "one" }, { "two" } }; }
所以,当@DataProvider修饰的方法提供了多组测试数据时,引用@DataProvider的测试方法,就会被多次执行,每次执行使用@DataProvider的一组测试数据。即@DataProvider修饰的方法中有多少组测试数据,引用@DataProvider的测试方法就会被执行多少次。但是自始至终只有一个测试类的实例,即该实例的一个测试方法被多次执行。
@Test(dataProvider = "dataMethod") public void testMethod(String param) { ? ?System.out.println("The parameter value is: " + param); }
首先,使用@Factory修饰的方法,负责提供测试类的实例。只是测试类的构造函数带了参数,为了构造不同的测试类实例,每次都要给测试类的构造函数传递不同的测试参数,从而构造不同的测试类的实例。@Factory修饰的方法永远返回Object[]类型。
其次,测试类中无需显式引用@Factory修饰的方法,因为该方法就提供测试类的实例,不需要调用。执行测试时,先构造一个测试类的实例,再执行该测试类中的所有测试方法。然后再构造一个新的测试类的实例,并执行其所有测试方法,直到所有的测试类的实例都被构造执行。即@Factory修饰的方法中有多少个测试类的实例,就会执行多少遍该测试类中的所有测试方法。
@Factory public Object[] factoryMethod() { ? ? return new Object[] { ? ? ? ? new SimpleTest("one"), ? ? ? ? new SimpleTest("two") ? ? }; }
3. 在@Factory方法中引用@DataProvider方法
既然@Factory修饰的方法,也需要测试数据用以构造测试类的实例,那么该方法还可以引用@DataProvider修饰的方法,以构造不同的测试类的实例。
@Factory(dataProvider = "dataMethod") public Object[] factoryMethod(String param) { ? ? return new Object[] { ? ? ? ? new SimpleTest(param) ? ? }; }
4. 不同测试类的实例
此外,@Factory修饰的方法不仅仅能够构造一个测试类的不同实例,还能够构造不同测试类的实例。
@Factory(dataProvider = "dataMethod") public Object[] factoryMethod(String param) { ? ? return new Object[] { ? ? ? ? new SimpleTest(param), new ComplicateTest(param) ? ? }; }
使用上述@dataProvider作为参数数据,将分别构造两个SimpleTest测试类实例,和ComplicateTest两个测试类实例。
<dependencies>
标签Test15.java package unittests; import java.lang.reflect.Method; import org.testng.annotations.*; public class Test15 { @Test(groups = "other") public void test3(){ System.out.print("I am qctest"); } @DataProvider(name = "dp") public Object[][] createData(Method m){ // 打印测试方法名 System.out.println(m.getName()); return new Object[][]{new Object[]{"qctest"}}; } @Test(dataProvider = "dp", groups = "init1") public void test1(String s){ } @Test(dataProvider = "dp", groups = "init2") public void test2(String s){ } }
xmltest15.xml <!-- 可选的,可在 testng.xml 文件中指定组依赖。使用<dependencies>标签来实现这个。 注意:被依赖的多个组之间用空格分隔。 --> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="suite" verbose="1"> <test name="MyTest1"> <groups> <dependencies> <group name ="others" depends-on="init1 init2" /> </dependencies> </groups> <classes> <class name="unittests.Test15" /> </classes> </test> </suite>
以testng的方式运行xmltest15.xml,运行类test15,结果如下:
[RemoteTestNG] detected TestNG version 6.14.3 test1 test2 I am qctest =============================================== suite Total tests run: 3, Failures: 0, Skips: 0 ===============================================
others组的方法,依赖于init1和init2组的方法的运行
public class ParamterTest { @Test @Parameters({"name","age"}) //参数变量名 public void paramTest1(String name, int age){ System.out.println("\n name = " + name + "; age = " + age); } }
<?xml version="1.0" encoding="UTF-8" ?> <suite name="parameter"> <test name="param"> <classes> <parameter name="name" value="zhangsan"/> <parameter name="age" value="18"/> <class name="com.units.mytest.paramter.ParamterTest"/> </classes> </test> </suite>
在parameter中定义引用的参数名和相对应的参数值。
DataProviderTest.java public class DataProviderTest { //通过dataProvider找到参数数据并传入 @Test(dataProvider = "data") public void testDataProvider(String name, int age){ System.out.println("name = " + name + "; age = " + age); } //提供参数化数据 @DataProvider(name = "data") public Object[][] providerData(){ Object[][] obj = new Object[][]{ {"zhangsan", 10}, {"lisi", 18}, {"wangwu", 28} }; return obj; } }
运行DataProviderTest.java的结果为
2、根据不同的方法进行不同的参数化
DataProviderTest.java package com.units.mytest.paramter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; public class DataProviderTest { @Test(dataProvider = "methodData") //从methodData这个数据来源中获取数据 public void test1(String name,int age){ System.out.println("test111方法 name=" + name + ";age=" + age); } @Test(dataProvider = "methodData") public void test2(String name,int age){ System.out.println("test222方法 name=" + name + ";age=" + age); } @DataProvider(name = "methodData") //定义一个方法数据 public Object[][] methodDataTest(Method method){ Object[][] result=null; //申明一个对象 //获取的方法是test1时,取以下数据 if (method.getName().equals("test1")){ result = new Object[][]{ {"zhangsan",20}, {"lisi",25} }; } //获取到的方法是test2时,取以下数据 else if (method.getName().equals("test2")){ result = new Object[][]{ {"wangwu", 50}, {"zhaoliu", 60} }; } return result; } }
使用工厂模式管理,即构造一个新的测试类的实例,并执行其所有测试方法,直到所有的测试类的实例都被构造执行。
比如,创建了一个Object数组,长度为5,这5个元素的值都是null,然后把创建好的数组实例的引用赋给obj变量。如果需要为这些元素分配具体的对象,则需要分别指定或用{}符号进行初始化,如下所示:
Object[] obj=new Object[]{new Object(),null,null,null,new String("123")}; //引用类型的数组 或分别指定 obj[0]=new Object();//数组元素在赋对象引用 obj[4]=new String("123");
factory 方法接收类似@Test 和@Before/After 的参数,且必须返回 Object[]。返回的
对象可以是任何类实例(注:对象所在类,不含@xxxx 注解的方法不被执行)。
package unittests; import org.testng.annotations.Test; public class Test16_WebTest { private int m_numberOfTimes; //构造方法 public Test16_WebTest(int numberOfTimes){ m_numberOfTimes = numberOfTimes; } @Test public void testServer(){ for(int i=0; i < m_numberOfTimes; i++){ System.out.println("access the web page" + i); } } }
package unittests; import org.testng.annotations.Factory; import unittests.Test16_WebTest; public class Test16_WebTestFactory { //说明: 附注@Factory 注解的方法中构造某测试类的实例,会自动调用该测试类中带有@Test注解的方法 @Factory public Object[] createInstances(){ //创建了一个数组实例,长度为10,每个数组元素的值均为null,并没有创建10个Object对象,若需要创建10个Object对象,则需要为每个数组元素分别指定或用符号{} Object[] result = new Object[10]; for(int i=0; i < 10; i++){ //数组元素在赋对象引用,实例化数组对象,并执行该实例的所有方法 result[i] = new Test16_WebTest(i * 10); } return result; } }
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="suite" verbose="1"> <test name="MyTest1"> <classes> <class name="unittests.Test16_WebTestFactory" /> </classes> </test> </suite>
[RemoteTestNG] detected TestNG version 6.14.3 access the web page0 access the web page1 access the web page2 access the web page3 access the web page4 access the web page5 access the web page6 access the web page7 access the web page8 access the web page9 access the web page0 access the web page1 ………… access the web page16 access the web page17 access the web page18 access the web page19 =============================================== suite Total tests run: 10, Failures: 0, Skips: 0 ===============================================
Test16_run.java //可以在 java 程序中通过代码来运行TestNG package unittests; import org.testng.TestNG; import unittests.Test16_WebTestFactory; public class Test16_run { public static void main(String[] args){ TestNG testNG = new TestNG(); testNG.setTestClasses(new Class[] {Test16_WebTestFactory.class}); testNG.run(); } }
直接在编辑器中运行Test16_run.java,即可以得到与4一样的结果
6、@Factory 也可以配合 dataprovider 使用,实现参数化
Test17_WebTestFactory.java //@Factory 也可以配合 data provider 使用,可用于构造器或者普通方法。 package unittests; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import unittests.Test16_WebTest; public class Test17_WebTestFactory { @Factory(dataProvider = "dp") public Object[] createInstances(int n){ Object[] result = new Object[n]; for(int i=0; i < n; i++){ result[i] = new Test16_WebTest(i * 10); } return result; } @DataProvider public Object[][] dp() { return new Object[][]{ new Object[] { 10 }, new Object[] { 20 }, }; } }
access the web page88 access the web page89 =============================================== suite Total tests run: 30, Failures: 0, Skips: 0 ===============================================
Test18.java package unittests; import org.testng.annotations.Test; @Test public class Test18 { public void test1() { System.out.println("access the test1"); } public void test2(){ System.out.println("access the test2"); } }
[RemoteTestNG] detected TestNG version 6.14.3 access the test1 access the test2 PASSED: test1 PASSED: test2 =============================================== Default test Tests run: 2, Failures: 0, Skips: 0 ===============================================
运行结果:test1,test2 都被执行了,也就是说类级别的@Test 注解会把该类的所有
方法都当作测试方法,不管是否有注解。这种情况下,依旧可为单个类方法进行注解以添加
其他属性,比如归属的组别。
MultiThreadOnAnnotion.java package com.units.mytest.multiThread; import org.testng.annotations.Test; public class MultiThreadOnAnnotion { /* invocationCount----表示所有线程总共执行的次数 threadPoolSize-----表示线程池的内线程的个数 timeOut-------超时时间-毫秒*/ @Test(invocationCount = 10,threadPoolSize = 3,timeOut = 1000) public void test(){ System.out.println(1); System.out.printf("Thread Id : %s%n",Thread.currentThread().getId()); } }
=============================================== Default Suite Total tests run: 10, Failures: 0, Skips: 0 ===============================================
MultiThreadOnXml.java package com.units.mytest.multiThread; import org.testng.annotations.Test; public class MultiThreadOnXml { //打印出当前方法的线程id @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()); } }
在resources中新建multiThread.xml,如下
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <!-- parallel是指多线程级别,这里是方法级别的多线程;thread-count:并发的多线程数,这里是2 --> <!-- methods级别:所有用例都可以在不同的线程下去执行 xml文件配置这种方式不能指定线程池,只有方法上才可以指定线程池--> <suite name="thread" parallel="methods" thread-count="2"> <test name="demo1"> <classes> <class name="com.units.mytest.multiThread.MultiThreadOnXml"/> </classes> </test> </suite>
multiThread.xml运行结果为
以上是将所有用例,分配给两个线程同时执行。
相同的test tag下的用例只能在同一个线程中去执行。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <!-- tests级别:不同的test tag下的用例可以在不同的线程下执行 相同的test tag下的用例只能在同一个线程中去执行 classs级别:相同的class tag 下的用例在同一个线程中执行 不同的class tag 下的用例可以在不同的线程中执行 methods级别:所有用例都可以在不同的线程下去执行 thread-count:代表了最大并发线程数 xml文件配置这种方式不能指定线程池,只有方法上才可以指定线程池 --> <suite name="thread" parallel="tests" thread-count="2"> <test name="demo1"> <classes> <class name="com.units.mytest.multiThread.MultiThreadOnXml"/> </classes> </test> </suite>
xml运行结果为
虽然这里分配了两个线程,但因只有一个test标签,所以只启用一个线程执行。
<class name="com.units.mytest.multiThread.MultiThreadOnXml"/>
)下的用例在同一个线程中执行;<suite name="thread" parallel="classes" thread-count="3"> <test name = "demo1"> <classes > <!--这里有两个class标签,同一个class标签里的所有用例,在同一个线程里执行--> <class name="com.units.mytest.multiThread.MultiThreadOnXml"/> <class name="com.units.mytest.BasicAnnotation"/> </classes> </test> </suite>
执行结果为:
beforeClass这是在类运行之前运行的方法 Thread Id : 11BeforeMethon这是在测试方法之前运行的 这是测试用例1 Thread Id : 12 AfterMethod这是在测试方法之后运行的 Thread Id : 11BeforeMethon这是在测试方法之前运行的 这是测试用例2 Thread Id : 12 AfterMethod这是在测试方法之后运行的 Thread Id : 11 afterClass这是在类运行之后运行的方法 AfterSuite测试套件,在当前测试套件下所有类运行结束之后运行一次,包含该套件下所有类 =============================================== thread Total tests run: 5, Failures: 0, Skips: 0 ===============================================
TimeOutTest.java package com.units.mytest; import org.testng.annotations.Test; public class TimeOutTest { @Test(timeOut = 3000)//单位为毫秒值 public void testSuccess() throws InterruptedException { Thread.sleep(2000); //等待2s } @Test(timeOut = 2000) //throws InterruptedException:在当前方法抛出中断异常,如有的话 public void testFailed() throws InterruptedException { Thread.sleep(3000); } }
在idea中创建testNG的工程,运行结束不会生产test-output目录和生成测试报告,原因是在运行配置中,没有勾选use Default reporters
2、在左侧选择要设置运行的测试脚本,在左侧选择Configuration的Listeners项,勾选use default reporters前的选择框打上对号,然后点击ok,重新运行test,就会生产test-output文件了。(可针对某个测试脚本的运行输出测试报告,其他不设置的不输出报告)
如下:
ReportNg测试报告展示
ExtentReport测试报告效果(深度报告)
package com.tester.extend.demo; import org.testng.Assert; import org.testng.Reporter; import org.testng.annotations.Test; public class TestMeThodsDemo { @Test public void test1(){ Assert.assertEquals(1,2); } @Test public void test2(){ Assert.assertEquals(1,1); } @Test public void test3(){ Assert.assertEquals("aaa","aaa"); } @Test public void logDemo(){ Reporter.log("这是我们自己写的日记"); //报告日志 throw new RuntimeException("这是我们自己的运行时异常"); } }