# AUTOTEST **Repository Path**: peter-hill/autotest ## Basic Information - **Project Name**: AUTOTEST - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-08-10 - **Last Updated**: 2021-10-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AUTOTEST ## TestNG > [官方文档](https://testng.org/doc/documentation-main.html#):+1: ### 介绍 > TestNG是一个测试框架,旨在简化广泛的测试需求,从单元测试(测试一个与其他类隔离的类)到集成测试(测试由几个类、几个包、甚至几个外部框架组成的整个系统,如应用服务器)。 > > 编写一个测试通常是一个三步的过程: > > 1. 编写你的测试的业务逻辑并在你的代码中插入TestNG注解。 > 2. 在testng.xml文件或build.xml中添加关于你的测试的信息(例如,类名,你希望运行的组,等等...)。 > 3. 运行TestNG。 > ### 基本注解 * @Test `标记一个类或一个方法作为测试的一部分。` * @BeforeSuite `被注释的方法将在这个套件的所有测试运行之前被运行。` * @AfterSuite `注释的方法将在这个套件的所有测试都运行后运行。` * @BeforeClass `注释的方法将在当前类中的第一个测试方法被调用之前被运行。` * @AfterClass `注释的方法将在当前类中的所有测试方法运行后被运行。` * @BeforeGroups `这个配置方法将在之前运行的组的列表。该方法保证在第一个属于这些组的测试方法被调用前不久运行。` * @AfterGroups `这个配置方法将在之后运行的组的列表。该方法保证在最后一个属于这些组的测试方法被调用后不久运行。` * @BeforeMethod `注释的方法将在每个测试方法之前运行。` * @AfterMethod `注释的方法将在每个测试方法之后运行。` * @BeforeTest `注释的方法将在任何属于标签内的类的测试方法运行之前被运行。` * @AfterTest ` 注释的方法将在所有属于标签内的类的测试方法运行后被运行。 ` * @DataProvider `标记一个方法为一个测试方法提供数据。被注解的方法必须返回一个Object[][],其中每个Object[]可以被分配给测试方法的参数列表。想要从这个DataProvider中接收数据的@Test方法需要使用一个与这个注解的名称相等的DataProvider名称。` * @Parameters `描述了如何向@Test方法传递参数。` * @Factory `标记一个方法为工厂,返回将被TestNG作为测试类使用的对象。该方法必须返回Object[]。` * @Listeners `在一个测试类上定义监听器。` ### 注解的简单应用 ```java public class BasicAnnoation { // Marks a class or a method as part of the test. @Test public void testCase1(){ System.out.println("这是一个测试用例"); } @Test public void testCase2(){ System.out.println("这是一个测试用例"); } // The annotated method will be run before each test method @BeforeMethod public void beforeMethod(){ System.out.println("before method"); } // The annotated method will be run after each test method. @AfterMethod public void afterMethod(){ System.out.println("after method"); } // The annotated method will be run before all tests in this suite have run. @BeforeSuite public void beforeSuite(){ System.out.println("before Suite"); } // The annotated method will be run after all tests in this suite have run. @AfterSuite public void afterSuite(){ System.out.println("After Suite"); } // The annotated method will be run before the first test method in the current class is invoked. @BeforeClass public void beforeClass(){ System.out.println("before Class"); } // The annotated method will be run after all the test methods in the current class have been run. @AfterClass public void afterClass(){ System.out.println("after Class"); } } ``` 注意观察各个方法的执行顺序 ```sh before Suite before Class before method 这是一个测试用例 after method before method 这是一个测试用例 after method after Class After Suite =============================================== Default Suite Total tests run: 2, Failures: 0, Skips: 0 =============================================== ``` ### 套件测试 1. 在套件测试包下新建登录、支付、配置类 2. 新建套件测试XML配置文件,由XML控制执行组合 登录测试类 ```java import org.testng.annotations.Test; public class LoginTest { @Test public void LoginIn(){ System.out.println("登录成功"); } } ``` 支付测试类 ```java import org.testng.annotations.Test; public class PayTest { @Test public void PayWe(){ System.out.println("支付成功"); } } ``` 套件配置类 ```java import org.testng.annotations.*; public class SuiteConfig { @BeforeSuite public void beforeSuite(){ System.out.println("before suite runned"); } @AfterSuite public void afterSuite(){ System.out.println("after siute runned"); } // The annotated method will be run before each test method @BeforeTest public void beforeMethod(){ System.out.println("before method"); } // The annotated method will be run after each test method. @AfterTest public void afterMethod(){ System.out.println("after method"); } } ``` XML配置文档 ```xml ``` ```shell before suite runned before method 登录成功 after method before method 支付成功 after method after siute runned =============================================== test Total tests run: 2, Failures: 0, Skips: 0 =============================================== ``` ### 分组测试 #### 在代码块内配置 1. 在`@Test`注解里加参数groups声明当前方法或者当前类是哪个分组的,使用@BeforeGroups和@AfterGroups时传入分组名,这些在分组之前or之后运行的方法就能在对应的分组前后运行 ```java package com.course.testng.groups; import org.testng.annotations.*; @Test(groups = {"stu"}) public class GroupOnMethond { @Test(groups = {"server"}) public void test1(){ System.out.println("服务组1"); } @Test(groups = {"server"}) public void test2(){ System.out.println("服务组2"); } @Test(groups = {"client"}) public void test3(){ System.out.println("客户组3"); } @Test(groups = {"client"}) public void test4(){ System.out.println("客户组4"); } @BeforeGroups({"server","client"}) public void beforeGroupsServer(){ System.out.println("服务、客户组之前"); } @AfterGroups("server") public void afterGroupsServer(){ System.out.println("服务组之后"); } } ``` ```shell 服务、客户组之前 服务组1 服务组2 服务组之后 服务、客户组之前 客户组3 客户组4 =============================================== Default Suite Total tests run: 4, Failures: 0, Skips: 0 =============================================== Process finished with exit code 0 ``` #### 在XML中配置 **目录结构** ![qafws9](https://gitee.com/peter-hill/upic/raw/master/uPic/qafws9.png) * [GroupOnMethond](# 在代码块内配置) * GroupsOnClass1 ```java package com.course.testng.groups; import org.testng.annotations.Test; @Test(groups = "stu") public class GroupsOnClass1 { public void stu1(){ System.out.println("class1 stu1 run"); } public void stu2(){ System.out.println("class1 stu2 run"); } } ``` * GroupsOnClass2 ```java package com.course.testng.groups; import org.testng.annotations.Test; @Test(groups = "stu") public class GroupsOnClass2 { public void stu1(){ System.out.println("class2 stu1 run"); } public void stu2(){ System.out.println("class2 stu2 run"); } } ``` * GroupsOnClass3 ```java package com.course.testng.groups; import org.testng.annotations.Test; @Test(groups = "teacher") public class GroupsOnClass3 { public void teacher1(){ System.out.println("class3 teacher1 running"); } public void teacher2(){ System.out.println("class3 teacher2 running"); } } ``` ```xml ``` --- * 观察上方配置文件,下面执行结果中的执行顺序为test节点为runAll的所有class,test节点为onlyrunstudents的只执行了groups为stu的class ```shell class1 stu1 run class1 stu2 run class2 stu1 run class2 stu2 run class3 teacher1 running class3 teacher2 running 服务、客户组之前 服务组1 服务组2 服务组之后 服务、客户组之前 客户组3 客户组4 class1 stu1 run class1 stu2 run class2 stu1 run class2 stu2 run =============================================== suitename Total tests run: 14, Failures: 0, Skips: 0 =============================================== Process finished with exit code 0 ``` ### 忽略(禁用)测试 * 如下代码所示,注解`@Test`中的enable传参为`false`的时候,当前测试节点就会被忽略,执行时会跳过当前测试节点,类似与jmeter中的禁用,默认为`true` ```java package com.course.testng; import org.testng.annotations.Test; 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 执行"); } } ``` ### 异常测试 * 异常测试是我们的预期结果为某个异常时,例如:调用接口时传入异常参数报错异常。也可以参考我在网上找的这篇[文章](https://www.jianshu.com/p/cfadce256c08)来理解 *** ```java package com.course.testng; import org.testng.annotations.Test; public class ExpectedException { /** * 期望结果为某个异常时 */ @Test(expectedExceptions = RuntimeException.class) public void runTimeExceptionFailed(){ System.out.println("exception test failed"); } @Test(expectedExceptions = RuntimeException.class) public void runTimeExceptionSuccess(){ System.out.println("exception test success"); throw new RuntimeException(); } } ``` * 如下运行结果所示,该抛出异常时却没有抛出异常,记为测试用例执行失败 ```shell exception test failed org.testng.TestException: Method ExpectedException.runTimeExceptionFailed()[pri:0, instance:com.course.testng.ExpectedException@c39f790] should have thrown an exception of type class java.lang.RuntimeException at org.testng.internal.ExpectedExceptionsHolder.noException(ExpectedExceptionsHolder.java:80) at org.testng.internal.Invoker.considerExceptions(Invoker.java:1130) at org.testng.internal.Invoker.invokeMethod(Invoker.java:603) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:707) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:979) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) at org.testng.TestRunner.privateRun(TestRunner.java:648) at org.testng.TestRunner.run(TestRunner.java:505) at org.testng.SuiteRunner.runTest(SuiteRunner.java:455) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415) at org.testng.SuiteRunner.run(SuiteRunner.java:364) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1187) at org.testng.TestNG.runSuitesLocally(TestNG.java:1116) at org.testng.TestNG.runSuites(TestNG.java:1028) at org.testng.TestNG.run(TestNG.java:996) at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66) at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109) exception test success =============================================== Default Suite Total tests run: 2, Failures: 1, Skips: 0 =============================================== Process finished with exit code 0 ``` ### 依赖测试 * 顾名思义就是在下一个测试节点执行时依赖上一个测试节点的成功执行,所依赖的对象可以是一个、多个方法,也可以是一个、多个组。即dependsOnGroups, dependsOnMethods都可以作为依赖对象传入 ```java package com.course.testng; import org.testng.annotations.Test; public class DependTest { @Test public void test1(){ System.out.println("test1"); throw new RuntimeException(); } @Test(dependsOnMethods = {"test1"}) public void test2(){ System.out.println("test2"); } } ``` * 可以看到当依赖的对象异常时,当前测试节点会自动跳过 ```shell l test1 java.lang.RuntimeException at com.course.testng.DependTest.test1(DependTest.java:9) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124) at org.testng.internal.Invoker.invokeMethod(Invoker.java:571) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:707) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:979) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) at org.testng.TestRunner.privateRun(TestRunner.java:648) at org.testng.TestRunner.run(TestRunner.java:505) at org.testng.SuiteRunner.runTest(SuiteRunner.java:455) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415) at org.testng.SuiteRunner.run(SuiteRunner.java:364) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1187) at org.testng.TestNG.runSuitesLocally(TestNG.java:1116) at org.testng.TestNG.runSuites(TestNG.java:1028) at org.testng.TestNG.run(TestNG.java:996) at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66) at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109) Test ignored. =============================================== Default Suite Total tests run: 2, Failures: 1, Skips: 1 =============================================== Process finished with exit code 0 ``` ### 参数化测试 ```java package com.course.testng.parameter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; public class DataProviderTest { @Test(dataProvider = "data") public void dataProviderTest(String name, int age){ System.out.println(name + " " + age); } @DataProvider(name="data") public Object[][] providerData() { Object[][] p = new Object[][]{ {"zhansan", 20}, {"lisi", 19}, {"wangw", 21} }; return p; } // 通过方法实现测试数据 @Test(dataProvider = "methodData") public void test1(String name, int age){ System.out.println(name + " " + age); } @Test(dataProvider = "methodData") public void test2(String name, int age){ System.out.println(name + " " + age); } @DataProvider(name = "methodData") public Object[][] methodDataTest(Method method){ Object[][] result; if (method.getName().equals("test1")){ result = new Object[][]{ {"zhangsna",20}, {"lisi", 49} }; return result; } if (method.getName().equals("test2")){ result = new Object[][]{ {"wangwu",20}, {"sunliu", 49} }; return result; } return null; } } ``` ```shell zhansan 20 lisi 19 wangw 21 zhangsna 20 lisi 49 wangwu 20 sunliu 49 =============================================== Default Suite Total tests run: 7, Failures: 0, Skips: 0 =============================================== Process finished with exit code 0 ``` ```java package com.course.testng.parameter; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ParameterTest { @Test @Parameters({"name", "age"}) public void parameterTest(String name, int age){ System.out.println(name + " " + age); } } ``` ```xml ``` ### 多线程测试 ```java import org.testng.annotations.Test; public class MultiThreadOnAnnoation { @Test(invocationCount = 10, threadPoolSize = 2) public void test(){ System.out.println(1); System.out.printf("Thread Id : %s%n", Thread.currentThread().getId()); } } ``` ```java import org.testng.annotations.Test; public class MultiThreadOnXml { @Test public void test1(){ System.out.println(1); System.out.printf("Thread Id : %s%n", Thread.currentThread().getId()); } @Test public void test2(){ System.out.println(2); System.out.printf("Thread Id : %s%n", Thread.currentThread().getId()); } @Test public void test3(){ System.out.println(3); System.out.printf("Thread Id : %s%n", Thread.currentThread().getId()); } @Test public void test4(){ System.out.println(4); System.out.printf("Thread Id : %s%n", Thread.currentThread().getId()); } } ``` ```xml ``` ### 超时测试 ```java import org.testng.annotations.Test; public class TimeOutTest { @Test(timeOut = 3000)//单位为毫秒值 public void testSuccess() throws InterruptedException { Thread.sleep(2000); } @Test(timeOut = 2000) public void testFailed() throws InterruptedException { Thread.sleep(3000); } } ``` ```shell org.testng.internal.thread.ThreadTimeoutException: Method com.course.testng.TimeOutTest.testFailed() didn't finish within the time-out 2000 at java.util.concurrent.FutureTask.setException(FutureTask.java:250) at java.util.concurrent.FutureTask.run(FutureTask.java:271) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) =============================================== Default Suite Total tests run: 2, Failures: 1, Skips: 0 =============================================== Process finished with exit code 0 ```