作者: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中去。