JUnit 入門(六) - 測試設備(Test fixture)

来源:互联网 发布:单片机晶振电路的作用 编辑:程序博客网 时间:2024/06/10 14:51
測試設備(Test fixture)是測試時都會用到的一組固定物件,說是固定物件,是表示這個物件在每次測試開始時都處於一個固定的初始狀態,每個測試方法要用到這組物件時,都由這個狀態開始操作起。

在JUnit中,我們定義一個測試案例(Test case),而在測試案例中,我們可以定義setUp()與tearDown()這兩個方法來建立測試設備與拆除測試設備,我們直接使用個簡單的例子來說明何時使用這兩個方法。

首先我們定義一個簡單的類別,它可以支援物件的檔案寫入與讀出:
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.*;import java.io.*; public class ObjectIOManager {    private String _filename;     public ObjectIOManager(String filename) {        _filename = filename;    }     // 讀出檔案中的物件資訊    public Object[] readObjects() {        ObjectInputStream objInput = null;        ArrayList students = new ArrayList();         try {            objInput = new ObjectInputStream(new FileInputStream(_filename));             System.out.print("Reading data from " + _filename + " ... ");            try {                while(true)                    students.add(objInput.readObject());            }            catch(EOFException e) {}             objInput.close();            System.out.println("done");        }        catch(ClassNotFoundException e) {            e.printStackTrace();        }        catch(IOException e) {            e.printStackTrace();        }        return students.toArray();    }     // 寫入物件至檔案中    public void writeObjects(Object[] objs) {        ObjectOutputStream objOutput = nulltry {            objOutput = new ObjectOutputStream(new FileOutputStream(_filename));             System.out.print("Writing data to " + _filename + " ... ");            for(int i = 0; i < objs.length; i++)                objOutput.writeObject(objs[i]);            objOutput.flush();            objOutput.close();            System.out.println("done");        }        catch(IOException e) {            e.printStackTrace();        }     }}


我們要測試這個類別是否如我們所設計般正常工作,我們先測試可不可以寫字串物件至檔案中再讀出,然後測試一個實作Serializable的物件是否可以寫入檔案再讀出,這個實作Serializable的類別我們定義如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.*; public class WritableObject implements Serializable {  private String _name;   public WritableObject(String name) {    _name = name;  }    public boolean equals(Object obj) {    if(_name.equals(((WritableObject)obj)._name))        return true;    else        return false;  }}


我們撰寫一個測試案例以進行測試:
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
import junit.framework.TestCase; public class ObjectIOManagerTest extends TestCase {     public ObjectIOManagerTest(String arg0) {        super(arg0);    }     public void testSimpleObjectIO() {        ObjectIOManager manager = new ObjectIOManager("test.dat");        String[] simpleObjects = {"Test1", "Test2", "Test3", "Test4"};        manager.writeObjects(simpleObjects);        Object[] objs = manager.readObjects();        for(int i = 0; i < simpleObjects.length; i++)            assertEquals(simpleObjects[i], (String)objs[i]);    }        public void testStudentObjectIO() {        ObjectIOManager manager = new ObjectIOManager("test.dat");        String[] simpleObjects = {"Test1", "Test2", "Test3", "Test4"};        WritableObject[] writable = new WritableObject[simpleObjects.length];        for(int i = 0; i < simpleObjects.length; i++)            writable[i] = new WritableObject(simpleObjects[i]);        manager.writeObjects(writable);        Object[] objs = manager.readObjects();        for(int i = 0; i < writable.length; i++)            assertEquals(writable[i], (WritableObject)objs[i]);        }     public static void main(String[] args) {        junit.textui.TestRunner.run(ObjectIOManagerTest.class);    }}


在testSimpleObjectIO()與testStudentObjectIO()這兩個方法中,很顯然的有重複的程式碼,它們是可以重複使用的物件,我們將這些重複的程式碼重新撰寫有setUp()方法中,我們重新改寫如下:
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
39
40
41
42
43
import junit.framework.TestCase; public class ObjectIOManagerTest extends TestCase {    private ObjectIOManager _manager;    String[] _simpleObjects = {"Test1", "Test2", "Test3", "Test4"};         public ObjectIOManagerTest(String arg0) {        super(arg0);    }     // 設定測試設備    protected void setUp() throws Exception {        super.setUp();        _manager = new ObjectIOManager("test.dat");    }     // 拆除測試裝備      protected void tearDown() throws Exception {        super.tearDown();        _manager = null;    }          public void testSimpleObjectIO() {        _manager.writeObjects(_simpleObjects);        Object[] objs = _manager.readObjects();        for(int i = 0; i < _simpleObjects.length; i++)            assertEquals(_simpleObjects[i], (String)objs[i]);    }        public void testStudentObjectIO() {        WritableObject[] writable = new WritableObject[_simpleObjects.length];        for(int i = 0; i < _simpleObjects.length; i++)            writable[i] = new WritableObject(_simpleObjects[i]);        _manager.writeObjects(writable);        Object[] objs = _manager.readObjects();        for(int i = 0; i < writable.length; i++)            assertEquals(writable[i], (WritableObject)objs[i]);        }     public static void main(String[] args) {        junit.textui.TestRunner.run(ObjectIOManagerTest.class);    }}


在上面的程式中,我們將字串陣列物件_simpleObjects設定為field,這樣可以避免每次都生成新的字串物件,而_manager則撰寫在setUp()方法中,setUp()方法會在每一次執行testXXXX()方法前呼叫,以建立一些測試裝備物件,而tearDown()會在每一次testXXXX()方法執行完畢後呼叫,以拆除測試裝備物件,在這個程式中使用tearDown()比較沒有意義,它只是將_manager參考至null物件,然後對於一些物件,例如該物件涉及到網路連線或資料庫連線時,可以在tearDown()中撰寫一些關閉連線或是關閉資源的程式,這時就顯示tearDown()的重
要。

注意到setUp()與tearDown()方法在每一次testXXXX()執行的前後都會被調用,所以不要被_manager設定為field而迷惑了,在testXXXX()開始執行時,測試設備都會重新產生一組測試裝備物件,所以您的每一個testXXXX()都會得到新的測試裝備物件,這個測試裝備物件與前一次testXXXX()執行時的裝備物件是沒有關係的。
原创粉丝点击