自動測試模塊式該系統的一個核心部分,它使用了 Selenium 這個工具。Selenium 是一款針對 Web 產品的測試工具。它根據測試腳本,向瀏覽器發出指令,代替人手工點擊界面之苦。Selenium 有三類命令:動作命令(Action)、輔助命令(Accessor)、斷言(Assertion)。動作命令可以向應用程序發出指令,比如點擊按鈕;輔助命令檢查當前應用程序的狀態并保存于變量中;斷言類似于單元測試中經常使用的 Assert 方法,但是在 Selenium 中還有許多結合 Xpath 獲取元素屬性的方法。
通過這些命令,用戶可以方便地實現對網頁的各類操作、定位網頁上面的元素并判斷元素的值。此外,Selenium 有兩個主要的運行模式:Selenium Core 和 Selenium Remote Control。
Selenium Core 將測試用例以 Iframe 形式嵌入一個 TestRunner 頁面(參見圖 5),然后將它們上傳到和應用程序一起的 Web 服務器端。用戶可以使用右上角的 Selenium TestRunner 控制模塊來操作測試腳本,獲得測試結果。
圖 5. Selenium Core 實例
Selenium Remote Control 更加適合測試復雜的基于 Ajax 技術的應用程序。它提供一個 Selenium Server 服務器,作為應用程序客戶端的代理向應用程序的服務器端發送請求(參見圖 6)。在這種模式下,測試人員可以編寫一些測試腳本來完成一些復雜的測試。
圖 6. Selenium Remote Control 原理
與 IBM 的 Rational Functional Tester 工具相比,Selenium Remote Control 有三個主要特點:
- Selenium 基于 Http 協議來實現。它根據測試腳本提供的 Xpath 定位網頁上面的元素并對其進行操作,就如我們通常使用絕對和相對路徑查詢操作系統文件一樣;IBM 的 Rational Functional Tester 則基于對象模型設計實現的。它抓取瀏覽器在屏幕上實時展現的對象集合,根據用戶輸入的元素屬性在上面尋找可能的對象。實踐證明,當頁面非常復雜時,這個方法不精確高效。
- Selenium 是一個開源項目,可編寫測試腳本的 API 包支持好幾種語言,包括 Java, C++, .Net, Python 等;IBM 的 Rational Functional Tester 需要 license,并且只支持 Java。
- Selenium 在運行時使用 JavaScript 向應用程序發出測試命令,所以它對當前瀏覽器的位置和電腦的屏幕沒有要求;IBM 的 Rational Functional Tester 需要獲得當前瀏覽器和電腦屏幕的位置,要求屏幕始終打開。這需要人圍的支持,提高項目開發的成本。
本測試模塊運用 Selenium Remote Control 的模式,新建了一個 Java 項目,編寫了一系列 Java 的測試腳本。項目的目錄結構參見圖 7。
圖 7. 測試源代碼文件結構
該項目結構類似于普通的 Java 項目。其中,我們導入了運行 Selenium Remote Control 所需的 jar 包。另外,build 目錄下的 test-output 是每次運行后測試報告生成的地方。文件 build.xml 中定義了很多 Ant 的任務,用來編譯和運行測試腳本。
下面是一個測試腳本的事例,它將一個集群加入管理服務列表。Selenium 的測試腳本類似于一般的 Junit 測試用例。首先,需要新建一個 Selenium 的會話。這個會話需要的參數包括 Selenium 代理服務器的地址(selenSrvrAddr)、端口(4444)、需要測試的 Web 應用的服務器地址(bpath)以及 Web 應用在服務器上面的相對路徑(appPath)。然后,定義具體方法,對應用程序進行操作。比如在下面事例中使用 Open 函數打開頁面,選擇頁面上面的一系列 Frame(這里給出 Frame 的 name 就可以,因為它在頁面上是唯一的),然后點擊鏈接(這個鏈接通過屬性 Link 來定位的)。最后,記得關閉這個會話。
清單 6.測試腳本事例import org.TestNG.annotations.AfterClass; import org.TestNG.annotations.BeforeClass; import org.TestNG.annotations.Parameters; import org.TestNG.annotations.Test; import com.thoughtworks.selenium.DefaultSelenium; import com.thoughtworks.selenium.Selenium; public class TestClusterAddPage { private Selenium driver = null; @Parameters({"selen-svr-addr", "brwsr-path", "aut-addr"}) @BeforeClass private void init(String selenSrvrAddr, String bpath, String appPath){ driver = new DefaultSelenium(selenSrvrAddr, 4444, bpath, appPath); driver.start(); } @Parameters({"cluster-ip", "cluster-username", "cluster-pwd"}) @Test public void testAddCluster(String ip, String username, String password){ driver.open("/ica/Login"); driver.selectFrame("rootFrame"); driver.selectFrame("consoleWorkAreaFrame"); driver.selectFrame("rootFrame"); driver.selectFrame("consolePortfolioFrame"); driver.selectFrame("taskEntriesFrame"); driver.click("link=Clusters"); … .. } @AfterClass private void stop(){ driver.stop(); } } |
從以上事例可以看出,Selenium 在定位頁面上元素時比較隨機。有時可以使用元素的 name 屬性,有時可以使用元素的 id 屬性。為此,項目組可以為客戶端頁面上的元素定義唯一的屬性,方便 Selenium 測試。
使用 Selenium Remote Control 模式需要在運行腳本前后啟動和停止 Selenium Server 服務器。這里我們在 build.xml 中定義了一個任務名為 start-selenium。該任務第一步就是啟動 selenium server 服務器,第二步是調用 TestNG 配置的測試腳本,最后是停止 selenium server 服務器。整個流程比較清晰明了(參見以下代碼)。
清單 7.Selenium 流程<target name="start-selenium"> <java jar="lib/selenium-server-1.0-beta-2/selenium-server.jar" fork = "true" spawn = "true"/> <Antcall target="run-task-jar"/> <get dest="${test.output}/results.txt" src="http://localhost:4444/selenium-server/driver/?cmd=shutDown" /> </target> |
TestNG 在配置自動測試腳本中的作用
本測試系統還使用 TestNG 工具來輔助配置自動測試。TestNG 是測試 Java 應用程序的框架之一。它通過一些語義注釋來傳遞測試的參數,定義測試腳本的順序并配置運行時的性能。用戶可以通過配置來生成各式測試報告,十分方便。
TestNG 要求將所有要運行的測試用例都記錄在一個叫 testng.xml 的文件中(參見以下代碼)。然后根據該文件中的測試用例順序依次執行測試。用戶還可以根據需要在測試用例的具體方法中標識 @BeforeClass,@AfterClass 等語義,更加具體得定義測試順序。
為方便配置測試 Web 應用程序,我們將所使用的瀏覽器和應用程序所部署的 IP 地址作為參數定義在 testng.xml 中。這些參數由 parameter 定義,通過 @Parameters 傳遞到函數中(參見上文)。具體的測試腳本由 Classes 元素中的 Class 來定義。
清單 8.testng.xml<!DOCTYPE suite SYSTEM "http://beust.com/TestNG/TestNG-1.0.dtd" > <suite name="My test suite"> <test name="SVCGUI unit test"> <parameter name="selen-svr-addr" value="localhost"></parameter> <parameter name="aut-addr" value="http://9.9.9.9:9080"></parameter> <parameter name="brwsr-path" value="*firefox"></parameter> <parameter name="cluster-ip" value="1.1.1.1"></parameter> <parameter name="cluster-username" value="admin"></parameter> <parameter name="cluster-pwd" value="abc"></parameter> <classes> <class name="src.cluster.TestClusterAddPage"/> <class name="src.cluster.TestClusterDeletePage"/> <class name="src.user.TestUserListPage"/> </classes> </test> </suite> |
在上文的事例中,定義了一個叫 My test suite 的測試組,其中包括三個測試腳本。用戶可以根據需要在同一個文件中定義其他測試組(suite),或者在一個測試組中定義更多的測試腳本集(classes)。
系統的 Web 管理站點會羅列出該文件中的 class 元素的 name 屬性值(參見圖 8)。然后讓用戶自由選擇需要的測試用例,保存成一份新的 testng.xml 文件。接著,用戶可以選擇馬上執行自動測試或者保存到下一次系統運行下載流程時執行。
圖 8. 測試實例管理界面
TestNG 還能夠為系統自動生成一份漂亮的測試報告。我們可以在 build.xml 中給出報告的存放地址和形式(包括 html/text 等,參見如下代碼)
清單 9.build.xml<target name="compile" description="compile the examples" depends="prepare"> <javac debug="true" fork="true" source="1.5" classpathref="cp" srcdir="${basedir}/src" destdir="${basedir}/build/classes" /> </target> <target name="testjar" description="make a test jar with the property file and the classes we need in it"> <jar destfile="${basedir}/example.jar"> <fileset dir="${basedir}/build/classes" includes="**/*.class"/> <fileset file="${basedir}/TestNG.xml"/> </jar> </target> <target name="run-task-jar" depends="compile, testjar" description="run examples using TestNG task with just xml"> <testng classpathref="cp" outputdir="${test.output}" testjar="${basedir}/example.jar"/> </target> |
在以上事例中有三個任務,compile/testjar/run-task-jar。這三個任務中 run-task-jar 是主要的任務,它調用了 TestNG 的語義 <testng>,并給出測試報告的生成目錄,以及測試腳本的所組成 jar 包名。
使用 Flex 實現的管理站點
Web 管理站點在整個測試系統中起到了畫龍點睛的作用。它的功能涵蓋了下載控制,測試腳本控制和測試報告發布。用戶可以通過它來新建,修改,刪除和瀏覽各模塊的當前配置。當然,也可以根據項目的需要添加其他模塊,比如播放產品的 demo,顯示項目的進度等等。
該 Web 管理站點由 Flex 技術實現;谇拔牡慕榻B,作為一個 RIA 技術,Flex 可以幫助我們快速實現一個豐富多彩、靈活互動的客戶端(整體效果參見圖 9)。
圖 9. 圖形管理界面
站點的客戶端定義了一個新的布局器 PodLayoutManagers, 它讓用戶通過 XML 文件來配置當前顯示的視圖(view),各個視圖所包含的模塊(pod)(參見以下代碼)。每種 view 和 pod 類型都有自己的 ID。此外 , 每個 pod 模塊需要定義所屬的類型。用戶可以自定義新類型,但是每個類型都要繼承于 PodContentBase 控件,并給出模塊的標題(title), 讀寫的 XML 文件(dataSource)。有些類型還詳細到具體讀取的 XML 文件中的屬性 , 以及它們在表格上門顯示的列名。比如,在 XML 中我們定義了一個管理視圖,叫做 Project Management Console,它有四個模塊,分別是 list, form、case 和 film 類型。其中 , 第二個 pod 標題為“Download To Do”, 讀取的數據文件為 data 目錄下的 tasks.xml。它會讀取文件中的 Name、Type、Weedday、time、Source Url、Target Url 屬性 , 并將它們以 name、type、weekday、time、source、target 顯示在列表中(參見上文) 。
清單 10.tasks.xml<?xml version="1.0" encoding="utf-8"?> <views> <view id="view1" label="Project Management Console"> <pod id="pod1" type="list" title="Unit Test Report" dataSource="data/testreport.xml" selectedViewIndex="1"/> <pod id="pod2" type="form" title="Download To Do" dataSource="data/tasks.xml" labels="Name,Type,Weedday,time,Source Url,Target Url" dataFields="name,type,weekday,time,source,target" /> <pod id="pod3" type="case" title="Test Case" dataSource="data/TestNG.xml" labels="Test Case" dataFields="name" /> <pod id="pod4" type="film" title="Product demo" dataSource="data/news.xml"/> </view> </views> |
Form 和 case 類型可以選擇兩種顯示的方式:Grid 和 Form。在 Grid 模式下,模塊會以列表形式顯示數據。在 Form 模式下,模塊會顯示一個表單,用戶可以新建,修改和刪除一條記錄(參見圖 10)。
圖 10. 下載管理界面
在這個頁面中,首先要在 PodContentBase 控件中加入一個 HBox 來切換兩個不同的視圖。然后定義一個 ViewStack,并在其中加入兩個控件:VBox 和 Canvas。VBox 顯示表單,而 Canvas 中用 DataGrid 讀取 dataFields 中的數據并以表格方式顯示。而頁面上面的 Action 主要在 Script 中實現。具體實現參見圖 11:
圖 11. 管理界面頁面代碼
Flex 可以與各類服務器端技術相結合。該 Web 管理站點采用 J2EE 作為服務器端技術,通過 serve let 同客戶端通信,完成對各 XML 配置文件的修改。由于篇幅有限,具體實現方式可以參考文章《 Flex 開發入門》。
總結
本文向大家詳細介紹了一個智能的 Web 界面測試系統。它的四個主要模塊配置靈活、運行高效,可以幫助團隊完成 Web 界面的各類測試。我們的開發和測試人員不必再為枯燥乏味的界面操作而嘆氣。此外,友好的 Web 管理站點進一步體現了系統的靈活、高效、開放的特點。該測試系統的另一個特點就是可擴展性。項目組可以根據自身的需要豐富管理站點的功能,引入一些項目進度、人員時間等管理模塊,使項目內部交流更加精密。
希望本文能為相關的軟件研發團隊提供一些技術和設計上的啟發。
文章來源于領測軟件測試網 http://www.kjueaiud.com/