Groovy之UT单元测试
这里介绍下Groovy中的Unit Test单元测试
UT语法
由于Groovy中已经内置了Junit。故非常适合进行UT单元测试。这里介绍几种常见的进行单元测试语法示例。首先,我们写一个普通的Java类
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class HelloWorld {
private String name;
public String hello(String otherName) {
StringBuilder sb = new StringBuilder();
sb.append("I'm " + name + ", ");
sb.append( "Hi " + otherName + "~" );
return sb.toString();
}
}
然后通过Groovy编写UT单元测试。具体地:
第一种:直接继承GroovyTestCase, 且方法名需要以test开头
class HelloWorldTest1 extends GroovyTestCase{
void testHello() {
HelloWorld helloWorld = new HelloWorld("Aaron")
String result = helloWorld.hello("Tony")
assert result == "I'm Aaron, Hi Tony~"
}
}
第二种:直接继承TestCase, 且方法名需要以test开头
class HelloWorldTest2 extends TestCase {
void testHello() {
HelloWorld helloWorld = new HelloWorld("Aaron")
String result = helloWorld.hello("Tony")
assert result == "I'm Aaron, Hi Tony~"
}
}
第三种:直接使用@Test注解, 方法名可随意
class HelloWorldTest3 {
@Test
void helloTest() {
HelloWorld helloWorld = new HelloWorld("Aaron")
String result = helloWorld.hello("Tony")
assert result == "I'm Aaron, Hi Tony~"
}
}
Assertion 断言
Groovy中内置了若干断言用于进行单元测试。为了便于演示,这里提供一个Java类用于进行单元测试
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class Flower {
private String type;
@Override
public String toString() {
return "This is a " + type +" Flower";
}
public String inspect() {
return "[Info]: " + type;
}
public void calcException(int i) {
try{
if( i==1 ) {
throw new FileNotFoundException();
} else if( i==2 ) {
throw new NullPointerException();
}
} catch (Exception e) {
throw new RuntimeException( e );
}
}
}
assertLength
assertLength用于断言数组长度,示例代码如下所示
class AssertionDemo extends GroovyTestCase{
/**
* assertLength: 断言数组长度
*/
void test1() {
int[] nums = [1,3,5,7]
assertLength(4, nums)
char[] alphabet = ["T", "C", "Z"]
assertLength(3, alphabet)
def array = [996, "Aaron"] as Object[]
assertLength(2, array)
}
}
assertArrayEquals
assertArrayEquals用于断言数组长度、内容完全一致
class AssertionDemo extends GroovyTestCase{
/**
* assertArrayEquals: 断言数组长度、内容完全一致
*/
void test2() {
Object[] nums1 = [1,3]
Object[] nums2 = [1,3]
assertArrayEquals(nums1 ,nums2)
Flower[] flowers1 = [ new Flower("牡丹"), new Flower("茉莉") ]
Flower[] flowers2 = [ new Flower("牡丹"), new Flower("茉莉") ]
assertArrayEquals( flowers1, flowers2 )
}
}
assertEquals、assertNotSame、assertSame
assertEquals用于断言内容是否相等 assertNotSame用于断言两个对象的地址是否不同 assertSame用于断言两个对象的地址是否相同
class AssertionDemo extends GroovyTestCase{
/**
* assertEquals: 断言内容是否相等
* assertNotSame: 断言两个对象的地址是否不同
* assertSame: 断言两个对象的地址是否相同
*/
void test3() {
// 校验result变量是否为期待值
String result = "Aaron" + "." + "Zhu"
String expected = "Aaron.Zhu"
assertEquals(expected, result)
// 校验浮点数num1、num2、num3是否为期待值
double num1 = 100.01
double num2 = 100.1
double num3 = 99.9
double expectedNum = 100
// 浮点数比较需要设置阈值
double delta = 0.1
assertEquals(expectedNum, num1, delta)
assertEquals(expectedNum, num2, delta)
assertEquals(expectedNum, num3, delta)
String errorMsg = "浮点数不相等"
// 支持设置断言失败的信息
assertEquals(errorMsg, expectedNum, num3, delta)
Flower flower = new Flower("牵牛花")
Flower expectedObj = new Flower("牵牛花")
// 断言两个对象的内容是否相等
assertEquals( expectedObj, flower )
// 断言两个对象的地址是否不同
assertNotSame( expectedObj, flower )
// 断言两个对象的地址是否相同
assertSame( flower, flower )
}
}
assertToString、assertInspect
assertToString用于断言对象调用toString方法的结果 assertInspect用于断言对象调用inspect方法的结果
class AssertionDemo extends GroovyTestCase{
/**
* assertToString: 断言对象调用toString方法的结果
* assertInspect: 断言对象调用inspect方法的结果
*/
void test4() {
Flower flower = new Flower(type: "向阳花")
String expected = "This is a 向阳花 Flower"
assertToString(flower, expected)
expected = "[Info]: 向阳花"
assertInspect(flower, expected)
}
}
shouldFail、shouldFailWithCause
shouldFail用于断言闭包执行失败, 并抛出指定或任意类型的异常 shouldFailWithCause用于断言闭包执行失败, 且内部嵌套异常为指定类型异常
class AssertionDemo extends GroovyTestCase{
/**
* shouldFail: 断言闭包执行失败, 并抛出指定或任意类型的异常
* shouldFailWithCause: 断言闭包执行失败, 且内部嵌套异常为指定类型异常
*/
void test5() {
// 断言闭包执行失败, 并抛出指定类型的异常
def msg1 = shouldFail(NullPointerException) {
new HashMap(null)
}
def msg2 = shouldFail(IllegalArgumentException) {
new HashMap(-1)
}
// 断言闭包执行失败, 并抛出任意类型的异常
def msg3 = shouldFail {
new HashSet(-1)
}
// 断言闭包执行失败, 且getCause方法获取的内部嵌套的异常为指定类型异常
Flower flower = new Flower()
def msg4 = shouldFailWithCause(FileNotFoundException) {
flower.calcException(1)
}
def msg5 = shouldFailWithCause(NullPointerException) {
flower.calcException(2)
}
}
}
assertTrue、assertFalse、assertNull、assertNotNull
assertTrue用于断言表达式为真 assertFalse用于断言表达式为假 assertNull用于断言对象为null assertNotNull用于断言对象不为null
class AssertionDemo extends GroovyTestCase{
/**
* assertTrue: 断言表达式为真
* assertFalse: 断言表达式为假
* assertNull: 断言对象为null
* assertNotNull: 断言对象不为null
*/
void test6() {
assertTrue( 200>1 )
assertFalse( 1>200 )
Flower flower = null
assertNull( flower )
flower = new Flower()
assertNotNull( flower )
}
}
Test Suite 测试套件
对于多个测试类,我们还可以编写Groovy脚本实现将多个测试类组织到一个Test Suite测试套件当中。为了便于演示,我们先写两个Groovy的测试类,分别如下所示
class IntegerTest extends GroovyTestCase {
void test1() {
assertSame(1,1)
}
void test2() {
assertTrue( 200>1 )
}
void test3() {
assertNotNull( 996 )
}
}
class StringTest extends GroovyTestCase {
void test1() {
def name = "Aaron"
assertSame( name, name )
}
void test2() {
assertTrue( "Aaron".length()>1 )
}
void test3() {
assertNotNull( "Aaron" )
}
}
现在我们看看如何将这两个测试类组织到一个测试套件当中,Groovy脚本如下所示
// Groovy 测试套件示例 1
def testSuite = new TestSuite()
def groovyTestSuite = new GroovyTestSuite()
// 向测试套件中分别添加各单元测试类
testSuite.addTestSuite( groovyTestSuite.compile("IntegerTest.groovy") )
testSuite.addTestSuite( groovyTestSuite.compile("StringTest.groovy") )
// 执行测试套件
TestRunner.run( testSuite )
对于测试类较多的局面,其还支持路径、文件名匹配的方式添加测试类到测试套件当中。Groovy脚本如下所示
// Groovy 测试套件示例 2
// 单元测试类的路径匹配表达式 .表示当前路径
String basedir = "."
// 单元测试类的文件名匹配表达式
String pattern = "*Test.groovy"
// 构建测试套件
def testSuite = AllTestSuite.suite(basedir, pattern)
// 执行测试套件
TestRunner.run( testSuite )
上述两个Groovy测试类、两个Groovy脚本的目录结构如下所示
参考文献
Groovy In Action · 2nd Edition Dierk König、Guillaume Laforge著
评论