01 TestNG更适合测试人员使用

  1. TestNG适合测试人员的原因:
  2. 1,比junit涵盖功能更全面的测试框架
  3. 2Junit更适合隔离性比较强的单元测试
  4. 3TestNG更适合复杂的集成测试

02 TestNG实战在idea中创建module

步骤:

  1. 拉取git上的目录下来,在idea打开
  2. 创建一个module,maven的项目文件

image-20211204122734804.png

03 注解实战@Test标签

使用过程中,@Test在alt+enter安装的时候总是出现下面的问题。其实在安装跳出的弹窗,选择安装对应的插件到所在项目的目录下就行了
然后安装就没问题了
image-20211205121712889.png

04 注解实战BeforeMethod和AfterMethod

BeforeMethod是方法之前运行的,AfterMethod是方法之后运行的。而且这两个在每个方法运行之前之后都会运行一次

05 注解实战BeforeClass和AfterClass

BeforeClass和AfterClass的应用场景:类运行前注册对象,静态方法,变量赋值等

06 注解实战BeforeSuite和AfterSuite

BeforeSuite是在BeforeClass前运行的,
AfterSuite是在AfterClass后运行的

应用场景:suite可以包含多个class,类应该属于某个测试套件之下

03-06实例演示

package com.course.testng;

import org.testng.annotations.*;

public class BasicAnnotation {

    //最基本的注解,用来把方法标记为测试的一部分
    @Test
    public  void testCase1(){
        System.out.println("testCase-1这是Testcase1的测试");
    }

    @Test
    public  void testCase2(){
        System.out.println("testCase-2这是Testcase1的测试");
    }

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

}

执行结果


BeforeSuite-测试套件
beforeClass-这是在类运行之前运行的
beforeMethod-这是在测试方法之前运行的
testCase-1这是Testcase1的测试
afterMethod-这是在测试方法之后运行的
beforeMethod-这是在测试方法之前运行的
testCase-2这是Testcase1的测试
afterMethod-这是在测试方法之后运行的
afterClass-这是在类运行之后运行的
afterSuite-测试套件

===============================================
Default Suite
Total tests run: 2, Passes: 2, Failures: 0, Skips: 0
===============================================


Process finished with exit code 0

07 套件测试

suite.xml

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="test">
    <test name="login">
        <classes>
            <class name="com.course.testng.suite.SuiteConfig"></class>
            <class name="com.course.testng.suite.LoginTest"></class>
        </classes>
    </test>

    <test name="pay">
        <classes>
            <class name="com.course.testng.suite.SuiteConfig"></class>
            <class name="com.course.testng.suite.PayTest"></class>
        </classes>
    </test>

</suite>

SuiteConfig.java (共有的套件文件)

package com.course.testng.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("beforeSuite运行了");
    }
    @AfterSuite
    public void afterSuite(){
        System.out.println("afterSuite运行了");
    }

    @BeforeTest
    public void beforeTest(){
        System.out.println("beforeTest开始运行了");
    }
    @AfterTest
    public void afterTest(){
        System.out.println("afterTest开始运行了");
    }
}

LoginTest.Java (逻辑控制的类-写测试主要的@Test标签下包含的方法)

package com.course.testng.suite;

import org.testng.annotations.Test;

//逻辑控制的类-写测试主要的@Test标签下包含的方法
public class LoginTest {

    @Test
    public void loginSuccess(){
        System.out.println("淘宝登录成功");
    }
}

PayTest.java

package com.course.testng.suite;

import org.testng.annotations.Test;

public class PayTest {

    @Test
    public void paySuccess(){
        System.out.println("支付宝支付成功");
    }
}

运行效果

beforeSuite运行了
beforeTest开始运行了
淘宝登录成功
afterTest开始运行了
beforeTest开始运行了
支付宝支付成功
afterTest开始运行了
afterSuite运行了

===============================================
test
Total tests run: 2, Passes: 2, Failures: 0, Skips: 0
===============================================

08 忽略测试

enabled = false 不被执行

@Test(enabled = false)

package com.course.testng;

import org.testng.annotations.Test;

public class IgnoreTest {

    @Test
    public void ignore1(){
        System.out.println("ignore1被执行了!!");
    }
    //enabled = false 不被执行
    @Test(enabled = false)
    public void ignore2(){
        System.out.println("ignore2被执行了!!");
    }
}

09 组测试中的方法分组测试

貌似testNG 7.0版本后组就有问题,要换版本,到时候在重新看看。

https://coding.imooc.com/learn/questiondetail/8QVD563JGKZXN4Ez.html (已经解决)

package com.course.testng.groups;

import org.testng.annotations.AfterGroups;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;

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

}

目前我的testNG是7.1版本

image-20211205170140269.png

所以运行的结果是:【后面回来再重新检查下,改下版本运行看看了】

这是服务端组测试方法11111
这是服务端组测试方法22222
这是客户端组测试方法33333
这是客户端组测试方法44444

===============================================
Default Suite
Total tests run: 4, Passes: 4, Failures: 0, Skips: 0
===============================================

原先自动安装了依赖包。

只要将maven安装依赖包的仓库将…\apache-maven-3.6.3\repository\org\testng 目录删除,然后pom.xml上输入要安装的版本。

<dependencies>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.10</version>
    </dependency>
</dependencies>

之后再clean一下

05测试框架TestNG - 图4

10 组测试中的类分组测试

目录

image-20211213230528189.png

GroupsOnClass1.java

package com.course.testng.groups;

import org.testng.annotations.Test;

@Test(groups = "stu")
public class GroupsOnClass1 {
    public void stu1(){
        System.out.println("这个是GroupsOnClass1的stu1111正在运行.....");
    }
    public void stu2(){
        System.out.println("这个是GroupsOnClass1的stu2222正在运行.....");
    }
}

GtoupsOnClass2.java

package com.course.testng.groups;

import org.testng.annotations.Test;

@Test(groups = "stu")
public class GtoupsOnClass2 {
    public void stu1(){
        System.out.println("这个是GroupsOnClass222的stu1111正在运行~~~~~");
    }
    public void stu2(){
        System.out.println("这个是GroupsOnClass22222的stu2222正在运行~~~~~");
    }
}

GtoupsOnClass3.java

package com.course.testng.groups;

import org.testng.annotations.Test;

@Test(groups = "teacher")
public class GtoupsOnClass3 {
    public void teacher1(){
        System.out.println("这个是GroupsOnClass333的teacher1正在运行!!!!!");
    }
    public void teacher2(){
        System.out.println("这个是GroupsOnClass222的teacher2正在运行!!!!!");
    }
}

groupsOnClass.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.GtoupsOnClass2"/>
            <class name="com.course.testng.groups.GtoupsOnClass3"/>
        </classes>
    </test>
    <!--   只是运行学生的-->
    <test name="runStu">
        <groups>
            <run>
                <include name="stu"/>
            </run>
        </groups>
        <classes>
            <class name="com.course.testng.groups.GroupsOnClass1"/>
            <class name="com.course.testng.groups.GtoupsOnClass2"/>
            <class name="com.course.testng.groups.GtoupsOnClass3"/>
        </classes>
    </test>

</suite>

11 异常测试

什么时候会用到异常测试?
在我们期望结果为一个异常的时候。比如:我们传入了某些不合法的参数,程序抛出了异常
也就是我们的预期结果就是这个异常

package com.course.testng;


import org.testng.annotations.Test;

/*
    异常测试
 */
public class ExpectExction {

    //这是一个失败的异常测试
    @Test(expectedExceptions = RuntimeException.class)
    public  void runTimeExceptionFailed() {
        System.out.println("这是一个失败的异常测试");
    }

    //这是一个成功的异常测试
    @Test(expectedExceptions = RuntimeException.class)
    public  void runTimeExceptionSuccess() {
        System.out.println(" 这是一个成功的异常测试 ");
        throw new RuntimeException();

    }
}

12 依赖测试

依赖测试出现的场景:
例如:test2方法依赖test1方法 应用标签:@Test(dependsOnMethods={“test1”})
如果test1失败了,则test2方法则被忽略

package com.course.testng.groups;

import org.testng.annotations.Test;

public class DependTest {

    @Test
    public void test1(){
        System.out.println("test 1 runnnnn");
    }
    //test1成功,则执行test2就都执行
    @Test(dependsOnMethods = {"test1"})
    public void test2(){
        System.out.println("test 2 runnnnn");
    }

    @Test
    public void test3(){
        System.out.println("test 3 runnnnn");
        throw new RuntimeException();
    }
    //test3执行失败,则执行test4不执行,被忽略掉
    //场景,例如要先登录才能进行下一步操作的时候,可以用到这种场景
    @Test(dependsOnMethods = {"test3"})
    public void test4(){
        System.out.println("test 4 runnnnn");
    }
}

13 参数化测试-xml文件参数化

Java文件—-ParameterTest.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 paramTest1(String name,int age){
        System.out.println("name="+name+",age="+age);
    }

}

xml文件—-Paramter.xml

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="parameter">
    <test name="param">
        <classes>
            <parameter name="name" value="江zhuoh"/>
            <parameter name="age" value="26"/>
            <class name="com.course.testng.parameter.ParameterTest"/>
        </classes>

    </test>

</suite>

14 参数化测试-DataProvider参数化

第一种:

DataProviderTest.java

package com.course.testng.parameter;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class DataProviderTest {

    // data和下面的name对应的值一样
    @Test(dataProvider = "data")
    public void testProvider(String name,int age){
        System.out.println("name="+name+",age="+age);
    }

    // data和上面的dataProvider对应的值一样
    @DataProvider(name="data")
    public Object[][] providerData(){
        Object[][] o=new Object[][]{
                {"张三",10},
                {"汪三",20},
                {"李三",30}
        };
        return o;
    }
}
name=张三,age=10
name=汪三,age=20
name=李三,age=30

===============================================
Default Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

第二种:通过方法名进行参数传递

package com.course.testng.parameter;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import java.lang.reflect.Method;

public class DataProviderTest {

    // data和下面的name对应的值一样
    @Test(dataProvider = "data")
    public void testProvider(String name, int age) {
        System.out.println("name=" + name + ",age=" + age);
    }

    // data和上面的dataProvider对应的值一样
    @DataProvider(name = "data")
    public Object[][] providerData() {
        Object[][] o = new Object[][]{
                {"张三", 10},
                {"汪三", 20},
                {"李三", 30}
        };
        return o;
    }

// 另一种操作

    @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);

    }

    //method写的目的:会自动将方法名,也就是test1和test2传进来
    // 使用的包是:import java.lang.reflect.Method;
    @DataProvider(name = "methodData")
    public Object[][] methodDataTest(Method method) {
        Object[][] result = null;

        if (method.getName().equals("test1")) {
            result = new Object[][]{
                    {"张四", 10},
                    {"汪四", 20},
                    {"李四", 30}
            };
        } else if (method.getName().equals("test2")) {
            result = new Object[][]{
                    {"王老五", 10},
                    {"王老七", 20},
            };
        };
            return result;

    }
}

15 多线程测试-注解方式实现

如果我们设置多个线程池,就可以有不同的id号啦(但是多线程的执行顺序我们无法控制)

package com.course.testng.multiThread;

import org.testng.annotations.Test;

//通过注解来实现
public class multiThreadOnAnnotion {
    // 如果我们设置多个线程池,就可以有不同的id号啦(但是多线程的执行顺序我们无法控制)
    @Test(invocationCount = 10,threadPoolSize = 3)
    public void test(){
        System.out.println(1);
        // 必须是f  printf
        System.out.printf("Thread ID : %s%n",Thread.currentThread().getId());
    }

}
# 运行结果
1
1
Thread ID : 11
1
Thread ID : 12
Thread ID : 13
1
Thread ID : 11
1
Thread ID : 13
1
Thread ID : 12
1
Thread ID : 12
1
Thread ID : 11
1
Thread ID : 12
1
Thread ID : 13

===============================================
Default Suite
Total tests run: 10, Failures: 0, Skips: 0
===============================================

16 多线程测试-xml文件实现

classs级别可以看看老师的代码实现

parallel ="methods" 表示级别是方法级别-
thread-count="2"  代表了最大并发线程数

methods级别:所有用例都能在不同的线程下去执行(一般配置这个)
tests级别:
 1)相同的test tag( 就是底下的demo2啦 <test name="demo2" >只能在相同的线程池去执行
 2)不同的test tag可以在不同的线程池去执行(底下的一个叫thread,一个叫demo2,正好符合不同的test tage)
classs级别:
 1)相同的class tag下的用例只能在同一个线程下执行
 2)不同的class tag下的用例可以在多个线程下执行
thread-count:最大并发线程数

java

package com.course.testng.multiThread;

import org.testng.annotations.Test;

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" ?>
<!--
    parallel ="methods" 表示级别是方法级别-
    thread-count="2"  代表了最大并发线程数

    methods级别:所有用例都能在不同的线程下去执行(一般配置这个)
    tests级别:
     1)相同的test tag( 就是底下的demo2啦 <test name="demo2" >只能在相同的线程池去执行
     2)不同的test tag可以在不同的线程池去执行(底下的一个叫thread,一个叫demo2,正好符合不同的test tage)
    classs级别:
     1)相同的class tag下的用例只能在同一个线程下执行
     2)不同的class tag下的用例可以在多个线程下执行
    thread-count:最大并发线程数

-->
<suite name ="thread" parallel ="classs" thread-count="3">
    <test name="demo1">
        <classes>
            <class name="com.course.testng.multiThread.multiThreadOnXml"/>
        </classes>


    </test>


</suite>

17 超时测试

package com.course.testng;

import org.testng.annotations.Test;

public class TimeOutTest {

    @Test(timeOut = 3000)   //单位 毫秒
    public void  testSuccess() throws InterruptedException{
        Thread.sleep(2000);
    }

    @Test(timeOut = 1000)   //单位 毫秒
    public void  testFailed() throws InterruptedException{
        Thread.sleep(2000);
    }
}