Dashboard > OpenSource Project > ... > JUnit > JUnit Intro - Test fixture
OpenSource Project Log In   View a printable version of the current page.
JUnit Intro - Test fixture
Added by minqing, last edited by minqing on Sep 26, 2004  (view change)
Labels: 
(None)

Reference by JavaWorld,caterpillar

測試設備(Test fixture)是測試時都會用到的一組固定物件,說是固定物件,是表示這個物件在每次測試開始時都處於一個固定的初始狀態,每個測試方法要用到這組物件時,都由這個狀態開始操作起。

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

首先我們定義一個簡單的類別,它可以支援物件的檔案寫入與讀出:

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 = null;
        try {
            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的類別我們定義如下:

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;
  }
}


我們撰寫一個測試案例以進行測試:

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()方法中,我們重新改寫如下:

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()執行時的裝備物件是沒有關係的。

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.1.5a Build:#411 Mar 16, 2006) - Bug/feature request - Contact Administrators