这里介绍下Groovy中的Unit Test单元测试
UT语法
由于Groovy中已经内置了Junit。故非常适合进行UT单元测试。这里介绍几种常见的进行单元测试语法示例。首先,我们写一个普通的Java类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @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开头
1 2 3 4 5 6 7
| 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开头
1 2 3 4 5 6 7
| class HelloWorldTest2 extends TestCase { void testHello() { HelloWorld helloWorld = new HelloWorld("Aaron") String result = helloWorld.hello("Tony") assert result == "I'm Aaron, Hi Tony~" } }
|
第三种:直接使用@Test注解, 方法名可随意
1 2 3 4 5 6 7 8
| 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类用于进行单元测试
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
| @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用于断言数组长度,示例代码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class AssertionDemo extends GroovyTestCase{
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用于断言数组长度、内容完全一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class AssertionDemo extends GroovyTestCase{
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用于断言两个对象的地址是否相同
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 30 31 32 33 34 35 36 37 38
| class AssertionDemo extends GroovyTestCase{
void test3() { String result = "Aaron" + "." + "Zhu" String expected = "Aaron.Zhu" assertEquals(expected, result)
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方法的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class AssertionDemo extends GroovyTestCase{
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用于断言闭包执行失败, 且内部嵌套异常为指定类型异常
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
| class AssertionDemo extends GroovyTestCase{
void test5() { def msg1 = shouldFail(NullPointerException) { new HashMap(null) } def msg2 = shouldFail(IllegalArgumentException) { new HashMap(-1) }
def msg3 = shouldFail { new HashSet(-1) }
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class AssertionDemo extends GroovyTestCase{
void test6() { assertTrue( 200>1 ) assertFalse( 1>200 )
Flower flower = null assertNull( flower ) flower = new Flower() assertNotNull( flower ) } }
|
Test Suite 测试套件
对于多个测试类,我们还可以编写Groovy脚本实现将多个测试类组织到一个Test Suite测试套件当中。为了便于演示,我们先写两个Groovy的测试类,分别如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13
| class IntegerTest extends GroovyTestCase { void test1() { assertSame(1,1) }
void test2() { assertTrue( 200>1 ) }
void test3() { assertNotNull( 996 ) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class StringTest extends GroovyTestCase { void test1() { def name = "Aaron" assertSame( name, name ) }
void test2() { assertTrue( "Aaron".length()>1 ) }
void test3() { assertNotNull( "Aaron" ) } }
|
现在我们看看如何将这两个测试类组织到一个测试套件当中,Groovy脚本如下所示
1 2 3 4 5 6 7 8 9 10
| def testSuite = new TestSuite() def groovyTestSuite = new GroovyTestSuite()
testSuite.addTestSuite( groovyTestSuite.compile("IntegerTest.groovy") ) testSuite.addTestSuite( groovyTestSuite.compile("StringTest.groovy") )
TestRunner.run( testSuite )
|
对于测试类较多的局面,其还支持路径、文件名匹配的方式添加测试类到测试套件当中。Groovy脚本如下所示
1 2 3 4 5 6 7 8 9 10
|
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著