51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 463|回复: 0
打印 上一主题 下一主题

[转贴] TestNG 参数化测试实践指南

[复制链接]
  • TA的每日心情
    无聊
    5 小时前
  • 签到天数: 939 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-8-1 10:55:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    参数化测试TestNG的一个重要特性。 在很多情况下,我们会遇到业务逻辑需要大量测试的场景。 参数化测试允许我们使用不同的值一次又一次地运行相同的测试。
       本文介绍了TestNG 参数化注入的三种不同方式,并在此基础上,介绍了测试代码和测试数据、测试数据和测试环境的分离实践以及一种利用Nacos将测试代码和测试数据维护分离的有效实践。另外,本文将会引导读者完成一个实例,该示例将会较好地演示TestNG 参数的注入方式以及分离测试代码、数据与环境的有效实践。
      示例项目准备
      这里我们使用IDEA 社区版演示本实践全过程,读者也可以使用Eclipse和VSCode参考执行,但笔者并不推荐。


    Language选择Java,Build system选择Maven,JDK选择1.8后,点“Create” 进入工程页面。
      pom.xml里加入dependency:
    1. <dependency>
    2.       <groupId>org.testng</groupId>
    3.       <artifactId>testng</artifactId>
    4.       <version>7.4.0</version>
    5.       <scope>test</scope>
    6.   </dependency>
    复制代码
    TestNG 参数化注入的方式
      TestNG可以通过如下三种不同的方式将参数直接传递给测试方法:
      ·使用注解Parameters配合testng.xml
      · 使用注解Parameters配合-D命令行参数
      · 使用注解DataProvider
      使用注解Parameters配合testng.xml
      我们通过在testng.xml定义参数,然后在代码里面可以直接引用。我们先写一个测试用例如下:
    1.   src/test/java/com/fastjrun.example/testng/ParameterizedTest1.java
    复制代码
    1. package com.fastjrun.example.testng;
    2.   import org.testng.annotations.Parameters;
    3.   import org.testng.annotations.Test;
    4.   public class ParameterizedTest1 {
    5.       @Test
    6.       @Parameters("myName")
    7.       public void parameterTest(String myName) {
    8.           System.out.println("Parameterized value is : " + myName);
    9.       }
    10.   }
    复制代码
    编写testng.xml如下:
    1. <?xml version = "1.0" encoding = "UTF-8"?>
    2.   <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    3.   <suite name = "Suite1">
    4.       <test name = "test1">
    5.           <parameter name = "myName" value="manisha"/>
    6.           <classes>
    7.               <class name = "com.fastjrun.example.testng.ParameterizedTest1" />
    8.           </classes>
    9.       </test>
    10.   </suite>
    复制代码
    执行测试。
      在testng.xml编辑窗口点击鼠标右键弹出下拉菜单后,从中选择“Run .../src/test/resources/testng.xml”即可执行该单元测试用例。

    执行结果如下:
    1. Parameterized value is : manisha
    2.   ===============================================
    3.   Suite1
    4.   Total tests run: 1, Passes: 1, Failures: 0, Skips: 0
    5.   ===============================================
    复制代码
    另外我们也可以如下图所示,在ParameterizedTest1类编辑窗口选中需要测试的方法名parameterTest,点击鼠标右键弹出下拉菜单后,从中选择“Run parameterTest()”即可执行该单元测试用例。

    但通过如上方式运行单元测试,结果如下:
    1. ……
    2.   [Utils] [ERROR] [Error] org.testng.TestNGException:
    3.   Parameter 'myName' is required by [url=home.php?mod=space&uid=724]@test[/url] on method parameterTest but has not been marked @Optional or defined
    4.   in /Users/cuiyingfeng/Library/Caches/JetBrains/IdeaIC2022.1/temp-testng-customsuite.xml
    复制代码
    显然如上方式触发的测试用例不能指定依赖的testng.xml,myName参数没有被初始化,导致测试失败。
      使用testng.xml 执行测试的方式适合对测试用例批量执行的场景;如果我们在IDE中只想执行某个具体的测试方法,还是需要从类中触发测试方法的方式,也就是要通过非testng.xml配置的方式解决myName初始化的问题。
      解决myName初始化问题的方法一共有两种,其中一种是在测试方法parameterTest输入参数前加@Optional注解,给myName一个默认的初始值如下:
    1. package com.fastjrun.example.testng;
    2.   import org.testng.annotations.Optional;
    3.   import org.testng.annotations.Parameters;
    4.   import org.testng.annotations.Test;
    5.   public class ParameterizedTest1 {
    6.       @Test
    7.       @Parameters("myName")
    8.       public void parameterTest(@Optional("optional") String myName) {
    9.           System.out.println("Parameterized value is : " + myName);
    10.       }
    11.   }
    复制代码
    另外就是使用-D命令行参数。
      使用注解Parameters配合-D命令行参数
      使用-D命令行参数就是让参数以系统参数的方式加载入JVM,该方式支持Java、Maven命令行执行。idea配置-D命令行参数的方式如下:

    使用注解DataProvider
      我们先写一个业务类PrimeNumberChecker如下所示,该类中只有一个方法validate,检查输入参数primeNumber是否为质数,如果是返回True,如果不是返回False。
    1.   src/main/java/com/fastjrun.example/testng/PrimeNumberChecker.java
    复制代码
    1. package com.fastjrun.example.testng;
    2.   public class PrimeNumberChecker {
    3.       public Boolean validate(final Integer primeNumber) {
    4.           for (int i = 2; i < (primeNumber / 2); i++) {
    5.               if (primeNumber % i == 0) {
    6.                   return false;
    7.               }
    8.           }
    9.           return true;
    10.       }
    11.   }
    复制代码
    再写一个测试类PrimeNumberCheckerTest:
      定义一个方法primeNumbers(), 该方法返回值是一个对象数组,该方法使用了注解DataProvider,其值为test1,方法体中只是简单返回了一个新建的对象数据。
      新增一个方法 testPrimeNumberChecker(),该方法定义了两个输入参数整型变量inputNumber和布尔变量expectedResult。该方法体调用PrimeNumberChecker的validate方法,来验证inputNumber为质数的结果是否为expectedResult。
      方法 testPrimeNumberChecker()其实是一个测试用例,该方法使用注解@Test(dataProvider = "test1"),表明该测试用例的dataProvider设置为test1,也就是说在执行该测试用例的时候,会使用primeNumbers()返回的对象数组为该方法的输入参数分别赋值。
    1.   src/test/java/com/fastjrun.example/testng/PrimeNumberCheckerTest.java
    复制代码
    1.  package com.fastjrun.example.testng;
    2.   import org.testng.Assert;
    3.   import org.testng.annotations.BeforeMethod;
    4.   import org.testng.annotations.DataProvider;
    5.   import org.testng.annotations.Test;
    6.   public class PrimeNumberCheckerTest {
    7.       private PrimeNumberChecker primeNumberChecker;
    8.       @BeforeMethod
    9.       public void initialize() {
    10.           primeNumberChecker = new PrimeNumberChecker();
    11.       }
    12.       @DataProvider(name = "test1")
    13.       public Object[][] primeNumbers() {
    14.           return new Object[][] {{2, true}, {6, false}, {19, true}, {22, false}, {23, true}};
    15.       }
    16.       // This test will run 4 times since we have 5 parameters defined
    17.       @Test(dataProvider = "test1")
    18.       public void testPrimeNumberChecker(Integer inputNumber, Boolean expectedResult) {
    19.           System.out.println(inputNumber + " " + expectedResult);
    20.           Assert.assertEquals(expectedResult, primeNumberChecker.validate(inputNumber));
    21.       }
    22.   }
    复制代码
    在PrimeNumberCheckerTest类编辑窗口选中需要测试的方法名testPrimeNumberChecker,点击鼠标右键弹出下拉菜单后,从中选择“Run testPrimeNumberChecker()”即可执行该单元测试用例。

    执行结果如下:
    1.  2 true
    2.   6 false
    3.   19 true
    4.   22 false
    5.   23 true
    6.   ===============================================
    7.   Default Suite
    8.   Total tests run: 5, Passes: 5, Failures: 0, Skips: 0
    9.   ===============================================
    复制代码
    从结果可以看出,该测试用例通过DataProvider一次性注入了5组测试数据。这种特性非常有助于我们在研发过程中采用TDD(测试驱动开发)。关于TDD,并不是本文探讨的内容,这里就不展开了。








    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-4-28 14:25 , Processed in 0.063971 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表