摘要:存儲(chǔ)過(guò)程的測(cè)試是一項(xiàng)非常繁瑣的工作,一些數(shù)據(jù)庫(kù)產(chǎn)品雖然提供了一些工具能夠統(tǒng)計(jì)出存儲(chǔ)過(guò)程的執(zhí)行時(shí)間、返回記錄數(shù)等信息,但是這些工具不能進(jìn)行批量的重復(fù)的測(cè)試,而且測(cè)試結(jié)果的顯示也不直觀。針對(duì)這些問(wèn)題,介紹了在 Junit 測(cè)試框架下實(shí)現(xiàn)存儲(chǔ)過(guò)程自動(dòng)化測(cè)試的方法,利用JUnit的自動(dòng)化和生成的測(cè)試代碼的復(fù)用,可實(shí)現(xiàn)存儲(chǔ)過(guò)程的回歸測(cè)試,利用XML技術(shù)存儲(chǔ)測(cè)試用例和測(cè)試結(jié)果,實(shí)現(xiàn)測(cè)試用例和測(cè)試代碼分離,提高了測(cè)試效率,為開發(fā)人員提供了直觀的測(cè)試結(jié)果。
關(guān)鍵詞:存儲(chǔ)過(guò)程;自動(dòng)化測(cè)試;測(cè)試用例;Junit框架;XML
中圖分類號(hào): TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2009)36-10252-02
Research on Automated Testing of Stored Procedure
MA Zhu-gen
(Department of Computer Science and Technology, Huaihua University, Huaihua 418008, China)
Abstract: Stored procedure test is an extremely tedious work.Some database products provide some tools to be able to make the statistics of the execution time of a stored procedure, the number of records and other information, but these tools can not carry on batch and repeated testing. Moreover,the test result is not intuitive. This paper describes the implementation scheme of stored procedure automation test under the junit framework.The code-reuse technique based automatic testing framework of Junitrealizes the regression testing of procedure. The test cases are described and organized using XML to realize the separation between code and data in order to improve efficiency of test, and the test result using XML provides developers with an intuitive notation.
Key words:stored procedure; software automation testing; test case; junit framework; XML
軟件測(cè)試是保證軟件質(zhì)量的重要手段,軟件測(cè)試在整個(gè)項(xiàng)目開發(fā)中所占的比重也越來(lái)越大。隨著軟件規(guī)模的擴(kuò)大和軟件復(fù)雜性的提高,軟件測(cè)試技術(shù)不斷發(fā)展,自動(dòng)化測(cè)試技術(shù)得到廣泛應(yīng)用,并逐漸成為軟件測(cè)試發(fā)展的方向。單元測(cè)試是軟件開發(fā)過(guò)程中要進(jìn)行的最基本的測(cè)試活動(dòng),是確保其他測(cè)試能夠順利進(jìn)行的基礎(chǔ)。隨著增量開發(fā)模式和重構(gòu)技術(shù)的發(fā)展,軟件自動(dòng)化測(cè)試工具JUnit也隨之產(chǎn)生。目前Junit已經(jīng)成為Java程序單元測(cè)試框架的標(biāo)準(zhǔn),已有多種對(duì)其進(jìn)行擴(kuò)展的自動(dòng)化測(cè)試工具[1]。
存儲(chǔ)過(guò)程被廣泛應(yīng)用在各種與數(shù)據(jù)庫(kù)相關(guān)的應(yīng)用系統(tǒng)中。在開發(fā)階段,對(duì)存儲(chǔ)過(guò)程進(jìn)行測(cè)試是必不可少的工作。通常的測(cè)試過(guò)程是由測(cè)試人員通過(guò)命令窗口執(zhí)行命令,再將命令窗口中的結(jié)果信息拷貝下來(lái),保存到一個(gè)文件里,在以后再進(jìn)行分析或者比較。測(cè)試工作也可以使用類似Rapid SQL等圖形化的工具來(lái)輔助做一些工作,但能完成的測(cè)試工作量較少。這種大部分依靠手工進(jìn)行的存儲(chǔ)過(guò)程的單元測(cè)試存在很多缺點(diǎn),如測(cè)試效率低,無(wú)法重用,無(wú)法進(jìn)行自動(dòng)化的回歸測(cè)試,沒(méi)有直觀的測(cè)試結(jié)果,需要程序員手工整理測(cè)試結(jié)果并生成測(cè)試報(bào)告。針對(duì)這些問(wèn)題,本文在Eclipse中利用Junit測(cè)試框架來(lái)實(shí)現(xiàn)存儲(chǔ)過(guò)程測(cè)試的自動(dòng)化。
1 Juit的框架結(jié)構(gòu)
Junit是Erich Gamma和Kent Beck編寫的一個(gè)回歸測(cè)試框架,它是一個(gè)Java程序自動(dòng)測(cè)試的框架[2],用在軟件測(cè)試的單元測(cè)試階段,即Java對(duì)象類的功能測(cè)試。JUnit共有七個(gè)包,核心的包就是junit.framework和junit.runner。Framework包中包含了Junit測(cè)試類所需的所有基類,它是整個(gè)Junit的基礎(chǔ)框架[3],負(fù)責(zé)整個(gè)測(cè)試對(duì)象的構(gòu)架,Runner則負(fù)責(zé)測(cè)試驅(qū)動(dòng)。JUnit框架中主要有以下幾個(gè)對(duì)象類[4-5]:
1) Assert類,它提供在編寫測(cè)試時(shí)要用到的所有assert方法。當(dāng)條件成立時(shí)assert方法保持沉默,但若條件不成立就拋出異常。Assert類是TestCase的父類。
2) TestCase類
客戶測(cè)試類所要繼承的類,負(fù)責(zé)測(cè)試時(shí)對(duì)客戶類進(jìn)行初始化,以及測(cè)試方法調(diào)用。類中的主要方法有:setUp()用于如變量賦值等測(cè)試的結(jié)果處理,tearDown()用于如文件關(guān)閉等測(cè)試的結(jié)束處理,run()測(cè)試實(shí)例的執(zhí)行,并把測(cè)試結(jié)果放入測(cè)試結(jié)果對(duì)象TestResult中。
3) TestResult類
負(fù)責(zé)收集TestCase所執(zhí)行的結(jié)果。一般來(lái)說(shuō),用戶不需要對(duì)TestResult進(jìn)行操作,測(cè)試結(jié)果由系統(tǒng)提供的測(cè)試工具自動(dòng)輸出。
4) TestSuite類
TestSuite對(duì)象是測(cè)試實(shí)例的集合,負(fù)責(zé)包裝和運(yùn)行所有的TestCase。
2 存儲(chǔ)過(guò)程測(cè)試代碼的自動(dòng)生成
Junit測(cè)試的實(shí)現(xiàn)流程就是繼承TestCase類,然后重載它的一些重要方法,如setUp()、tearDown(),最后將這些對(duì)象組裝到一個(gè)Testsuite對(duì)象中,交由TestRunner來(lái)運(yùn)行。為了利用 JUnit 帶來(lái)的高效率,首先需要改變被測(cè)存儲(chǔ)過(guò)程的調(diào)用方式,即從手工調(diào)用改為使用 JDBC 來(lái)調(diào)用,把一個(gè)個(gè)存儲(chǔ)過(guò)程的調(diào)用寫成Java 代碼,以后需要進(jìn)行回歸測(cè)試時(shí),只需要運(yùn)行這些 Java測(cè)試代碼就可以了。但是直接使用 JUnit,也會(huì)是一個(gè)煩瑣的過(guò)程,因?yàn)楸仨氃诿慷螠y(cè)試代碼中編寫連接數(shù)據(jù)庫(kù)的代碼和調(diào)用存儲(chǔ)過(guò)程時(shí)的一大堆參數(shù)設(shè)置的代碼。對(duì)于存儲(chǔ)過(guò)程測(cè)試來(lái)說(shuō),這些代碼就顯得非常累贅了,于是設(shè)想把這些操作封裝為一個(gè)公用的類,只需要在測(cè)試代碼中提供數(shù)據(jù)庫(kù)連接信息、存儲(chǔ)過(guò)程名字和參數(shù)值就可以了,其他的工作由這個(gè)公用的類來(lái)處理。因此在實(shí)現(xiàn)存儲(chǔ)過(guò)程測(cè)試代碼的自動(dòng)生成過(guò)程中,首先必須要解決如何獲得存儲(chǔ)過(guò)程名和存儲(chǔ)過(guò)程參數(shù)以及在生成的測(cè)試代碼中如何運(yùn)行存儲(chǔ)過(guò)程,下面分別進(jìn)行討論。
2.1 存儲(chǔ)過(guò)程名和參數(shù)的獲取
在存儲(chǔ)過(guò)程測(cè)試代碼生成過(guò)程中,第一個(gè)問(wèn)題是要針對(duì)哪些存儲(chǔ)過(guò)程生成測(cè)試代碼。獲取存儲(chǔ)過(guò)程名可以有兩種方式,其一是由用戶手動(dòng)指定,其二是將儲(chǔ)過(guò)程名稱保存在文件中,由系統(tǒng)自動(dòng)從文件中分析出存儲(chǔ)過(guò)程名稱。這樣的文件可以是一個(gè)定義了 Java 常量的 .java 文件,也可以是一個(gè) .properties 文件。文件中可用\"=\"來(lái)定義存儲(chǔ)過(guò)程,系統(tǒng)將自動(dòng)把\"=\"右邊的部分識(shí)別為存儲(chǔ)過(guò)程的名稱。
要為存儲(chǔ)過(guò)程自動(dòng)生成測(cè)試代碼,有一個(gè)前提條件是被測(cè)試的存儲(chǔ)過(guò)程已經(jīng)在數(shù)據(jù)庫(kù)中創(chuàng)建。作為數(shù)據(jù)庫(kù)的對(duì)象,存儲(chǔ)過(guò)程的名稱、參數(shù)等信息也都有相應(yīng)的數(shù)據(jù)字典表存放。只要知道存儲(chǔ)過(guò)程的名字,可以查詢數(shù)據(jù)字典來(lái)獲取存儲(chǔ)過(guò)程的參數(shù)信息,如參數(shù)名稱、數(shù)據(jù)類型、長(zhǎng)度、出入?yún)㈩愋偷取R虼?,在測(cè)試代碼生成過(guò)程中可以根據(jù)存儲(chǔ)過(guò)程的名稱查詢數(shù)據(jù)庫(kù)的系統(tǒng)表來(lái)獲取參數(shù)信息,例如DB2 的 SYSCAT.ROUTINEPARMS表,Oracle 的 USER_ARGUMENTS 表或者SQLServer的SYSCOLUMNS 表等。
2.2 測(cè)試代碼中存儲(chǔ)過(guò)程的運(yùn)行
在已經(jīng)生成的測(cè)試代碼中,如果將大批的數(shù)據(jù)庫(kù)操作寫在測(cè)試代碼中顯然是不合適的,這樣會(huì)造成代碼的混亂和維護(hù)困難。因此考慮封裝一個(gè)類,用它專門來(lái)運(yùn)行存儲(chǔ)過(guò)程,它提供了以下主要方法:
1) SPProcesss (DBInfoObject dbConfig), 構(gòu)造函數(shù),根據(jù)傳入的數(shù)據(jù)庫(kù)配置信息,建立數(shù)據(jù)庫(kù)連接,初始化運(yùn)行環(huán)境;2) getSPParmList(String routineSchema , String routineName) 根據(jù)存儲(chǔ)過(guò)程模式和存儲(chǔ)過(guò)程名獲取參數(shù)列表;3) runStoredProcedure(StoredProcedureInfo spInfo) 運(yùn)行存儲(chǔ)過(guò)程,存儲(chǔ)過(guò)程信息包含在名為 StoredProcedureInfo 的類中。4) String (getDurationTime) 獲取存儲(chǔ)過(guò)程運(yùn)行時(shí)間;5) object getReturnedObject (int parmIndex)獲取存儲(chǔ)過(guò)程輸出參數(shù)的值。
其中的 StoredProcedureInfo是記錄存儲(chǔ)過(guò)程信息的類,包括存儲(chǔ)過(guò)程名、存儲(chǔ)過(guò)程參數(shù)列表等。因此,只需要首先創(chuàng)建存儲(chǔ)過(guò)程信息,然后調(diào)用 runStoredProcedure 方法即可運(yùn)行存儲(chǔ)過(guò)程。而這部分代碼也是自動(dòng)生成的,程序員真正需要做的就是修改調(diào)用參數(shù)的值。
3 改進(jìn)的Junit框架
采用Junit作為單元測(cè)試工具有許多優(yōu)點(diǎn),但也存在著不足。在實(shí)際的單元測(cè)試中,發(fā)現(xiàn)JUnit產(chǎn)生的測(cè)試代碼量是龐大的。為了提高測(cè)試代碼的復(fù)用,文獻(xiàn)[6]提出了一種改進(jìn)的自動(dòng)化單元測(cè)試框架。該框架設(shè)計(jì)的核心是實(shí)現(xiàn)測(cè)試用例與測(cè)試代碼的分離,運(yùn)用XML文件作為測(cè)試數(shù)據(jù)存儲(chǔ)的容器,把每個(gè)測(cè)試用例中的數(shù)據(jù)裝入到對(duì)應(yīng)的JavaBean中,最后構(gòu)建一個(gè)JavaBean對(duì)象為元素的ArraList來(lái)存儲(chǔ)所有的測(cè)試用例。測(cè)試執(zhí)行時(shí),測(cè)試代碼只需要從ArrayList里面取得測(cè)試用例的數(shù)據(jù),測(cè)試代碼僅僅完成驗(yàn)證任務(wù)。這樣,如果測(cè)試用例增加了,只需修改相應(yīng)的XML文件,而不必再修改測(cè)試代碼,就可完成相應(yīng)的測(cè)試。
借鑒文獻(xiàn)[6]的方法,本文將測(cè)試用例和測(cè)試結(jié)果都存儲(chǔ)為 XML 文檔,使用方法writeToFile(String fileName, String time,ArrayList testResultList)將測(cè)試結(jié)果保存在XML文件中,測(cè)試結(jié)果可以包括存儲(chǔ)過(guò)程運(yùn)行的時(shí)間、返回的記錄數(shù)、調(diào)用的參數(shù)列表或者出錯(cuò)信息等。選擇把測(cè)試結(jié)果保存為 XML的一個(gè)重要原因是通過(guò)簡(jiǎn)單的 XML編程即可實(shí)現(xiàn)對(duì)歷次的測(cè)試結(jié)果的比較分析。其實(shí)現(xiàn)方法就是將測(cè)試結(jié)果的XML文件命名為 TestCaseName_年_月_日_時(shí)_分_秒.xml,每次運(yùn)行測(cè)試?yán)?,都生成一個(gè)具有時(shí)間戳的測(cè)試結(jié)果文件,例如:
testSP_2009_10_18_17_27_00.xml
testSP_2009_10_18_17_30_00.xml
testSP_2009_10_18_17_32_00.xml
通過(guò)比較這三個(gè)文件中同一個(gè)存儲(chǔ)過(guò)程的運(yùn)行耗時(shí)、返回記錄數(shù)等指標(biāo)就能知道這次的測(cè)試結(jié)果比上次是否有所改進(jìn),或者系統(tǒng)在不同時(shí)間點(diǎn)的性能變化情況。
有了JUnit 測(cè)試代碼之后,在 Eclipse 中,左鍵雙擊將要運(yùn)行的 Java 文件,選擇 Run As->JUnit Test 就可以在工作環(huán)境中運(yùn)行測(cè)試文件了。運(yùn)行完畢后,會(huì)生成一個(gè)XML文件,再配合以XSL樣式文件,就可以在瀏覽器中看到美觀的測(cè)試報(bào)告了。
4 結(jié)束語(yǔ)
Junit和Eclipse兩種軟件的源代碼都能從網(wǎng)上免費(fèi)獲得,利用Junit基于XML存儲(chǔ)測(cè)試數(shù)據(jù)和測(cè)試結(jié)果的新測(cè)試框架真正提高了測(cè)試效率,簡(jiǎn)化了測(cè)試步驟,從根本上提高了測(cè)試代碼的重用性。利用JUnit實(shí)現(xiàn)了以往存儲(chǔ)過(guò)程測(cè)試中很難進(jìn)行的回歸測(cè)試,利用XML技術(shù)實(shí)現(xiàn)了測(cè)試數(shù)據(jù)和測(cè)試代碼分離,提高了測(cè)試效率,為開發(fā)人員提供了直觀的測(cè)試結(jié)果。
現(xiàn)有的測(cè)試框架可以擴(kuò)展到Cactus(Apache Software開發(fā)的用來(lái)對(duì)服務(wù)器上的Java代碼進(jìn)行測(cè)試的框架)框架上,實(shí)現(xiàn)從瀏覽器進(jìn)行存儲(chǔ)過(guò)程測(cè)試用例的調(diào)用執(zhí)行,可以克服因?yàn)殚_發(fā)和生產(chǎn)環(huán)境之間可能存在的網(wǎng)絡(luò)、安全等因素而影響測(cè)試準(zhǔn)確性的問(wèn)題。
參考文獻(xiàn):
[1] 余波,王樹林,張大方.基于Junit自動(dòng)生成類測(cè)試案例框架的實(shí)現(xiàn)[J].計(jì)算機(jī)工程與應(yīng)用,2006,42(1):89-91.
[2] 王東剛.軟件測(cè)試與JUnit實(shí)踐[M].北京:人民郵電出版社,2004.
[3] 孔亮亮,殷兆麟.Java類測(cè)試工具Junit的分析與擴(kuò)展[J].計(jì)算機(jī)工程與設(shè)計(jì),2005,26(12):3413-3415.
[4] 何成萬(wàn),余秋惠.用JUnit實(shí)現(xiàn)Java程序自動(dòng)測(cè)試[J].計(jì)算機(jī)應(yīng)用,2002,22(3):93-94.
[5] 王聰.基于JUnit框架的軟件測(cè)試[J].湖北汽車工業(yè)學(xué)院學(xué)報(bào),2007,21(1):43-46.
[6] 隋智泉.一種改進(jìn)的單元測(cè)試JUnit框架[J].電腦知識(shí)與技術(shù):學(xué)術(shù)交流,2007,2(8):479-480.