👍TestNG一篇足以

本篇只能算入门,介绍一些常用的功能。

1.TestNG

1-1.是什么?

TestNG,即Testing, Next Generation,下一代测试技术,是一套根据JUnit和NUnit思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用来做集成测试。

1-2.插件

idea

idea去plugin里搜索TestNG,然后点击install,重启idea即可

Eclipse

放在eclipse的plugins文件夹下,然后启动eclipse,点击Help -> software update -> Installed Software, 查找到TestNG Eclipse插件,点击Install(安装),安装完成后,重启eclipse。

1-3.TestNG的优点

  • 漂亮的HTML格式测试报告
  • 支持并发测试
  • 参数化测试更简单
  • 支持输出日志
  • 支持更多功能的注解
  • 更适合集成测试

1-4.层次结构

  • 一个suite(套件) 由一个或多个测试组成。
  • 一个test(测试) 由一个或多个类组成
  • 一个class(类) 由一个或多个方法组成。
  • @BeforeSuite/@AfterSuite 在某个测试套件开始之前/在某个套件所有测试方法执行之后
  • @BeforeTest/@AfterTest 在某个测试开始之前/在某个测试所有测试方法执行之后
  • @BeforeClass/@AfterClass 在某个测试类开始之前/在某个类的所有测试方法执行之后
  • @BeforeMethod/@AfterMethod 在某个测试方法之前/在某个测试方法执行之后
  • @BeforeGroup/@AfterGroup 在某个组的所有测试方法之前/在某个组的所有测试方法执行之后

1-5.运行方式

  • With a testng.xml file (直接run as test suite)
  • With ant (使用ant)
  • From the command line (从命令行)
  • IDE (直接在IDE中执行)

2.简单示例

本篇的源码地址

code目录下,testng-demo子项目中。

2-1.基本类

先添加jar依赖

pom依赖

<dependencies>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.14.3</version>
        <scope>test</scope>
    </dependency>
</dependencies>

注意:

  • 这注意版版本不要用太新了。目前2020年8月,最新的版本是7.3.0,但是这选择的版本是 6.14.3。
  • 使用7.1.0的使用@BeforeGroup和@AfterGroup无效,换低版本就好了。
  • 使用7.3.0的使用idea在run测试类时候报错了TestNG by default disables loading DTD from unsecured Urls,换低版本就好了。
  • idea的TestNG插件版本和TestNG的版本间版本间有问题。所以选择版本时候,要注意不要使用太新的。自己测试下。
  • 实体类

    public class Student {
        private int id;
        private String name;
        private boolean sex;
    
        ...省略setter、gettter、toString、构造方法...
    }

    dao

    public class StudentDao {
    
        public void add(Student student){
            System.out.println("StudentDao ## add");
        }
    
        public List<Student> list(){
            System.out.println("StudentDao ## list");
            List<Student> students = new ArrayList<>();
            students.add(new Student(1, "沐雨云楼", true));
            students.add(new Student(2, "张三", false));
            return students;
        }
    
        public void delete(int id){
            System.out.println("StudentDao ## delete");
        }
    }

    service

    public class StudentService {
    
        public StudentDao studentDao;
    
        public void add(Student student){
            System.out.println("StudentService ## add");
            studentDao.add(student);
        }
    
        public List<Student> list(){
            System.out.println("StudentService ## list");
            return studentDao.list();
        }
    
        public void delete(int id){
            System.out.println("StudentService ## delete");
            studentDao.delete(id);
        }
    }

    2-2.测试类演示

    2-2-1.最简单测试类

    我是用idea来开发的,讲下如何快速生成测试类

    快捷键: alter+insert生成测试类

    简单测试类

    public class StudentDaoTest {
        @Test
        public void testAdd() {
            System.out.println("testAdd");
        }
    
        @Test
        public void testList() {
            System.out.println("testList");
        }
    
        @Test
        public void testDelete() {
            System.out.println("testDelete");
        }
    }

    类和方法上都可以run来测试

    2-2-2.执行顺序

    注解 说明
    @BeforeSuite 表示会在当前测试集合中的任意一个测试用例开始运行前执行
    @AfterSuite 表示会在当前测试集合中的所有测试程序运行结束之后执行
    @BeforeTest 表示会在Test中的任意一个测试用例开始运行前执行
    @AfterTest 表示会在Test中的所有测试用例运行结束后执行
    @BeforeGroups 分组测试用例的任一测试用例开始运行前执行
    @AfterGroups 分组测试用例的所有测试用例运行结束后执行
    @BeforeClass 在当前测试类的任意一个测试用例开始运行前执行
    @AfterClass 在当前测试类的所有测试用例运行结束后执行
    @BeforeMethod 在每个测试方法开始运行前执行
    @AfterMethod 在每个测试方法运行结束后执行
    @Test 被认为是一个测试方法,既一个测试用例

    执行顺序: @BeforeSuite > @BeforeTest > @BeforeMethod > @Test > @AfterMethod > @AfterTest > @AfterSuite

    使用最多就是@BeforeClass@AfterClass

    public class StudentDaoTest {
    
        private StudentDao studentDao;
    
        @BeforeClass
        public void beforeClass() {
            System.out.println("beforeClass###");
            studentDao = new StudentDao();
        }
    
        @AfterClass
        public void afterClass() {
            System.out.println("afterClass###");
        }
    
        @BeforeMethod
        public void beforeMethod() {
            System.out.println("beforeMethod...");
        }
    
        @AfterMethod
        public void afterMethod() {
            System.out.println("afterMethod...");
        }
    
        @Test
        public void testAdd() {
            System.out.println("testAdd");
            studentDao.add(new Student(3,"超级飞侠",true));
        }
    
        @Test
        public void testList() {
            System.out.println("testList");
        }
    
        @Test
        public void testDelete() {
            System.out.println("testDelete");
        }
    }

    结果:

    beforeClass###
    
    beforeMethod...
    testAdd
    StudentDao ## add
    afterMethod...
    
    beforeMethod...
    testDelete
    afterMethod...
    
    beforeMethod...
    testList
    afterMethod...
    
    afterClass###

    2-2-3.忽略测试

    • 忽略整个包 @Ignore
    • 忽略整个测试类 @Ignore
    • 忽略某个方法 @Test(enabled = false)

    忽略整个包

    @Ignore
    package com.iworkh.testng;
    
    import org.testng.annotations.Ignore;
    

    忽略整个测试类

    @Ignore
    public class StudentDaoIgnoreTest {
    
        @Test
        public void testAdd() {
            System.out.println("testAdd");
        }
    
        public void testList() {
            System.out.println("testList");
        }
    
        @Test
        public void testDelete() {
            System.out.println("testDelete");
        }
    }

    在类上加@Ignore注解

    忽略某个方法

    public class StudentDaoIgnoreTest {
    
        @Test
        public void testAdd() {
            System.out.println("testAdd");
        }
    
        @Test(enabled = false)
        public void testList() {
            System.out.println("testList");
        }
    
        @Test
        public void testDelete() {
            System.out.println("testDelete");
        }
    }

    在不需要测试的方法上的@Test的属性里设置@Test(enabled = false)

    2-2-4.提供数据

    共两种方式

    • 通过xml和@Parameters
    • 通过@DataProvider注解
    2-2-4-1.Parameters方式

    测试类

    public class StudentDaoParameterTest {
    
        @Test
        @Parameters({"id", "name", "sex"})
        public void testAdd(int id, String name, boolean sex) {
            System.out.println("testAdd");
            System.out.println(new Student(id, name, sex));
        }
    }

    配置文件:testng-parameters.xml

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1" >
    
        <test name="testParams">
            <parameter name="id" value="10"/>
            <parameter name="name" value="豆豆"/>
            <parameter name="sex" value="false"/>
            <classes>
                <class name="com.iworkh.testng.demo.dao.StudentDaoParameterTest"/>
            </classes>
        </test>
    </suite>

    通过run配置文件,查看结果

    2-2-4-2.DataProvider方式

    为测试方法提供数据,使用@DataProvider注解。@DataProvider也有两种形式:

    • 第一种:把在测试代码和测试数据放在同一个类中;
    • 第二种:把所有的数据提供都单独写在一个类里面,当测试数据比较多时,这种方法利于维护。

    测试类和测试数据在同一类

    public class StudentDaoDataProviderTest {
    
        @DataProvider(name = "insertStu")
        public Object[] providerData() {
            Student student = new Student(5, "王五", true);
            return new Object[]{student};
        }
    
        @Test(dataProvider = "insertStu")
        // 方法参数要和dataProvider传来的参数一致
        public void testAdd(Student student) {
            System.out.println("testAdd");
            System.out.println(student);
        }
    }

    两个地方需要注意:

    • 数据提供方法:使用@DataProvider在一个方法上,并定义名称;@DataProvider注解的方法返回值必须是Object[]或者Object[][]类型
    • 数据使用方法:@Test的属性dataProvider名称要跟@DataProvider的name一致;方法参数要和dataProvider传来的参数一致

    测试类和测试数据分开

    数据类

    public class StudentDaoDataProvider {
    
        @DataProvider(name = "listStus")
        public Object[][] providerData() {
            return new Object[][]{{1, "沐雨云楼", true}, {2, "小爱", false}, {3, "亚瑟", true},};
        }
    }

    测试类

    public class StudentDaoDataProviderTest {
        @Test(dataProvider = "listStus", dataProviderClass = StudentDaoDataProvider.class)
        // 参数要和dataProvider传来的参数一致
        public void testList(int id, String name, boolean sex) {
            System.out.println("testList");
            System.out.println(String.format("id: %d, 姓名: %s, 性别: %b", id, name, sex));
        }
    
    }

    @Test属性dataProviderClass指定的数据提供类;dataProvider指定数据提供的方法上@DataProvider的name值

    2-2-5.依赖

    同一类中,多个方法的执行顺序,默认是按着字母顺序进行执行的。

    如果有依赖关系的话,可以通过两种方式

    • 依赖方法 dependsOnMethods, 值是方法名,不支持正则
    • 依赖组 dependsOnGroups,值是组名,支持正则

    这简单说下group组的概念,即将可以将多个测试方法,分为一组。这样就可以方便管理。这样就可以使用@BeforeGroup,@AfterGroup,@dependsOnGroups

    public class StudentDaoDependsTest {
    
        @Test
        public void testParent() {
            System.out.println("testParent");
        }
    
        @Test
        public void parentFirst() {
            System.out.println("parentFirst");
        }
    
        @Test
        public void parentSecond() {
            System.out.println("parentSecond");
        }
    
        @Test(dependsOnMethods = {"testParent", "parentFirst", "parentSecond"})
        // 依赖方法,值是方法名,不支持正则表达式
        public void testChild() {
            System.out.println("testChild");
        }
    
        @Test(groups = {"env_1"})
        public void firstEnv() {
            System.out.println("env_1");
        }
    
        @Test(groups = {"env_2"})
        public void secondEnv() {
            System.out.println("env_2");
        }
    
        @Test(dependsOnGroups = {"env.*"})
        // 依赖groups,值是group名,支持正则匹配
        public void biz() {
            System.out.println("startBiz");
        }
    }

    2-2-6.优先级

    同一类中,多个方法的执行顺序,默认是按着字母顺序进行执行的。

    还可以通过@Testpriority来指定数字,默认值是0。(按照数字大小顺序优先执行,优先执行1,然后是2…)

    public class StudentDaoPriorityTest {
    
        @Test(priority = 1)
        public void one() {
            System.out.println("1");
        }
    
        @Test(priority = 2)
        public void two() {
            System.out.println("2");
        }
    
        @Test(priority = 100)
        public void last() {
            System.out.println("100");
        }
    }
    

    2-2-7.异常

    • expectedExceptions: 匹配异常的类型
    • expectedExceptionsMessageRegExp: 匹配异常的message
    public class StudentDaoExceptionTest {
    
        @Test(expectedExceptions = ArithmeticException.class,
              expectedExceptionsMessageRegExp = ".*zero.*")
        public void testDelete() {
            System.out.println("testDelete");
            System.out.println(1/0);
        }
    
        @Test(expectedExceptions = RuntimeException.class,
              expectedExceptionsMessageRegExp = "增加数据异常")
        public void testAdd() {
            System.out.println("testAdd");
            throw new RuntimeException("增加数据异常");
        }
    }

    2-2-8.超时

    public class StudentDaoTimeOutTest {
    
        @Test(timeOut = 2000)
        public void timeOut() {
            try {
                // 未超时
                TimeUnit.SECONDS.sleep(1);
                // 超时
                // TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    3.suite套件测试

    3-1.配置文件

    • 一个suite(套件) 由一个或多个测试组成。
    • 一个test(测试) 由一个或多个类组成
    • 一个class(类) 由一个或多个方法组成。
    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1" >
        <test name="login" >
            <classes>
                <class name="com.iworkh.testng.demo.suite.SuiteConfig" />
                <class name="com.iworkh.testng.demo.suite.LoginTest" />
            </classes>
        </test>
    
        <test name="pay">
            <classes>
                <class name="com.iworkh.testng.demo.suite.SuiteConfig"/>
                <class name="com.iworkh.testng.demo.suite.PayTest"/>
            </classes>
        </test>
    </suite>

    3-2.测试类

    SuiteConfig

    public class SuiteConfig {
    
        @BeforeSuite
        public void beforeSuite(){
            System.out.println("SuiteConfig beforeSuite ###");
        }
    
        @AfterSuite
        public void afterSuite(){
            System.out.println("SuiteConfig afterSuite ###");
        }
    
        @BeforeTest
        public void beforeTest(){
            System.out.println("SuiteConfig beforeTest @@@");
        }
    
        @AfterTest
        public void afterTest(){
            System.out.println("SuiteConfig afterTest @@@");
        }
    }

    LoginTest

    public class LoginTest {
    
        @BeforeClass
        public void beforeClass(){
            System.out.println("LoginTest beforeClass ...");
        }
    
        @AfterClass
        public void afterClass(){
            System.out.println("LoginTest afterClass ...");
        }
    
        @BeforeMethod
        public void beforeMethod(){
            System.out.println("LoginTest beforeMethod ...");
        }
    
        @AfterMethod
        public void afterMethod(){
            System.out.println("LoginTest afterMethod ...");
        }
    
        @Test
        public void testLogin() {
            System.out.println("LoginTest login");
        }
    
        @Test
        public void testLogOut() {
            System.out.println("LoginTest logout");
        }
    
    }

    PayTest

    public class PayTest {
    
        @Test
        public void testPay() {
            System.out.println("PayTest pay");
        }
    }

    3-3.结果

    如果run?

    这只讲idea的,其他方式自己官网找下

    结果

    SuiteConfig beforeSuite ###
    SuiteConfig beforeTest @@@
    
    LoginTest beforeClass ...
    
    LoginTest beforeMethod ...
    LoginTest logout
    LoginTest afterMethod ...
    
    LoginTest beforeMethod ...
    LoginTest login
    LoginTest afterMethod ...
    
    LoginTest afterClass ...
    
    SuiteConfig afterTest @@@
    
    
    SuiteConfig beforeTest @@@
    PayTest pay
    SuiteConfig afterTest @@@
    
    SuiteConfig afterSuite ###

    从上面结果可以看出,@BeforeSuite@AfterSuite在一个suite配置中,只运行一次。

    4.分组

    testng的组,可以对方法和类进行分组

    4-1.方法分组

    方法上分组比较简单,直接看代码

    public class GroupOnMethodTest {
    
        @BeforeGroups("gpOne")
        public void beforeGroupOne(){
            System.out.println("beforeGroup_one");
        }
    
        @AfterGroups("gpOne")
        public void afterGroupOne(){
            System.out.println("afterGroup_one");
        }
    
        @Test(groups = "gpOne")
        public void test1(){
            System.out.println("gp_one -- test1");
        }
    
        @Test(groups = "gpOne")
        public void test2(){
            System.out.println("gp_one -- test2");
        }
    
        @Test(groups = "gpTwo")
        public void test3(){
            System.out.println("gp_two -- test3");
        }
    }

    4-2.类分组

    说明:@Test不一定非要写在方法上,如果写在类上,那么这个类中的public方法都会是测试方法。

    类上分组测试,要使用到xml配置来run

    4-2-1.类

    三个类共分为两组,然后来指定组来run

    GroupOnClassOne

    @Test(groups = "goc_loginout")
    public class GroupOnClassOne {
    
        public void testLogin(){
            System.out.println("GroupOnClassOne testLogin ...");
        }
    }

    GroupOnClassTwo

    @Test(groups = "goc_loginout")
    public class GroupOnClassTwo {
    
        public void testLogout(){
            System.out.println("GroupOnClassTwo testLogout ...");
        }
    }

    GroupOnClassThree

    @Test(groups = "goc_pay")
    public class GroupOnClassThree {
    
        public void testPay(){
            System.out.println("GroupOnClassThree testPay ...");
        }
    }

    4-2-2.配置文件

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1" >
    
        <test name="runAll">
            <classes>
                <class name="com.iworkh.testng.demo.group.GroupOnClassOne"/>
                <class name="com.iworkh.testng.demo.group.GroupOnClassTwo"/>
                <class name="com.iworkh.testng.demo.group.GroupOnClassThree"/>
            </classes>
        </test>
    
        <test name="runGroupLoginout">
            <groups>
                <run>
                    <include name="goc_loginout"/>
                </run>
            </groups>
            <classes>
                <class name="com.iworkh.testng.demo.group.GroupOnClassOne"/>
                <class name="com.iworkh.testng.demo.group.GroupOnClassTwo"/>
                <class name="com.iworkh.testng.demo.group.GroupOnClassThree"/>
            </classes>
        </test>
    </suite>

    使用groupsruninclude几个标签来指定run的类上的组名

    5.多线程

    测试的级别由上至下可以分为suite -> test -> class -> method,箭头的左边元素跟右边元素的关系是一对多的包含关系。

    parallel参数几个值:

    • methods: 所有方法都在不同的线程中run

      一个线程负责一个@Test标签的程序,多个并行时,每个class,method之间的线程ID都不一样

    • tests: 同一个<test>中类里的所有方法在一个线程中run

      一个线程负责一个TestNG.xml中的一个<Test>标签,多个并行时,每个<Test>所包含的class,method之间的线程ID是一致的,但是 每个<Test>之间的线程ID是不一致的

    • classes: 同一个<class>中所有方法在一个线程中run

      一个线程负责一个class里面所有的带有@Test标签的method。多个并行时,每个class之间的线程id不一样,但是同一个class里的@Test的method线程id是一样的

    • none: 不起多线程

    5-1.测试类

    测试类一:ThreadByXmlTestFirst

    public class ThreadByXmlTestFirst {
    
        @Test
        public void testOne() {
            System.out.println("ThreadByXmlTestFirst ## 方法一:" + Thread.currentThread().getId());
        }
    
        @Test
        public void testTwo() {
            System.out.println("ThreadByXmlTestFirst ## 方法二:" + Thread.currentThread().getId());
        }
    }

    测试类二:ThreadByXmlTestSecond

    public class ThreadByXmlTestSecond {
    
        @Test
        public void testOne() {
            System.out.println("ThreadByXmlTestSecond ## 方法一:" + Thread.currentThread().getId());
        }
    
        @Test
        public void testTwo() {
            System.out.println("ThreadByXmlTestSecond ## 方法二:" + Thread.currentThread().getId());
        }
    }

    测试类三:ThreadByXmlTestThree

    public class ThreadByXmlTestThree {
    
        @Test
        public void testOne() {
            System.out.println("ThreadByXmlTestThree ## 方法一:" + Thread.currentThread().getId());
        }
    
        @Test
        public void testTwo() {
            System.out.println("ThreadByXmlTestThree ## 方法二:" + Thread.currentThread().getId());
        }
    }

    5-2.配置

    5-2-1.methods

    每个测试方法都用一个线程来run。

    配置

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1" parallel="methods" thread-count="5">
    
        <test name="threadXml_A">
            <classes>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestFirst"/>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestSecond"/>
            </classes>
        </test>
    
        <test name="threadXml_B">
            <classes>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestFirst"/>
            </classes>
        </test>
    </suite>

    结果

    ThreadByXmlTestFirst ## 方法二:14
    ThreadByXmlTestFirst ## 方法一:13
    
    ThreadByXmlTestSecond ## 方法二:16
    ThreadByXmlTestSecond ## 方法一:15

    5-2-2.tests

    同一test下的类里所有方法都用一个线程来run。

    配置

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1" parallel="tests" thread-count="5">
    
        <test name="threadXml_A">
            <classes>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestFirst"/>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestThree"/>
            </classes>
        </test>
    
        <test name="threadXml_B">
            <classes>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestSecond"/>
            </classes>
        </test>
    </suite>
    

    结果

    ThreadByXmlTestSecond ## 方法一:14
    ThreadByXmlTestFirst ## 方法一:13
    
    ThreadByXmlTestSecond ## 方法二:14
    ThreadByXmlTestFirst ## 方法二:13
    
    ThreadByXmlTestThree ## 方法一:13
    ThreadByXmlTestThree ## 方法二:13

    ThreadByXmlTestFirst和ThreadByXmlTestThree都在threadXml_A中,所有它们的测试方法都一个线程来run

    5-2-3.classes

    同一classes下的类里所有方法都用一个线程来run。

    配置

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1" parallel="classes" thread-count="5">
    
        <test name="threadXml_A">
            <classes>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestFirst"/>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestThree"/>
            </classes>
        </test>
    
        <test name="threadXml_B">
            <classes>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestFirst"/>
                <class name="com.iworkh.testng.demo.thread.ThreadByXmlTestSecond"/>
            </classes>
        </test>
    </suite>

    结果

    ThreadByXmlTestThree ## 方法一:14
    ThreadByXmlTestFirst ## 方法一:13
    
    ThreadByXmlTestFirst ## 方法二:13
    ThreadByXmlTestThree ## 方法二:14
    
    ThreadByXmlTestFirst ## 方法一:15
    ThreadByXmlTestSecond ## 方法一:16
    
    ThreadByXmlTestFirst ## 方法二:15
    ThreadByXmlTestSecond ## 方法二:16

    不同的类,不同的线程执行

    5-3.注解多线程

    @Test(threadPoolSize = 2, invocationCount = 2)
    public class ThreadByAnnoTest {
    
        public void testOne() {
            System.out.println("方法一:" + Thread.currentThread().getId());
        }
    
        @Test(threadPoolSize = 3, invocationCount = 3)
        public void testTwo() {
            System.out.println("方法二:" + Thread.currentThread().getId());
        }
    }

    通过@Test的两个属性threadPoolSizeinvocationCount,分别指线程数和执行次数
    注意:方法上的属性会替换调方法上的属性

    结果:

    方法一:12
    方法一:11
    
    方法二:13
    方法二:14
    方法二:15

    6.报告

    testng常见测试报告

    一些扩展链接

    6-1.ExtentReport报告

    有的文章使用的是testng-extentsreport来出的报告,有兴趣的可以参照下这篇blog ExtentReport测试报告

    本篇使用的是extentreports-testng-adapter来出的报告。具体步骤如下:

    通过extentreports文档4和testng进行整合介绍,我们知道ExtentReport的社区版和专业版的依赖是不一样的。我们使用社区版来演示学习。

    添加依赖

    <dependencies>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports</artifactId>
            <version>4.1.7</version>
        </dependency>
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports-testng-adapter</artifactId>
            <version>1.0.7</version>
        </dependency>
    </dependencies>

    这里使用的是4.1.7,目前最新版本已经5.x,但是要跟我们选的testng的版本对应,所以选中了4.1.7。要注意版本之间的兼容问题。

    • ExtentITestListenerClassAdapter:每执行完一个Test更新一次报告
    • ExtentITestListenerAdapter:每执行完一个Test更新一次报告
    • ExtentIReporterSuiteClassListenerAdapter:每执行完一个suite更新一次报告
    • ExtentIReporterSuiteListenerAdapter:每执行完一个suite更新一次报告

    测试类

    public class ReportTest {
    
        @Test
        public void testFail(){
            System.out.println("fail");
            Assert.assertTrue(false);
        }
    
        @Test
        public void testPass(){
            System.out.println("pass");
            Assert.assertTrue(true);
        }
    }

    report配置文件

    extent.reporter.html.start=true
    extent.reporter.html.out=test-output/HtmlReport/ExtentHtml.html

    test-ng的配置

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
    
    <suite name="testSuite" verbose="1">
        <listeners>
            <listener class-name="com.aventstack.extentreports.testng.listener.ExtentITestListenerClassAdapter"/>
        </listeners>
        <test name="report">
            <classes>
                <class name="com.iworkh.testng.report.ReportTest"/>
            </classes>
        </test>
    </suite>

    跑完testng报告,然后去test-output/HtmlReport/ExtentHtml.html目录下查看对应的ExtentHtml.html报告

    6-2.Allure报告

    这只介绍如何开发本地玩,至于如何集成到jenkins中,可以查看官网步骤。 集成Jenkins

    共以下几个步骤:

    • 下载allure-commandline,根据自己系统,下载并安装 allure-commandline下载地址
    • 配置allure环境变量(我的电脑 - 高级系统设置 - 高级 - 环境变量 - path - 添加bin目录到path中)。然后命令行验证allure --version
    • 编写代码,配置maven插件
    • mvn clean test生成报告
    • 启动allure-commandline,allure serve ./allure-results(注意测试报告位置), 然后查看生成的报告

    a.生成报告

    mvn clean test

    b.命令启动

    allure serve ./allure-results

    c.报告结果


    转载请注明来源,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 157162006@qq.com

    文章标题:👍TestNG一篇足以

    字数:5k

    本文作者:沐雨云楼

    发布时间:2020-08-22, 18:37:28

    最后更新:2020-09-12, 21:21:47

    原始链接:https://iworkh.gitee.io/blog/2020/08/22/java-test-ng/

    版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

    目录
    ×

    喜欢就点赞,疼爱就打赏

    pgmanor iworkh gitee