追求代碼質量: 可重復的系統測試
發表于:2009-06-22來源:作者:點擊數:
標簽:代碼質量系統
在測試加入到 servlet 容器的 Web 應用程序時,編寫符合邏輯的可重復的測試尤其需要技巧。在 Andrew Glover 的提高代碼 質量 的這個續篇中,他介紹了 Cargo,這是一個以通用方式自動化容器管理的 開源 框架,有了這個框架,您可以隨時編寫符合邏輯的可重復的
在測試加入到 servlet 容器的 Web 應用程序時,編寫符合邏輯的可重復的測試尤其需要技巧。在 Andrew Glover 的提高代碼
質量的這個續篇中,他介紹了 Cargo,這是一個以通用方式自動化容器管理的
開源框架,有了這個框架,您可以隨時編寫符合邏輯的可重復的
系統測試。
在本質上,像
JUnit 和 TestNG 一樣的
測試框架方便了可重復性測試的創建。由于這些框架利用了簡單 Boolean 邏輯(以 assert 方法的形式)的
可靠性,這使得無人為干預而運行測試成為可能。事實上,自動化是測試框架的主要優點之一 —— 我能夠編寫一個用于斷言具體行為的相當復雜的測試,且一旦這些行為有所改變,框架就會報告一個人人都能明白的錯誤。
利用成熟的測試框架會帶來框架 可重復性的優點,這是顯而易見的。但邏輯的 可重復性卻取決于您。例如,考慮創建用于驗證 Web 應用程序的可重復測試的情況,一些 JUnit 擴展框架(如 JWebUnit 和
HttpUnit)在協助自動化的
Web 測試方面非常好用。但是,使測試的 plumbing 可重復則是
開發人員的任務,而這在部署 Web 應用程序資源時很難進行。
實際的 JWebUnit 測試的構造過程相當簡單,如清單 1 所示:
清單 1. 一個簡單的 JWebUnit 測試
package test.come.acme.widget.Web;
import net.sourceforge.jwebunit.WebTester;
import
junit.framework.TestCase;
public class WidgetCreationTest extends TestCase {
private WebTester tester;
protected void setUp() throws Exception {
this.tester = new WebTester();
this.tester.getTestContext().
setBaseUrl("http://localhost:8080/widget/");
}
public void testWidgetCreation() {
this.tester.beginAt("/CreateWidget.html");
this.tester.setFormElement("widget-id", "893-44");
this.tester.setFormElement("part-num", "rt45-3");
this.tester.submit();
this.tester.assertTextPresent("893-44");
this.tester.assertTextPresent("su
clearcase/" target="_blank" >ccessfully created.");
}
}
這個測試與一個 Web 應用程序通信,并試圖創建一個基于該交互的小部件。該測試隨后校驗此部件是否被成功創建。讀過本系列之前部分的讀者們也許會注意到該測試的一個微妙的可重復性問題。您注意到了嗎?如果這個
測試用例連續 運行兩次會怎樣呢?
改進代碼質量
不要錯過了 Andrew 的附隨的 討論
論壇,獲取有關代碼編寫方法、測試框架及編寫高質量代碼的幫助。
由這個小部件實例(即,widget-id)的驗證方面可以判斷出,可以
安全地做出這樣的假設,即此應用程序中的
數據庫約束很可能會阻止創建一個已經存在的額外的小部件。由于缺少了一個在運行另一個測試前刪除此測試用例的目標小部件的過程,如果再連續運行兩次,這個測試用例非常有可能會失敗。
幸運的是,如前面文章中所探討的那樣,有一個有助于數據庫-依賴性(database-dependent)測試用例可重復性的機制 —— 即 DbUnit。
使用 DbUnit
改進 清單 1 中的測試用例來使用 DbUnit 是非常簡單的。DbUnit 只需要一些插入數據庫的數據和一個相應的數據庫連接,如清單 2 所示:
清單 2. 用 DbUnit 進行的數據庫-依賴性測試
package test.come.acme.widget.Web;
import
java.io.File;
import java.io.IOException;
import java.
sql.Connection;
import java.sql.DriverManager;
import java.sql.
SQLException;
import org.
dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import net.sourceforge.jwebunit.WebTester;
import junit.framework.TestCase;
public class RepeatableWidgetCreationTest extends TestCase {
private WebTester tester;
protected void setUp() throws Exception {
this.handleSetUpOperation();
this.tester = new WebTester();
this.tester.getTestContext().
setBaseUrl("http://localhost:8080/widget/");
}
public void testWidgetCreation() {
this.tester.beginAt("/CreateWord.html");
this.tester.setFormElement("widget-id", "893-44");
this.tester.setFormElement("part-num", "rt45-3");
this.tester.submit();
this.tester.assertTextPresent("893-44");
this.tester.assertTextPresent("successfully created.");
}
private void handleSetUpOperation() throws Exception{
final IDatabaseConnection conn = this.getConnection();
final IDataSet data = this.getDataSet();
try{
DatabaseOperation.CLEAN_INSERT.execute(conn, data);
}finally{
conn.close();
}
}
原文轉自:http://www.anti-gravitydesign.com