您的位置:軟件測試 > 開源軟件測試 > 開源功能測試工具 > Selenium
使用 Selenium 和 TestNG 進行編程式測試
作者:網(wǎng)絡轉(zhuǎn)載 發(fā)布時間:[ 2012/12/7 15:15:54 ] 推薦標簽:

DbUnit 再次登場

您可能回想起,DbUnit 通過有效地管理測試場景中的數(shù)據(jù)簡化了使用數(shù)據(jù)庫的工作。通過使用 DbUnit,可以在測試前將一組已知的數(shù)據(jù)加載到數(shù)據(jù)庫中,這意味著您可以依賴這些在測試過程中呈現(xiàn)的數(shù)據(jù)。此外,在完成測試后,還可以從數(shù)據(jù)庫中刪除測試結(jié)果產(chǎn)生的數(shù)據(jù)。DbUnit 作為一種方便的 fixture(JUnit 或 TestNG)簡化了所有這些工作,它能夠讀取包含測試數(shù)據(jù)的種子文件,邏輯插入、刪除數(shù)據(jù),或更新數(shù)據(jù)到相應的數(shù)據(jù)庫表中。

由于這里使用了 TestNG 驅(qū)動 Selenium,我將創(chuàng)建一個 DbUnit fixture,它將在測試 級別上運行。TestNG 支持在五種粒度級別上運行 fixture。低的兩種級別,方法和類是常見的 —— 用于每個測試方法的 fixture 或者用于整個類的 fixture。之后,TestNG 為一個測試集合(定義在 TestNG 配置文件中并由 test 元素指定)定義了一個 fixture,為一組 測試(定義在 TestNG 的 Test 注釋中)定義了一個 fixture。

測試細節(jié)

創(chuàng)建一個 DbUnit fixture 并在測試級別上運行,這意味著運行任何測試之前,測試類的集合將共享相同的邏輯,為數(shù)據(jù)庫正確地播種。在本文的示例中,在運行每個邏輯測試集合前,我希望數(shù)據(jù)庫具有一組干凈的數(shù)據(jù)。使用 DbUnit 的 CLEAN_INSERT 命令確保在先前運行的測試中創(chuàng)建的行被刪除掉 —— 因此,我可以重新運行測試,該測試可以不斷創(chuàng)建數(shù)據(jù)并且不用考慮數(shù)據(jù)庫約束。

此外,我希望 fixture 能夠依賴參數(shù)化數(shù)據(jù),這使我在運行某個測試之前,能夠靈活地切換種子文件,甚至是特定數(shù)據(jù)庫的位置。將 TestNG 與參數(shù)相關聯(lián)起來再簡單不過了:我所需做的僅僅是使用 Parameters 注釋裝飾 fixtrue,聲明方法簽名中相應的參數(shù),并提供 TestNG 配置文件中的值。

清單 8 定義了一個簡單的 DbUnit fixture,它使用所需的種子文件播種數(shù)據(jù)庫。請注意:該 fixture 被定義為包含五個 參數(shù)。(這可能非常多,但是在 fixture 中包含參數(shù)不是很好嗎?)


清單 8. 測試集合的 DbUnit fixture

                public class DatabaseFixture { @Parameters({"seed-path","db-driver","db-url","db-user","db-psswrd"}) @BeforeTest public void seedDatabase(String seedpath, String driver,    String url, String user, String pssword) throws Exception {  IDatabaseConnection conn = this.getConnection(driver, url, user, pssword);  IDataSet data = this.getDataSet(seedpath);  try {   DatabaseOperation.CLEAN_INSERT.execute(conn, data);  }finally {   conn.close();  } } private IDataSet getDataSet(String path) throws IOException, DataSetException {  return new FlatXmlDataSet(new File(path)); } private IDatabaseConnection getConnection(String driver,    String url, String user, String pssword ) throws ClassNotFoundException,    SQLException {  Class.forName(driver);  Connection jdbcConnection =     DriverManager.getConnection(url, user, pssword);  return new DatabaseConnection(jdbcConnection); }} 


要將實際的值與清單 8 中的參數(shù)相關聯(lián),我必須在 TestNG 的 testng.xml 文件中定義它們,如清單 9 所示:

清單 9. TestNG 的 testng.xml 文件中定義的特定于 DbUnit 的參數(shù)

                 <parameter name="seed-path" value="test/conf/gt15-seed.xml"/>  <parameter name="db-driver" value="org.hsqldb.jdbcDriver"/> <parameter name="db-url" value="jdbc:hsqldb:hsql://127.0.0.1"/> <parameter name="db-user" value="sa"/> <parameter name="db-psswrd" value=""/> 


通用參數(shù)值

現(xiàn)在我已經(jīng)定義了一個靈活的 fixture,它將處理數(shù)據(jù)庫狀態(tài)和相應測試,F(xiàn)在可以準備使用 TestNG 將所有內(nèi)容連接起來。通常,第一步是了解希望實現(xiàn)的內(nèi)容。在本例中,我想完成以下任務:

    我希望在運行任何邏輯測試集合前,DbUnit fixture 能夠完成自己任務。
    我希望將相同的測試集合運行兩次:一次用于 Firefox,一次用于 Internet Explorer。

TestNG 的 parameter 元素的作用域是局部的,這對我來說是件好事。這樣,我可以很容易地在 TestNG 配置文件中定義通用參數(shù)值,并且當需要時在 TestNG 的 test 組元素中重寫它們。

比如,要運行兩組測試,簡單創(chuàng)建兩個 test 元素。我可以通過 TestNG 的 package 元素將我的 fixture 和相關測試包括進來,package 元素能夠使包結(jié)構(gòu)中所有測試(或 fixture)的查找變得簡單。接著,我可以在兩個定義了的 test 組中將 Firefox 和 Internet Explorer 的 brwsr-path 參數(shù)關聯(lián)起來。所有這些都顯示在了 testng.xml 文件中,如清單 10 所示:

清單 10. 使 DbUnit 運行的靈活的 testng.xml 文件

                <suite name="User Acceptance Tests" verbose="1" >  <!-- required for DbUnit fixture   --> <parameter name="seed-path" value="test/conf/gt15-seed.xml"/>  <parameter name="db-driver" value="org.hsqldb.jdbcDriver"/> <parameter name="db-url" value="jdbc:hsqldb:hsql://127.0.0.1"/> <parameter name="db-user" value="sa"/> <parameter name="db-psswrd" value=""/>  <!-- required for Selenium fixture --> <parameter name="selen-svr-addr" value="localhost"/>  <parameter name="aut-addr" value="http://localhost:8080/gt15/"/>   <test name="GT15 CRUDs- Firefox" >    <parameter name="brwsr-path" value="*firefox"/>  <packages>   <package name="test.com.acme.gt15.Web.selenium" />   <package name="test.com.acme.gt15.Web.selenium.fixtures" />  </packages> </test> <test name="GT15 CRUDs- IE" >     <parameter name="brwsr-path" value="*iexplore"/>  <packages>   <package name="test.com.acme.gt15.Web.selenium" />   <package name="test.com.acme.gt15.Web.selenium.fixtures" />  </packages>  </test></suite> 


我很高興地宣布,我已經(jīng)完成了創(chuàng)建一套可重復驗收測試所需的所有事情。剩下的工具是處理 Web 應用程序容器本身。幸運地是,我可以使用 Cargo 來完成。

Cargo 執(zhí)行加載

Cargo 是一個創(chuàng)新的以通用方式自動化容器管理的開源項目,比如,用于將 WAR 文件部署到 JBoss 的相同 API 還可以啟動和停止 Tomcat。Cargo 還可以自動下載并安裝容器 —— Cargo API 的用途很廣泛,從 Java 代碼到 Ant 任務,甚至是 Maven。

諸如 Cargo 這樣的工具將處理編寫邏輯重復測試用例所面對的一個大的挑戰(zhàn),它避免一種潛在的假設,即運行 的容器具有新好的應用程序代碼。此外,還可以構(gòu)造一個利用 Cargo 的能力自動完成以下任務的編譯過程(例如在 Ant 內(nèi)):

    下載所需的容器。
    安裝該容器。
    啟動容器。
    將選擇的 WAR 或 EAR 文件部署到容器上。

稍后,您還可以使 Cargo 停止所選的容器。(并且,不需要對下載和安裝容器發(fā)出警告,或者,如果本地機器中已經(jīng)存在了正確的版本,Cargo 將跳過步驟 1 和 2。)

我希望使用 Cargo 來確保啟動并運行新和好的 Web 應用程序。并且,我不需要考慮在哪里部署 WAR 文件,或者必須確保正在使用的是新的 WAR 文件。我真正想達到的目的是使用戶驗收測試實現(xiàn)無事件 —— 我僅需要發(fā)出一個 命令,然后坐下來等待結(jié)果。甚至可以更好,在一個 CI 環(huán)境中,我不用等待;當測試完成后我將獲得一個通知!

測試容器管理

要在 Ant 內(nèi)設置 Cargo,我需要定義一個任務,它將下載特定版本的 Tomcat 并將其安裝到本地機器上的臨時目錄。接下來,將新版本的代碼部署到 Tomcat 上,如清單 11 所示:

清單 11. 設置 Cargo 的任務

                <target name="ua-test" depends="compile-tests,war"> <taskdef resource="cargo.tasks">  <classpath>  <pathelement location="${libdir}/${cargo-jar}" />  <pathelement location="${libdir}/${cargo-ant-jar}" />  </classpath> </taskdef>  <cargo containerId="tomcat5x" action="start" wait="false" id="${tomcat-refid}">  <zipurlinstaller installurl="${tomcat-installer-url}" />  <configuration type="standalone" home="${tomcatdir}">   <property name="cargo.remote.username" value="admin" />   <property name="cargo.remote.password" value="" />   <deployable type="war" file="${wardir}/${warfile}" />  </configuration> </cargo> <antcall target="_start-selenium" /> <cargo containerId="tomcat5x" action="stop" refid="${tomcat-refid}" /></target> 


清單 11 中的 target 使用 antcall 調(diào)用另一個 target。實際上,清單 11 中后的 cargo 任務封裝了 _start-selenium target,并且確保運行測試后停止 Tomcat。

在清單 12 中定義的 _start-selenium target 中,我需要啟動(并稍后停止)Selenium 服務器。在此過程中,我的測試還將連接到其 Selenium fixture 中的服務器實例。請注意:該 target 是如何引用另一個 target ——


清單 12. 啟動和停止 Selenium 服務器

                <target name="_start-selenium"> <java jar="${libdir}/${selenium-srvr-jar}" fork="true" spawn="true" /> <antcall target="_run-ua-tests" /> <get dest="${testreportdir}/results.txt"         src="${selenium-srvr-loc}/selenium-server/driver/?cmd=shutDown" /></target> 


后,該組中后的 target 將通過 TestNG 實際運行我的編程式 Selenium 測試。注意,我是如何通過使用清單 13 中的 _run-ua-tests target 的 xmlfileset 元素,使 TestNG 使用我的 testng.xml 文件。

清單 13. 運行 TestNG testng.xml 文件中的測試

<target name="_run-ua-tests"> <taskdef classpathref="build.classpath" resource="testngtasks" /> <testng outputDir="${testreportdir}"          classpath="${testclassesdir};${classesdir}" haltonfailure="true">  <xmlfileset dir="./test/conf" includes="testng.xml" />  <classpath>   <path refid="build.classpath" />  </classpath> </testng></target> 

結(jié)束語

正如您看到的一樣,Selenium 極大地簡化了用戶驗收測試,尤其當使用 TestNG 驅(qū)動的時候。雖然編程式測試并不適用于所有人(非開發(fā)人員可能更喜歡 Selenium 的 Fit 樣式的表),它確實讓您了解到了 TestNG 非凡的靈活性。編程式測試還允許您使用 DbUnit 和 Cargo 構(gòu)建自己的測試框架,從而確保測試的邏輯可重復性。

開源 Web 測試框架的發(fā)展絕不會停止,這對于追求代碼質(zhì)量的完美主義者是個好消息。Selenium 是驅(qū)動瀏覽器的開源 Web 測試框架中新出現(xiàn)的工具之一,它能夠使用戶驗收測試自動化 —— 因此,它非常。結(jié)合使用 Selenium 和 TestNG,正如我在本文中演示的一樣,您將獲得一個非常好的測試驅(qū)動,并從依賴性測試以及參數(shù)測試中獲得巨大的優(yōu)勢。嘗試使用 Selenium 和 TestNG 吧,您的用戶將為此感謝您。

上一頁123下一頁
軟件測試工具 | 聯(lián)系我們 | 投訴建議 | 誠聘英才 | 申請使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd