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 的区别。
个人更喜欢插件化的,可拓展的工具。