TestNG

TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use.

快速开始

maven 引入

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

代码

  • StringUtil.java

基础字符串测试工具类

public class StringUtil {

    /**
     * 是否为空
     * @param s 字符串
     * @return 是否为空
     */
    public static boolean isEmpty(final String s) {
        return null == s
                || "".equals(s.trim());
    }
}
  • TestNg.java
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestNg {

    @Test
    public void simpleTest() {
        final String string = "";
        Assert.assertTrue(StringUtil.isEmpty(string));
    }
}

运行结果:

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

用法和 Junit4 区别不大

DataProvider

DataProvider 让数据驱动测试变得更加简单。

我们首先看一个简单的例子,然后再讲解。

简单例子

  • TestNg.java

我们对测试类做简单调整:

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

public class TestNg {

    /**
     * 是否为空数据准备
     * ps: 只需要返回的是 object[][],数据的来源可以如下:
     * xml,excel,ymal,txt,database....
     * @return 数据
     */
    @DataProvider(name = "isEmpty")
    public Object[][] isEmptyDataProvider() {
        return new Object[][]{
                {"", true},
                {null, true},
                {"    ", true},
                {"1", false},
                {"   1", false}
        };
    }

    @Test(dataProvider = "isEmpty")
    public void isEmptyTest(final String string, boolean result) {
        System.out.println(string+", "+result);
        Assert.assertEquals(result, StringUtil.isEmpty(string));
    }
}

测试结果:

, true
null, true
    , true
1, false
   1, false

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

简单说明

  • 数据的声明

我们使用 @DataProvider 声明一个 Object[][] 的返回值,然后在测试方法中指定使用这个数据集。

测试方法的参数,和我们数据集合定义的一一对应。

如此,TestNG 就会依次将数据集合中的数据放到方法中依次执行验证。

可以减少因为数据入参,而需要不断添加新的测试方法的困境

  • Object[][]

对于这个数据的获取,也让其变得拥有更多的灵活性。我们的数据来源可以自行定义:

  • txt

  • excel

  • ymal

  • 数据库

….

一些想法

TestNG 当初的意图是因为 Junit 在注解出现之后,停滞了一段时间,现在很多功能都逐渐被 Junit 反超回来。

  • 数据驱动测试

不过数据驱动测试,是个非常棒的想法

  • testng 不对的地方

个人认为应该拓展 Junit,而不是取代,没必要吃力不讨好,全部覆盖。

我们因为在高楼之上,建筑高楼。而不应该推倒重来。

除非是全新的思想,完全有信心远超旧事物。

Spock 的优点

Spock 是针对 Grovvy 一款很棒的测试框架。

清晰的测试流程

模式

大部分的代码,都应该遵守一种 arrange-act-assert 模式

实际案例

  • Junit 测试常见代码
@Test
public void chargeCreditCard() {
    CreditCardBilling billing = new CreditCardBilling();
    Client client = new Client();
    billing.charge(client,150);
    assertEquals("Revenue should be recorded",150,billing.getCurrentRevenue());
}

有注释版本:

@Test
public void chargeCreditCard() {
    //1. a billing service and a customer with a valid credit card
    CreditCardBilling billing = new CreditCardBilling();
    Client client = new Client();
    //2. client buys something with 150 dollars
    billing.charge(client,150);
    //3. we expect the transaction to be recorded
    assertEquals("Revenue should be recorded",150,billing.getCurrentRevenue());
}

直观地可以发现,拥有注释的会更便于理解。但是不是每个程序员都会测试代码写注释。

  • Spock 版本
public void "charging a credit card - happy path"() {

    given: "a billing service and a customer with a valid credit card"
    CreditCardBilling billing = new CreditCardBilling();
    Client client = new Client();

    when: "client buys something with 150 dollars"
    billing.charge(client,150);

    then: "we expect the transaction to be recorded"
    billing.getCurrentRevenue() == 150
}

更加便于阅读

灵活的命名

上一个例子,业务你已经发现了。

Spock 中,方法的命名是:charging a credit card - happy path

Junit 中,却局限于 Java 本身的语法限制,只能命名为 chargeCreditCard,甚至还有如下的命名:

chargeCreditCard01
chargeCreditCard02
chargeCreditCard03
...
  • 个人建议

我觉得这也不是无法解决,@Test 注解中可以新增一个属性,比如 label/remark 等,用来说明测试的意图, 并且在生成测试报告时,显示此属性即可。

但是,目前的测试注解中应该没有。(Junit4/TestNG6)

利于阅读的测试报告

由于 Spock 的 given-when-then 的规范性,测试报告可以直接生成可阅读的,包含了测试的逻辑。

报告可以清晰看到:

METHOD: charging a credit card - happy path
-----------------------------------------------------------------
GIVEN:  a billing service and a customer with a valid credit card
WHEN:  client buys something with 150 dollars
THEN:  we expect the transaction to be recorded

对于开发者、测试者、管理者都有着积极的作用。

  • Junit 中能实现吗?

好像不能。。。

内置支持所有 + 终极解决方案

我觉得这就像笨重的 VS 和 VSC 的区别。

个人更喜欢插件化的,可拓展的工具。