JUnit 中的断言表达式(Assertion)

最近在学习测试用例生成工具 EvoSuite 和 Randoop 的时候(Randoop 我之前有写总结 《Randoop的使用》),发现 JUnit 中的一些断言语句忘得差不多了,现在简单总结一下,我参考的 JUnit 版本是 4.12。
JUnit 中的断言表达式(Assertion)_第1张图片

1. JUnit 简介

简单来讲,JUnit 是一个常见的 Java 测试框架,它的主要作用就是帮助人们重复地执行测试用例(我之前写过 JUnit 4 的总结 JUnit 概述)。现在最新的版本是 JUnit 5 了,更新了部分很有用的断言语句,确定使用平台为 JDK 8.0 了。在这里不做赘述,大家可以去官网看看。

2. JUnit 断言

断言在 JUnit 中的实现是 org.junit.Assert 类,它的作用就是验证函数的输出是否与预期的输出相同,如果相同则返回 true,不相同则返回 false。API 文档见官网 https://junit.org/junit4/javadoc/latest/index.html。我是根据此 API 来分别总结不同的断言语句的,末尾我会给出一些 JUnit5 中的新断言语句。

1. 数组比较 assertArrayEquals

assertArrayEquals() 函数用来比较 2 个数组是否相同。它也存在有很多多态函数来比较不同的数组类型。

public static void assertArrayEquals(int[] expecteds, int[] actuals) 
public static void assertArrayEquals(boolean[] expecteds, boolean[] actuals) 
public static void assertArrayEquals(byte[] expecteds, byte[] actuals) 
public static void assertArrayEquals(char[] expecteds, char[] actuals) 
//...

值得注意的是,当我们要比较 2 个浮点值数组的时候,我们需要加上第 3 个参数 delta 表示数组在进行一一比较时,能够容忍的精度损失(二进制存储带来的风险)。如 delta=0.01 时,1.011.00 被认为是相等的。

public static void assertArrayEquals(double[] expecteds, double[] actuals, double delta) 
public static void assertArrayEquals(float[] expecteds, float[] actuals, float delta) 

另外, assertArrayEquals() 函数也可以用来比较 2 个对象(即 Object)是否相同。Java 中判断 2 个对象是否相同用 Object.equals() 函数,特例是如果二者都是 null ,二者相等。

public static void assertArrayEquals(Object[] expecteds, Object[] actuals) 

assertArrayEquals() 函数还可以打印报错语句。它需要在函数开头加一个 message 字符串参数,当断言返回值为假时,会报异常并给出 message 的提示。

public static void assertArrayEquals(String message, int[] expecteds, int[] actuals) 
public static void assertArrayEquals(String message, boolean[] expecteds, boolean[] actuals) 
public static void assertArrayEquals(String message, byte[] expecteds, byte[] actuals) 
public static void assertArrayEquals(String message, char[] expecteds, char[] actuals) 
//...
2. 变量比较 assertEquals, assertNotEquals

assertEquals() 函数是最常见且最简单的断言语句,它会比较 2 个变量是否相同。它存在有很多多态函数来比较不同的变量类型,如整型,字符型和布尔型等。看名字就应该大致了解其功能。

public static void assertEquals(Object expected, Object actual) 
public static void assertEquals(String message, double expected, double actual) 
public static void assertEquals(String message, double expected, double actual, double delta) 
//...

assertNotEquals 是另一种形式比较变量的断言语句,它与 assertNotEquals 相反,它是用来判断 2 个变量是否不相等。

public static void assertNotEquals(float unexpected, float actual, float delta) 
public static void assertNotEquals(long unexpected, long actual) 
//...
3. 条件真假 assertFalse, assertTrue

assertFalse()assertTrue 函数是用来比较布尔表达式的真假。不同的是前者判断条件是否为假,后者判断条件是否为真。

public static void assertFalse(boolean condition) 
public static void assertTrue(String message, boolean condition) 
4. 是否为空 assertNull, assertNotNull

assertNotNullassertNull 函数是同来判断对象是否为空的断言语句。如果一个对象没有被实例化就为空。

public static void assertNull(Object object) 
public static void assertNotNull(String message, Object object) 
5. 对象比较 assertSame, assertNotSame

assertNotSameassertNotSame 函数是 比较 2 个对象是否是同一个对象,即对象的引用地址相同。注意不要与之前的 assertEquals 函数弄混淆, assertEquals 函数是 比较 2 个对象是否相同,也就是说当 2 个对象不为空的时候,assertEquals 函数会利用对象的 Object.equals() 函数来比较。

public static void assertSame(Object expected, Object actual) 
public static void assertNotSame(String message, Object unexpected, Object actual)

我们可以为对象重写 Object.equals() 函数来辅助 assertEquals 函数的使用。例如我们可以为 YStack 对象(假设 YStack 实现堆栈功能的类)写一个 equals() 函数,这样,我们就可以在测试用例中使用 assertEquals 函数了。我们编写的 equals() 函数如下,

public boolean equals(Object stack2){
	if (!(stack2 instanceof YStack)){ // 判断参数是否属于 YStack 类
		return false;
	}		
	if (((YStack) stack2).getElems().length != this.getElems().length){
		return false; // 判断 2 个对象中的元素个数是否相等
	}	
	int i;
	for(i=0; i<this.getElems().length; i++){ // 逐个比较 2 个对象中的元素
		if(((YStack) stack2).getElems()[i] != this.getElems()[i]){
			return false;
		}
	}	
	if(i==(this.getElems().length){ // 2 个对象相同,返回 true
		return true;
	}
}

编写测试用例及其执行结果为,

@Test
public void testPush1(){
	YStack ystack = new YStack();
	ystack.push(1);
	YStack ystack2 = new YStack();
	ystack2.push(1);
	Assert.assertEquals(ystack, ystack2); // 返回为 true
	Assert.assertSame(ystack, ystack2); // 返回为 false
}
@Test
public void testPush2(){
	YStack ystack = new YStack();
	ystack.push(1);
	YStack ystack2 = ystack;
	Assert.assertEquals(ystack, ystack2); // 返回为 true
	Assert.assertSame(ystack, ystack2); // 返回为 true
}
6. 模式匹配 assertThat

assertThat 函数判断给定的值或者对象是否满足给定的匹配。这里的第一个参数反泛型 actual 可以指代任何需要比较数据类型,而第二个参数 matcher 指代要匹配模式,该参数的获取需要调用 org.hamcrest.CoreMatcher 的函数。

public static void assertThat(T actual, Matcher<? super T> matcher) 
public static void assertThat(String reason, T actual, Matcher<? super T> matcher) 

例 1,使用函数 is() 来判断变量 a 是否是等于 0。

@Test
public void testANYTHING1(){
    int a = 1;
    // 需要引入 import org.hamcrest.CoreMatcher
	Assert.assertThat("a is not equal to 0!", a, CoreMatcher.is(0));	
}

例 2,使用函数 containsString()startsWiths() 来判断字符串是否 1)包含字符串 ab 且 2)以字符串 a 开头。一旦不满足匹配,则会提供更加完备的报错信息。

@Test
public void testANYTHING2(){
	String str = "aaa";
	Assert.assertThat(
	  "aaaa is not matched", str, 
	  CoreMatchers.allOf(CoreMatcher.containsString("ab"), CoreMatcher.startsWith("a"))
	);	// AllOf 的 allOf 函数提供逻辑与的功能
}

JUnit 中的断言表达式(Assertion)_第2张图片

除了上述的 2 个例子,CoreMatcher 类还有其他的函数也可以尝试一下,如 hasItem()endsWith()notNullValue() 等。

7. 直接报错 fail

当我们需要直接使测试用例失败时,可以使用 fail() 函数,它将直接抛出 AssertionError 的异常。

public static void fail(String message)
public static void fail()

你可能感兴趣的:(java,断言,Assertion,JUnit)