Reference by JavaWorld
,caterpillar
JUnit將測試不通過的結果區分為失敗(failure)與錯誤(error),失敗指的是斷言結果為false,也是您所預期應該成功的測試失敗了,而錯誤指的是意料之外的異常,這個異常是您沒有考慮到的,也許會造成程式的錯誤,或是程式的終止,例如ArrayIndexOutOfBoundsException就是一個錯誤。
有時候您設計好一個類別,在測試的時候您注重於一些斷言的測試,然而程式中可能有一些部份可能是您沒有考慮到的,JUnit的錯誤就是在幫您捕捉這些沒有考慮到的部份,我們使用一個簡單的例子作為說明,首先我們設計一個類別:
public class SimpleArray {
private int[] _array;
public SimpleArray() {
_array = new int[10];
}
public SimpleArray(int length) {
_array = new int[length];
}
public void set(int index, int value) {
_array[index] = value;
}
public int get(int index) {
return _array[index];
}
public int length() {
return _array.length;
}
}
為了測試這個簡單的類別,我們撰寫一個測試案例:
import junit.framework.TestCase;
public class SimpleArrayTest extends TestCase {
private SimpleArray _simpleArray;
public SimpleArrayTest(String arg0) {
super(arg0);
}
protected void setUp() throws Exception {
super.setUp();
_simpleArray = new SimpleArray();
}
protected void tearDown() throws Exception {
super.tearDown();
_simpleArray = null;
}
public void testSetGet() {
for(int i = 0; i < _simpleArray.length(); i++)
_simpleArray.set(i, i);
for(int i = 0; i < _simpleArray.length()+1; i++)
assertTrue(i == _simpleArray.get(i));
}
public static void main(String[] args) {
junit.textui.TestRunner.run(SimpleArrayTest.class);
}
}
我故意在測式get()方法時存取超過陣列長度的元素,來看一下測試的結果如何?
.E
Time: 0.01
There was 1 error:
1) testSetGet(SimpleArrayTest)java.lang.ArrayIndexOutOfBoundsException: 10
at SimpleArray.get(SimpleArray.java:17)
at SimpleArrayTest.testSetGet(SimpleArrayTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at SimpleArrayTest.main(SimpleArrayTest.java:28)
FAILURES!!!
Tests run: 1, Failures: 0, Errors: 1
測試指出了一個錯誤,並告知了這個錯誤來自於存取超過陣列邊界,這表示您的這個類別最好為它加上邊界檢查了。
如果您的類別在執行某些功能時,指明必須處理某些例外,例如IOException,您可以在testXXXX()中使用try.....catch來處理它,或是將之丟出,由呼叫testXXXX()的來源來處理它,下面這個程式是個實例,假設java.io.FileReader是您所設計的類別,我們提供一個測試檔案test.txt,當中只撰寫了一個字元'1':
import java.io.*;
import junit.framework.TestCase;
public class FileReaderTest extends TestCase {
private FileReader _reader;
public FileReaderTest(String arg0) {
super(arg0);
}
public void setUp() throws FileNotFoundException {
_reader = new FileReader("test.txt");
}
public void tearDown() throws IOException {
_reader.close();
}
public void testRead() throws IOException {
assertTrue('1' == _reader.read());
}
public void testClose() throws IOException {
_reader.close();
try {
_reader.read();
fail("reading file after closed and didn't throw IOException");
}
catch(IOException e) {
}
}
public static void main(String[] args) {
junit.textui.TestRunner.run(FileReaderTest.class);
}
}
注意到 testClose() 這個方法所進行的測試,有時候您所測試的可能是一個預期會丟出的例外,您想要看看當錯誤的情況成立時,是不是真會丟出例外,例如 testClose() 測試 FileReader 在 close() 之後如果再 read(),是不是會如期丟出IOException,我們先行在方法中用try....catch捕捉了這個例外,如果沒有如期丟出例外,則不會被catch捕捉,而程式流程繼續往下,執行到 fail() 陳述,這表示例外處理沒有發生,我們此時主動丟出一個失敗(failure),表示程式的執行並不如我們所預期的。