【一:实战开发testng的介绍】

目录

1、主要内容

1.1、为啥要做接口测试

  • 更容易实现持续集成
  • 自动化测试落地性价比更高,比UI更稳定
  • 大型系统更多更复杂,系统间模块越来越多
  • BUG更容易定位
  • 降低研发成本,提高效率

1.2、接口自动化测试落地过程

需求阶段 项目立项,产品设计,需求文档
研发阶段 UI设计、前端开发,后端开发,测试设计,测试开发
测试阶段 环境搭建,多项测试执行,BUG修复,测试报告
项目上线 显示回归测试,上线报告,添加监控

1.3、接口测试范围

1.4、手工接口常用的工具

  • postman(Chrome)
  • httpRequest
  • fiddler
  • jemter(统计结果不完善,倾向于性能测试)

1.5、自动化框架的设计

2、testng自动化测试框架

  1. @test:最基本的注解,用来把方法标记为测试的一部分
  2. @BeforeMethod: 测试方法之前运行的方法
  3. @AfterMethod:测试方法之后运行的方法
  4. @BeforeClass: 指的是在类运行之前运行的方法
  5. @AfterClass:指的是在类运行之后运行的方法
  6. @BeforeTest:多个测试类的集合,在设定好的测试集合前运行的方
  7. @AfterTest:多个测试类的集合,在设定好的测试集合后运行的方法
  8. @ BeforeSuite: 测试套件,在类运行之前运行的方法:
  9. @ AfterSuite: 测试套件,在类运行之后运行的方法
  10. @Test(dependsOnMethods = {"test1"}):依赖测试,在执行次方法之前执行test1方法之前
  11. 1@Test(expectedExceptions = RuntimeException.class):异常测试,方法里面要抛出异常throw new RuntimeException();,否则会是一个失败的异常测试
  12. @Test(enabled = true):忽略测试
  13. @Test(timeOut = 2000):超时测试
  14. @Test(invocationCount = 10,threadPoolSize = 3),多线程测试,一般用xml配置

总结:testng的annotations运行顺序为:
@BeforeSuite>@BeforeTest>@BeforeClass>@BeforeMethod>@test>@AfterMethod>@AfterClass>@AfterTest>@AfterSuite

基本测试

1、基本注解

java 复制代码
import org.testng.annotations.*;
public class BasicAnnotation {

    //最基本的注解,用来把方法标记为测试的一部分
    @Test
    public void testCase1(){
        System.out.printf("Thread Id : %s%n",Thread.currentThread().getId());
        System.out.println("Test这是测试用例1");
    }

    @Test
    public void testCase2(){
        System.out.printf("Thread Id : %s%n",Thread.currentThread().getId());
        System.out.println("Test这是测试用例2");
    }

    @BeforeMethod
    public void beforeMethod(){
        System.out.println("BeforeMethod这是在测试方法之前运行的");
    }

    @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测试套件");
    }
}

2、忽略测试

xml 复制代码
public class IgnoreTest {

    @Test(enabled = false)
    public void ignore2(){
        System.out.println("ignore2 执行");
    }

    @Test(enabled = true)
    public void ignore3(){
        System.out.println("ignore3 执行");
    }
}

3、依赖测试

依赖测试,被依赖测测试方法必须成功,不能失败,失败的话会不成功

复制代码
public class DependTest {

    @Test
    public void test1(){
        System.out.println("test1 run");
        throw new RuntimeException();
    }

    @Test(dependsOnMethods = {"test1"}) //执行前依赖于test1()
    public void test2(){
        System.out.println("test2 run");
    }

}

4、超时测试

xml 复制代码
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);
    }
}

5、异常测试

java 复制代码
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();
    }

}


6、通过xml文件参数测试

java 复制代码
public class ParamterTest {

    @Test
    @Parameters({"name","age"})
    public void paramTest1(String name,int age){
        System.out.println("name = " + name + ";  age = " + age);
    }
}
java 复制代码
<?xml version="1.0" encoding="UTF-8" ?>

<suite name="parameter">
    <test name="param">
        <classes>
            <parameter name="name" value="zhangsan"/>
            <parameter name="age" value="10"/>
            <class name="com.course.testng.paramter.ParamterTest"/>
        </classes>
    </test>

</suite>


7、通过data实现数据驱动

java 复制代码
public class DataProviderTest {
    @DataProvider(name="data")
    public Object[][] providerData(){
        Object[][] o = new Object[][]{
                {"zhangsan",10},
                {"lisi",20},
                {"wangwu",30}
        };
        return o;
    }

    @Test(dataProvider = "data")
    public void testDataProvider(String name,int age){
        System.out.println("name =" + name +"; age=" + age);
    }

}
java 复制代码
public class DataProviderTest {

    @DataProvider(name="methodData")
    public Object[][] methodDataTest(Method method){
        Object[][] result=null;
        if(method.getName().equals("test1")){
            result = new Object[][]{
                    {"zhangsan",20},
                    {"lisi",25}
            };
        }else if(method.getName().equals("test2")){
            result = new Object[][]{
                    {"wangwu",50},
                    {"zhaoliu",60}
            };
        }

        return result;
    }


    @Test(dataProvider = "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);
    }


}

2.1、suit套件测试(按类分)

上述内容大家基本都了解,而在实际使用中我们再配合套件时,需要注意:
假设现在有如图所示项目:

  • LogInTest类:登录测试类;
java 复制代码
public class LoginTest {
    @Test
    public void loginTaoBao(){
        System.out.println("淘宝登陆成功");
    }
}
  • ParTest类:支付测试类;
java 复制代码
public class PayTest {
    @Test
    public  void paySuccess(){
        System.out.println("支付宝支付成功");
    }
}
  • SuiteConfig类:套件配置类;
java 复制代码
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");
    }
}
  • suite.xml:套件xml文件
xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<suite name="test">
    <test name="login"> <!--名字自定义-->
        <classes>
            <class name="com.course.testng.suite.SuiteConfig"/>
            <class name="com.course.testng.suite.LoginTest"/>
        </classes>
    </test>
    <test name="pay"> <!--名字自定义-->
        <classes>
            <class name="com.course.testng.suite.SuiteConfig"/>
            <class name="com.course.testng.suite.PayTest"/>
        </classes>
    </test>
</suite>



我们期望实现的是通过xml文件运行整个项目
](https://img-blog.csdnimg.cn/e741c9f6165d42d5bfe59563d72860b3.png))
登录类内容

](https://img-blog.csdnimg.cn/dfe5b5e7d057438eb5abe94a299a9677.png))
支付类内容
](https://img-blog.csdnimg.cn/5148935f37cf49fcb86ed37d9214d06e.png))
套件配置类内容
](https://img-blog.csdnimg.cn/2fdbc6fd61884bdf8fd1e3c4ba82cb53.png))
xml文件内容,xml的内容配置在resources下
](https://img-blog.csdnimg.cn/1bdd3453d2fc45ce9453141b1a7836ee.png))
点击对应的xml,右键,实际运行结果如下:
](https://img-blog.csdnimg.cn/08a9c2ad04004e869d4f65e19b662ee6.png))

2.2、分组测试(按方法分组,也可以分开写)

2.2.1、在class文件中分组

java 复制代码
public class GroupsOnMethod {
    @Test(groups = "server")
    public void test1(){
        System.out.println("这是服务端组的测试方法1111");
    }

    @Test(groups = "server")
    public void test2(){
        System.out.println("这是服务端组的测试方法2222");
    }

    @Test(groups = "client")
    public void test3(){
        System.out.println("这是客户端组的测试方法3333");
    }
    @Test(groups = "client")
    public void test4(){
        System.out.println("这是客户端组的测试方法4444");
    }

    @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("这是客户端组运行之后运行的方法!!!!!");
    }

}

2.2.2、使用xml文件分组

2.2.1、@Test(groups = "stu")组


2.2.2、@Test(groups = "teacher")组

2.2.3、分组的配置文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<suite name="suitename">
    <test name="runAll">
        <classes>
            <class name="com.course.testng.groups.GroupsOnClass1"/>
            <class name="com.course.testng.groups.GroupsOnClass2"/>
            <class name="com.course.testng.groups.GroupsOnClass3"/>
        </classes>
    </test>

    <test name="onlyRunStu">
        <groups>
            <run>
                <include name="stu"/>
            </run>
        </groups>

        <classes>
            <class name="com.course.testng.groups.GroupsOnClass1"/>
            <class name="com.course.testng.groups.GroupsOnClass2"/>
            <class name="com.course.testng.groups.GroupsOnClass3"/>
        </classes>

    </test>
</suite>


2.2.4、现在对应的xml,右键,查看运行结果

2.3、多线程运行(注解的方式配置)

2.3.1、通过注解的方式实现三个线程池运行里随机运行10次方法

java 复制代码
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());
    }

}

运行结果

2.4、多线程运行(在xml里面配置)

java 复制代码
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());
    }

}
xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<suite name="thread" parallel="methods" thread-count="3">
    <!--
    tests级别:不同的test tag下的用例可以在不同的线程下执行
            相同的test tag下的用例只能在同一个线程中去执行
    classs级别:相同的class tag 下的用例在同一个线程中执行
                不同的class tag 下的用例可以在不同的线程中执行
    methods级别:所有用例都可以在不同的线程下去执行

    thread-count:代表了最大并发线程数

    xml文件配置这种方式不能指定线程池,只有方法上才可以指定线程池
    -->
    <test name = "demo1">
        <classes name="d">
            <class name="com.course.testng.multiThread.MultiThreadOnXml"/>
            <class name="com.course.testng.BasicAnnotation"/>
            <class name="com.course.testng.multiThread.MultiThreadOnXml"/>
        </classes>
        <classes name="d1">
            <class name="com.course.testng.multiThread.MultiThreadOnXml"/>
            <class name="com.course.testng.BasicAnnotation"/>
            <class name="com.course.testng.multiThread.MultiThreadOnXml"/>
        </classes>

    </test>

    <test name = "demo2">
        <classes name="d3">
            <class name="com.course.testng.BasicAnnotation"/>
        </classes>

    </test>



</suite>

xml文件配置这种方式不能指定线程池,只有方法上才可以指定线程池
运行结果;

相关推荐
带刺的坐椅几秒前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看1 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程2 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t2 小时前
ZIP工具类
java·zip
lang201509282 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan3 小时前
第10章 Maven
java·maven
百锦再3 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说3 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多4 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再4 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven