摘要 不能因為Java Micro Edition缺乏反射能力就說Java Micro Edition開發人員無法利用JUnit風格測試的優點。其實,藉助於具有JUnit風格的其它一些架構和工具,Java ME開發人員仍然能夠改進Java ME應用程式的開發品質。本系列文章(兩篇)正是想詳細探討J2MEUnit和JMUnit這兩個開源架構在Java ME單元測試開發中的應用。
一、引言
如今,JUnit測試正在逐漸成為大多數Java標準版(SE)和企業版(EE)應用程式開發中的基本組成部分-對於那些積極擁護測試驅動開發者尤其如此。Kent Beck和Eric Gamma的最初的Smalltalk架構變得如此流行和成功,以至於它被移植到很多程式設計語言中,包括Ada(AUnit)、C#(NUnit)、Python(PyUnit),甚至還有Fortran(fUnit)。實踐證明,Java的JUnit是所有的單元測試架構中最成功的並且已經派生出許多JUnit"變種"(以各種"擴充"的形式),這些架構最終協助在從多線程Java應用程式到進階企業Java應用程式的主流開發中實現單元測試。
然而,使用JUnit或找到一種JUnit擴充用於Java Micro Edition開發一直以來卻是很難的事情。須知,JUnit架構依賴於Java反射API。由於Java ME環境中還不支援反射API,所以,典型的很大程度上依賴於反射的JUnit工具還不能協助進行Java ME開發。儘管如此,已經出現兩個專門針對裝置應用程式開發人員構建的Java ME JUnit擴充。值得注意的是,隨著NetBeans和NetBeans Mobility 5.5的發行,NetBeans和NetBeans Mobility Pack正在計劃合并一個Java ME JUnit風格的架構。這種新版本的IDE將以一種更為利索的方式在你的Java ME應用程式中加入單元測試。
本文將通過使用Java ME JUnit架構向你介紹JUnit測試;通過本文,你會發現,如何擷取這些工具,如何使用它們進行測試以及如何使用它們來構建品質更好的軟體。
二、擷取Java ME單元測試架構
如今,市場上存在兩個可用的JavaME JUnit測試架構,它們是J2MEUnit和JMUnit。這兩個工程都是可自由下載的開源架構,你可以從SourceForge.net上下載一個打包檔案。
然而,這兩個開源工程的工程主管(Elmar Sonnenschein和Brunno Silva,分別維護J2MEUnit和JMUnit),正在計劃把這兩個架構合并為一個。新的工程將在J2MEUnit工程基礎上得到進一步鞏固。根據Sonnenschein本人的說法,"因為更多的現有使用者的工程都是基於SourceForge上的J2MEUnit架構;所以,我們計劃基於Brunno的JMUnit 2.0建立一個J2MEUnit 2.0發行版本。"Silva在一次最近的新聞發布會上聲稱在今年年底可能無法完成產品的合并和一個2.0版本的發行。Silva進一步建議說,新的工程"不想破壞這兩個架構的目前使用者的原有代碼,因此,原始代碼會繼續存在,只是不再建議使用。新的單元架構應該展現出兩個架構-JMUnit和J2MEUnit-各自的特色。"
三、一個簡單的應用程式範例
在分析各種單元測試架構之前,你需要一些簡單的代碼以備測試之用。在這個例子中,下面這個簡單的Conversion類能夠用於建立並測試Java ME單元測試。
public class DistanceConversion {
public static int feetToMeters(int ft){
return (ft * 3048)/10000;
}
public static int metersToFeet(int meters){
return (meters*3281)/1000;
}
public static int milesToKM(int miles){
return (miles*1609)/1000;
}
public static int kmToMiles(int km){
return (km*6214)/10000;
}
}
public class TemperatureConversion {
public static float fahrenheitToCelsius (float degrees){
return ((degrees-32)/9)*5;
}
public static float celsiusToFahrenheit (float degrees){
return ((degrees * 9)/5)+32;
}
public static boolean isHotter (float degFaren, float degCel){
return ((fahrenheitToCelsius(degFaren))-degCel) > 0;
}
public static boolean isCooler (float degFaren, float degCel){
return ((fahrenheitToCelsius(degFaren))-degCel) < 0;
}
}