極限編程方法的興起將測試驅動開發和持續集成帶入了主流 Java 開發實踐。如果沒有采用正確的工具,在 Java 服務器端開發中使用這些技術很快會成為一場噩夢。在本文中,軟件開發人員 Philippe Girolami 描述了如何處理持續集成,以及如何聯合使用 DbUnit 和 JUnit,以便在每次測試之前通過設置數據庫狀態來端到端地控制測試環境。
軟件開發中重要的一種做法是測試。通過推薦測試優先的開發和持續集成,極限編程(Extreme Programming,XP)將這一邏輯推到了極限,在這里測試是盡可能頻繁地自動進行的。不過,大多數非 XP 開發都進行了某種形式的測試,也許稱為非回歸測試、黑箱測試、功能測試或者其他的名字。很多項目使用關系數據庫存儲數據,因而所有測試策略都需要考慮在每次測試過程中數據庫中所發生的事情:如果測試使測試數據庫處于不一致狀態,那么后面的所有測試都可能失敗!一種避免這種情況的方法是在每次測試之前將數據庫狀態設為一個已知的相關狀態。在本文中,我將介紹我們的小組是如何結合 JUnit 使用 DbUnit 做到這一點的,以及如何用 Anthill 自動生成測試報告。盡管設置看起來很費功夫,但是實際上并不是這樣,并且它已經證明自己是一個有用的工具。
表示數據庫內容
DbUnit 擴展了 JUnit,它使數據庫在測試之間處于一種已知狀態,幫助避免造成后面的測試失敗或者給出錯誤結果的問題,如果測試會破壞數據庫會出現這些問題。它可以讀取表的內容并用 FlatXmlDataSet 將它在存儲為 XML,如清單 1 所示:
清單 1. FlatXmlDataSet 示例
<dataset> <OPERATOR ID='APC (Washington/Baltimore)' CODE='ABC5APC' ENCODED_STRING='aabbclearcase/" target="_blank" >cc'/> <OPERATOR ID='ASA Ritabell' CODE='ABC6ASA R' ENCODED_STRING='bbccdd'/> <OPERATOR ID='Advanced Info. Service PLC' CODE='ABC1Adva' ENCODED_STRING='ccddee'/> <OPE_OPERATOR ID='Aerial Communications Inc.' CODE='ABC2Aeri' ENCODED_STRING='ddeeff'/></dataset>
這個數據集表示名為 OPE_OPERATOR 的數據庫表中的三列,如表 1 中后三行所描述的:
表 1.中數據的表定義
OPE_OPERATOR | ||
ID | INT | |
CODE | VARCHAR | |
ENCODED_STRING | VARCHAR |
每個 XML 實體標識數據庫中的一個表,而每個屬性表示一列的值。
在自己的項目中設置 DbUnit
設置 DbUnit 很簡單。有關項目文件下載的信息,請參閱 參考資料的內容。可以將所有三個 JAR 文件加到項目的編譯目標中以進行測試。
如果是一個多 schema 環境,那么要將 DbUnit.qualified.table.names 屬性設置為 true 。使用 Oracle 的開發團隊通常是這種情況:每一個用戶有自己的 schema。這可以使您免于在每個表名前面加上 schema 名稱的前綴,并可以在團隊中共享測試數據。
DbUnit 使您可以容易地執行 JDBC 查詢并獲取它們的值。使用 DbUnit JDBC 包裝器而不是純粹的 JDBC 有幾個理由:
可以用 SQL 查詢創建一個 Dataset ,并使用 DbUnit 的 assertion(斷言)方法(在后面描述)。
可以用 SQL 查詢創建一個 Dataset ,并將它保存為一個 FlatXmlDataSet 。可以在以后將它重新裝載到數據庫中。
可以容易地從任何行中獲取列的內容,無需進行迭代。
首先檢查行計數是否為 1,然后檢查第一行(從 0 開始計)中, FK_OTHER_ID 列包含數字 1234。
使用 assert 方法檢查數據庫內容
DbUnit 有斷言方法,可以用于比較表的兩組數據或者表的兩個表示。如果需要在運行一次測試而不是多次查詢后檢查表的確切內容,一般會用它們。
創建數據
根據數據庫的大小、架構的穩定性如何以及開發的進展情況,可能要從頭開始創建或者從生產數據庫中拷貝測試數據。
如果導出一個完整的生產數據庫,可能必須要刪除過多的行--或者像在這里一樣,用一個查詢而不是直接用連接創建一個數據集。提取本身對于很大的表來說可能是個問題--我們的小組只能用查詢提取某些表的一部分。從表中刪除行也有些問題,主要涉及到瀏覽所有外鍵并保證數據的一致性的困難。
添加測試數據
添加測試數據有時可能乏味的。我們的經驗是度過正確添加數據的初困難階段后,可以達到這樣一個層次,不僅添加數據變得容易了,而且對數據庫結構的理解也有了極大提高。
即使使用 Enterprise JavaBeans (EJB) 技術隱藏數據庫,這種第一手知識仍然非常有用。因為開發人員對數據庫有了更好的理解,因而可以更快地檢查其內容,從而使調試更容易了。這在重構代碼和數據庫時又會給予我們極大的幫助。
用 DbUnit 和 JUnit 創建基類
好的 JUnit 實踐鼓勵開發人員擴展基類 TestCase 以獲得特化(specialization)行為。DbUnit 提供了自己的特化-- DatabaseTestCase ,通過它可以特化行為以滿足自己的需要。
首先,創建一個名為 ProjectDatabaseTestCase 的基本測試用例,并向它添加實用工具方法,然后,重新定義 setUp() 和 teardown() ,以使它們能夠創建和銷毀通過 DbUnit 到數據庫的連接。