Spring: A Developer's Notebook筆記和小結(5)

/**
作者:Willpower
來源:Rifoo Technology(
http://www.rifoo.com
時間:2006-01-05
備註:轉載請保留以上聲明
**/

測試驅動開發的思想要求大家在開發之間先寫測試,這裏作者以一個簡單的單元測試來完成第一章起步篇的結束。

作者在文中提到,使我們的測試能自動化會給我們開發以很大的自信心。另外,能夠很好的包容變化。
EJB和struts都不能很好的使用測試驅動開發來做,因爲它們加載都很麻煩而且很難去通過mock來寫單元測試。

作者給我們推薦Spring,每個對象都能在Spring的容器外去運行,這是一個優勢。而且容器本身也是輕量級的,啓動的過程是微乎其微。這對於我們測試是巨大的便利。Spring也鼓勵我們開發人員通過測試在我們的系統中去設計鬆耦合的模塊/組件。

可以把單元測試看成是我們應用程序的另一個客戶端。這個測試用來斷言什麼是正確的或者我們應用應該是正常運行的。例如,如果添加一個對象到一個list列表中,那麼這個list的size就應該增加1。所以當我們創建一個新特徵或對一箇舊特徵進行調試時,我們可以很容易獨立去運行一個test。可以把test作爲整個build的全過程來運行。如果test失敗,那麼整個build也失敗。

每個test case都是TestCase類的一個子類。我們看下面這個測試RentABike接口的單元測試代碼:

Example 1-11. RentABikeTest.java
public class RentABikeTest extends TestCase{

  private RentABike rentaBike;

  public void setUp( ) {
    rentaBike = new ArrayListRentABike("Bruce's Bikes");
  }
 
  public void testGetName( ) {
    assertEquals("Bruce's Bikes", rentaBike.getStoreName( ));
  }
 
  public void testGetBike( ) {
    Bike bike = rentaBike.getBike("11111");
    assertNotNull(bike);
    assertEquals("Shimano", bike.getManufacturer( ));
  }

  public void testGetBikes( ) {
    List bikes = rentaBike.getBikes( );
    assertNotNull(bikes);
    assertEquals(3, bikes.size( ));
  }
}


這個代碼簡單說明一下,在初始化

setUp是testcase的初始化方法,這裏創建一個數組用來存放租用的山地車。testGetName是用來測試RentABikegetName這個方法的ArrayListRentABike的時候,傳入的Bruce's Bikes爲參數,這個就是storename。然後初始化了三個山地車對象到這個數組中。

bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, "Fair"));
bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222", 12, "Excellent"));
bikes.add(new Bike("Trek", "6000", 19, "33333", 12.4, "Fair"));

這裏用assertEquals來強行斷言我們得到的山地車是否是相等。如果相等,比如編號爲11111的山地車名稱應該是Shimano,如果這個時候返回的對象不是Shimano,那麼說明這個測試不是我們預料的結果,測試則失敗。否則,測試就會成功。
更多單元測試的基礎請參看junit in action這本書。

下面我們要修改前面章節的ANT部署腳本,代碼如下:
Example 1-12. build.xml
<property name="test.class.dir" value="${test.dir}/classes"/>
<path id="bikestore.class.path">
  <fileset dir="${spring.dir}/dist">
      <include name="*.jar"/>
  </fileset>
  <pathelement location="${spring.dir}/lib/jakarta-commons
        /commons-logging.jar"/>
  <pathelement location="${spring.dir}/lib/log4j/log4j-1.2.8.jar"/>
  <pathelement location="${spring.dir}/lib/j2ee/servlet.jar"/>
  <dirset dir="${basedir}"/>
  <dirset dir="${class.dir}"/>
</path>
<path id="junit.class.path">
  <path refid="bikestore.class.path"/>
  <pathelement location="PATH_TO_JUNIT"/>
</path>
<target name="compile.test" depends="init"
        description="Compiles all unit test source">
    <javac srcdir="${test.dir}"
          destdir="${test.class.dir}"
          classpathref="junit.class.path"/>
</target>


這一段腳本提供了編譯test代碼的功能,這個任務名爲compile.test。大家注意這一段,<pathelement location="PATH_TO_JUNIT"/>。我們要添加環境變量到junit包的路徑,放可執行該腳本。

我們最後來看看運行test的腳本:

<target name="test" depends="compile.test, compile"
        description="Runs the unit tests">
    <junit printsummary="withOutAndErr" haltonfailure="no"
          haltοnerrοr="no" fork="yes">
        <classpath refid="junit.class.path"/>
        <formatter type="xml" usefile="true" />
        <batchtest todir="${test.dir}">
          <fileset dir="${test.class.dir}">
            <include name="*Test.*"/>
          </fileset>
        </batchtest>
    </junit>
  </target>


最終,單元測試的結果如下:
Buildfile: build.xml

init:

compile:

compile.test:

test:
  [junit] Running RentABikeTest
  [junit] Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0.36 sec

BUILD SUCCESSFUL
Total time: 2 seconds

總結:ANT能夠構建整個應用程序,包括單元測試部分。如果一個test case失敗了,我們需要讓它成功,才能使應用整個能成功構建起來。這種方式可以幫助我們找到容易忽略的小錯誤,這些小錯誤將來也許成了很大的錯誤。

第一章的所有筆記就告一段落了,下一章作者會帶着我們一起去體驗Spring,使用Spring的WebMVC給我們的應用創建一個真實的用戶接口,也會告訴大家如何將現有的用戶接口集成到Spring中去。

發佈了84 篇原創文章 · 獲贊 2 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章