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 引入

  [xml]
1
2
3
4
5
6
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.14.3</version> <scope>test</scope> </dependency>

代码

  • StringUtil.java

基础字符串测试工具类

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
public class StringUtil { /** * 是否为空 * @param s 字符串 * @return 是否为空 */ public static boolean isEmpty(final String s) { return null == s || "".equals(s.trim()); } }
  • TestNg.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
import org.testng.Assert; import org.testng.annotations.Test; public class TestNg { @Test public void simpleTest() { final String string = ""; Assert.assertTrue(StringUtil.isEmpty(string)); } }

运行结果:

  [plaintext]
1
2
3
4
=============================================== Default Suite Total tests run: 1, Failures: 0, Skips: 0 ===============================================

用法和 Junit4 区别不大

DataProvider

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

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

简单例子

  • TestNg.java

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

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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)); } }

测试结果:

  [plaintext]
1
2
3
4
5
6
7
8
9
10
, 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 测试常见代码
  [java]
1
2
3
4
5
6
7
@Test public void chargeCreditCard() { CreditCardBilling billing = new CreditCardBilling(); Client client = new Client(); billing.charge(client,150); assertEquals("Revenue should be recorded",150,billing.getCurrentRevenue()); }

有注释版本:

  [java]
1
2
3
4
5
6
7
8
9
10
@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 版本
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
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,甚至还有如下的命名:

  [plaintext]
1
2
3
4
chargeCreditCard01 chargeCreditCard02 chargeCreditCard03 ...
  • 个人建议

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

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

利于阅读的测试报告

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

报告可以清晰看到:

  [plaintext]
1
2
3
4
5
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 的区别。

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