王 亮, 謝錫海2,尹成瑞
(1.青海大學 信息化技術中心, 西寧 810016;2.西安郵電大學 通信與信息工程學院, 西安 710061)
自動化測試技術[1-3]的發(fā)展經(jīng)歷了捕獲回放[4]、單腳本執(zhí)行、關鍵字驅動的測試集執(zhí)行[5-6]這3個階段的發(fā)展,已經(jīng)逐步走向成熟,這三者的共同特點是基于單機版的測試平臺執(zhí)行[7]。對于單機版測試平臺來說,其測試套中的腳本運行是串行化的,當測試套中腳本規(guī)模較大時,運行一次所需的時間比較長。
智能云測試系統(tǒng)[8-9]的目標是在實現(xiàn)測試資源管理自動化的基礎上,提供更高效的自動化腳本執(zhí)行平臺,在智能云測試系統(tǒng)中,需要存在大量的執(zhí)行機運行在獨立的計算機或者虛擬機[10]上。這些執(zhí)行機需要在統(tǒng)一的調度程序控制下,完成啟動進程、打開相應的控制臺、接受并運行指定腳本、反饋當前的執(zhí)行狀態(tài)、結束進程的動作。然而 通用測試平臺執(zhí)行機的啟動、運行及停止均是無人值守的。智能云測試系統(tǒng)內(nèi)部通過命令來驅動執(zhí)行機來完成,這個需求對測試平臺的通信機制提出了新的挑戰(zhàn),并且這一通信機制對于后續(xù)測試工具及自動化的發(fā)展帶來了新思路。
通用測試平臺提供多種連接方式來連接設備,以TCL語言為基礎,為測試人員提供了廣泛的手工測試和自動化測試支持。通用測試平臺實質是將多種不同的設備連接方式作了統(tǒng)一管理。避免了用戶分別使用超級終端、SSH Client等不同的客戶端來訪問設備。所以通用測試平臺需要支持同時以不同的連接方式連接設備,并與設備CLI接口進行交互。通用測試平臺集成文本編輯器來支持TCL腳本的編寫,使得通用測試平臺集TCL腳本編輯、執(zhí)行功能于一體,更加接近于TCL語言集成開發(fā)環(huán)境。
測試平臺作為一個標準的Windows程序,其絕大部分功能是由主界面的各項菜單來驅動的。用戶在通用測試平臺主界面上的各項操作,包括點擊各類菜單,編輯器中輸入字符等操作,最終都會產(chǎn)生一系列的Windows消息,通用測試平臺通過接收并處理這些消息來響應用戶,并進行各項處理,大致的流程如圖1所示。
圖1 消息驅動
現(xiàn)有通用測試平臺系統(tǒng)并不支持任何分布式特性,面對來自智能云測試系統(tǒng)的新需求時,進行相應升級改造。智能云測試系統(tǒng)執(zhí)行機的功能需求實際只是當前通用測試平臺系統(tǒng)所實現(xiàn)功能的一個子集,通過將外部的驅動方式由Windows消息修改為特定命令格式后,可以滿足智能云測試的實際應用,將具體操作理解為驅動模塊,將通用測試平臺的實際功能模塊理解為業(yè)務模塊。將驅動模塊由Windows消息轉換為其他特定命令,而業(yè)務模塊即可透明的支持多種應用場景,如圖2所示。
圖2 命令驅動
在實際實現(xiàn)時,考慮到通信機制的通用性,重點考慮單機版測試平臺與分布式測試平臺實現(xiàn)上的統(tǒng)一;通信機制需要有良好的擴展性來支撐未來需求。通過正常方式啟動的通用測試平臺不受任何影響,仍然是由用戶通過GUI菜單產(chǎn)生的Windows消息來驅動;而在啟動通用測試平臺時給出特定命令行參數(shù),通用測試平臺會在啟動時進行智能云測試服務注冊,注冊成功后會自動開啟另外一條命令通道,接受并處理Carbon命令。
智能云測試[11]是在云計算的基礎下一種新型測試方法。由云系統(tǒng)維護資源池,統(tǒng)一管理測試所需的環(huán)境:設備、儀器和PC機等。智能云測試系統(tǒng)以云為中心,將測試資源集中管理,按需動態(tài)分配,同時腳本集中在云端并發(fā)分布式執(zhí)行。用戶通過web接口向系統(tǒng)提交測試任務,設定被測設備型號,選定測試版本,測試用例,提交后系統(tǒng)會自動計算該任務所需要的環(huán)境,并動態(tài)分配測試組網(wǎng)、執(zhí)行機來執(zhí)行相應測試例,并及時給出結果反饋。
智能云測試通信機制本質是一種Client-Server通信機制的擴展,通過將消息報文采用標準的HTTP消息進行封裝,來支持多種語言實現(xiàn)的服務端和客戶端。也就是與編程語言無關的多客戶端多服務端通信機制,如圖3所示。
圖3 智能云測試從通信機制
通信機制有如下特點:1)語言無關性:對于客戶端和服務提供端來說,可以采用任意語言編程實現(xiàn),且支持混合調用。TCL語言客戶端可以調用C++服務提供端的服務,反之亦然??蛻舳诵枰{用某服務時,不需要關心還服務是采用何種語言實現(xiàn);2)平臺無關性:客戶端、Carbon-Server和服務提供者可以運行在Windows及Linux操作系統(tǒng),并且Windows系統(tǒng)上的客戶端程序也可以向Linux系統(tǒng)下的某個服務發(fā)起請求并得到處理,整個過程對客戶端完全透明;3)部署簡單:客戶端、Carbon-Server和服務提供者在同一臺物理機器,亦可以完全在不同的物理機器;4)可擴展性高:由于服務和客戶程序的松耦合性,在本系統(tǒng)中添加新的服務是極為便利的事情。不需要更改任何現(xiàn)有的服務提供者和客戶端,相應的是,某服務提供者提供更多的功能命令時,也只需要修改該服務本身,不對其他服務造成影響。
Carbon-Server以C/S模式實現(xiàn)一個簡便的進程間通信平臺。基于命令行形式的服務命令調用;簡便的客戶端/服務實現(xiàn)接口;多編程語言支持;選用Selenium作為基礎框架進行開發(fā),Selenium是一款為實現(xiàn) Web應用程序開源的自動化測試框架[[12-15],其服務程序的開發(fā)和部署都相對容易,對操作系統(tǒng)和服務平臺依賴小,可擴展性強。Selenium的通信過程如圖4所示。
圖4 Selenium通信結構
這個通信過程中,客戶端接口將用戶調用的服務器命令及參數(shù)封裝在HTTP請求當中發(fā)送給Selenium-Server,Selenium-Server解析命令內(nèi)容并構造JSON字符串寫入到對應瀏覽器的命令隊列。瀏覽器中運行的Java-Script服務程序(Core)定時向Selenium-Server發(fā)送HTTP響應(帶有POST消息)。如果命令隊列不為空,Selenium-Server就把命令字符串通過HTTP響應發(fā)送給服務程序運行。服務程序執(zhí)行命令并把結果封裝在下一個HTTP響應當中返回給Selenium-Server,最后Selenium-Server把命令結果封裝在HTTP響應命令當中返回給客戶端。要滿足Carbon-Server的要求,Selenium-Server需要刪除其中的瀏覽器支持部分,而主要保留了其中的通信機制、命令隊列、日志處理這3個部分。并對以下幾個方面進行了改進,改進后Carbon-Server的通信結構如圖2所示。
圖5 Carbon-Server通信結構
2.2.1 注冊/撤消服務
Carbon-Server支持服務的注冊和撤消。使用Carbon-Server提供的服務程序開發(fā)接口編寫的服務程序,通過向Carbon-Server發(fā)送registerService命令來完成注冊。Carbon-Server接受到注冊命令時為服務程序創(chuàng)建命令隊列。注冊之后,服務程序就可以定時從命令隊列當中讀取命令。相應的,unregisterService命令撤消服務的注冊。Carbon-Server會刪除服務對應的命令隊列,并停止處理客戶端對該服務的命令請求。
2.2.2 服務隊列標識
服務程序在注冊Carbon-Server時,在register Service 命令中包含了服務的名稱信息。Carbon-Server使用服務隊列管理類來維護服務名稱到對應的命令隊列的映射。每一個服務創(chuàng)建一個命令隊列,并映射到一個唯一的服務名稱標識。因此,在Carbon-Server上注冊的服務不能存在重名的現(xiàn)象??蛻舳嗽谡埱竽硞€服務的命令時也必須指定服務的ServiceId。
2.2.3 并發(fā)訪問
Carbon-Server的應用環(huán)境中,通常存在兩種情況的并發(fā)需求:多客戶端并發(fā)訪問同一個服務、多客戶端并發(fā)訪問不同的服務。Carbon-Server使用Apache的Http包來提供HTTP服務。對于每一個HTTP請求(響應)都會創(chuàng)建一個處理線程。因此,并發(fā)訪問實際上體現(xiàn)為多線程并發(fā)讀寫命令隊列。實現(xiàn)時使用同步阻塞的方法來限制同時只有一個線程寫入指定服務的命令隊列并等待結果。
2.2.4 定時老化
Carbon-Server為每一個注冊成功的服務創(chuàng)建一個計數(shù)器,并使用一個專門的定時器線程對所有定時器進行刷新,定時器刷新線程每隔一定時間將所有計數(shù)器的值加1。如果計數(shù)器的值達到限制的數(shù)值,則認為該服務已超時,需要刪除其命令隊列。另一方面,當Carbon-Server接受到服務程序發(fā)送的命令獲取消息時,計數(shù)器設置為0。
2.2.5 狀態(tài)查詢
Carbon-Server提供listAllService命令來查詢所有服務的狀態(tài)。返回信息以換行符分隔,每一行對應一個服務的狀態(tài)信息。行的內(nèi)容又以逗號分隔為不同的列。
2.2.6 服務類型
Carbon-Server的配置文件中可以定義兩種類型的服務,Internal和External:對于Internal類型的服務,Carbon-Server在啟動時會自動根據(jù)配置文件的信息來啟動服務程序;而對于External類型的服務,Carbon-Server不會自動啟動服務(用戶可以手動啟動服務或在客戶端通過stsrtService命令啟動)。當服務的定時器超時時,對于Internal的服務,Carbon-Server會關閉原來的服務程序并重新啟動,而對于External類型的服務則只是刪除命令隊列。
2.2.7 并發(fā)方式及命令封裝
Carbon-Server支持兩種服務并發(fā)方式:基于線程的并發(fā)和基于進程的并發(fā)。如果服務程序支持基于線程的并發(fā),則主線程只處理getNewSession/releaseSession命令。則當客戶端發(fā)送getNewSession命令時,服務器程序需要啟動一個新的服務線程并注冊到Carbon-Server。新線程的ServiceId包含一個隨機的GUID和最初的服務名稱。Carbon-Server會把這個ServiceId返回為客戶端。這個新的線程可以作為一個單獨的服務來使用。處理結束時,客戶端需要發(fā)送releaseSession來釋放服務線程。如果服務程序支持基于進程的并發(fā),則不管Internal還是External類型的服務,Carbon-Server都不會自動服務程序。只有當接受到客戶端的startService命令時才會通過命令行來啟動服務程序。這類服務程序的第一個命令行參數(shù)必須為一個字符串參數(shù),服務程序使用該字符串參數(shù)加上內(nèi)置的服務名稱作為ServiceId注冊到Carbon-Server。因此,Carbon-Server在啟動服務程序時需要生成一個隨機的GUID作為服務啟動參數(shù)。Carbon-Server使用XML字符串來封裝客戶端發(fā)送給服務程序的命令信息。
2.2.8 服務與客戶接口
Carbon-Server提供Java/C++/TCL的服務端開發(fā)接口。不管哪種語言形式,服務開發(fā)接口都需要提供3個功能:注冊命令、啟動服務、停止服務。注冊命令接口至少包含兩個參數(shù):命令名稱和命令執(zhí)行對象。通過調用注冊命令接口可以建立命令名稱到命令執(zhí)行對象之間的映射。服務程序根據(jù)這個映射關系來執(zhí)行客戶端的命令請求。首先生成一個CarbonAgent對象。構造函數(shù)的參數(shù)分別指定Carbon-Server的地址、服務名稱。然后使用register接口注冊一系列命令。所以命令類都需要實現(xiàn)接口AbstractCarbonAgentCommand的方法execute。該方法傳入一個字符串數(shù)組參數(shù),返回結果也為一個字符串。Carbon-Server提供Java/C++/TCL的客戶端開發(fā)接口??蛻舳私涌趯嶋H上只需要把命令行封裝在 HTTP請求中發(fā)送即可??蛻舫绦蛑恍枰{用submit接口把命令發(fā)送給服務器執(zhí)行即可。
在智能云測試通信系統(tǒng)中,服務提供方由業(yè)務模塊、代理模塊及監(jiān)聽服務器組成。其中業(yè)務模塊與代理模塊在同一進程中,通過函數(shù)調用及回調的方式來交互。監(jiān)聽服務器一般在單獨進程中實現(xiàn),進程間采用Socket方式封裝HTTP消息來實現(xiàn)。
對于執(zhí)行機分布式執(zhí)行的場景來說,業(yè)務模塊代表通用測試平臺進程,代理模塊在CCarbonAgent.dll中實現(xiàn),為通用測試平臺進程提供業(yè)務注冊,消息封裝及解封裝,保活操作;監(jiān)聽服務器則對應Canbon-Server進程。它們之間的關系如圖6所示。
圖6 provider組成
由于Canbon-Server服務器對外完全采用HTTP消息的方式通信,這樣的方式?jīng)Q定了業(yè)務模塊與代理模塊的實現(xiàn)不受語言限制。一般情況下,對于不同形態(tài)的業(yè)務模塊來說,分別提供不同的代理模塊來配合,如圖7所示。
圖7 多代理框架
代理模塊實現(xiàn)時,通常要遵循的原則是:實現(xiàn)上盡量獨立,與業(yè)務模塊通過接口集成,代理模塊的實現(xiàn)要充分考慮不同語言的特點。對于C/C++代理程序來說,比較適合的實現(xiàn)是獨立的標準DLL。這樣的話可以方便任意C/C++程序經(jīng)過簡單的改造演變成服務模塊。對于Java程序來說,比較合適的實現(xiàn)是封裝成獨立的Jar包來完成。對于TCL代理來說,封裝成Lib庫是合適的選擇。
2.3.1 服務提供方通信細節(jié)
在通用測試平臺的實踐中,代理模塊向通用測試平臺提供如下的接口來注冊命令。
DLL_API int CarbonServer_InstallService(struct sCarbonServiceInfo *pService)
入?yún)⒌臄?shù)據(jù)結構定義如下(所有參數(shù)以字符串的形式統(tǒng)一傳遞):
typedef struct sCarbonCmdList {
Std::string strName;
int (*fCmdHandle) (std::string);
}sCarbonCmdList;
注冊本地服務基本信息
typedef struct sCarbonServiceInfo {
DWORD dServerIpAddr;
UINT uServerPort;
Std::string strServiceName;
Std::vector
}sCarbonServiceInfo;
其中,字符串變量strServiceName表示通用測試平臺所提供的服務名稱,向量vecCmdList包含了通用測試平臺服務所提供的所有有效命令列表。對于每個命令結構,由sCarbonCmdList結構來記錄命令的名稱及回調函數(shù)指針。注冊后,當監(jiān)聽服務器Carbon-Server收到該服務對應的命令請求時,會從以上命令列表中進行匹配,檢查是合法命令時,則直接通過回調函數(shù)來調用通用測試平臺服務觸發(fā)相應操作。
智能云測試通信系統(tǒng)中,調用方一般是由Client、Agent及Carbon-Server組成。其實現(xiàn)機制與服務提供方類似,如圖8所示。
圖8 調用方通信機制
一般情況下,Carbon-Server與服務提供方運行在一臺服務器,并向外提供TCP端口服務。調用方通過代理模塊向該服務發(fā)送命令請求,并接受運行結果。同一種語言的代理模塊需要分別支持Provider服務和Caller客戶端操作接口。
服務調用方通信細節(jié):通用測試平臺的實踐中,通用測試平臺主機注冊就是采用向注冊服務器請求,并由注冊服務器記錄到數(shù)據(jù)庫中。注冊程序是一個獨立的GUI程序,內(nèi)部通過調用代理模塊提供的命令請求接口來實現(xiàn)通信。代理模塊提供的請求接口如下:
DLL_API int CarbonClient_ExecCommand(bool bIsNewSession,Struct sExeRegInfo *pRegInfo,std::string &strOutput)
其中,入?yún)⒅械膕ExeRegInfo結構記錄了待請求的服務及命令,strOutput變量為輸出參數(shù),記錄了命令的執(zhí)行結果。值得注意的是,該接口會觸發(fā)請求服務的相應功能,不會立刻返回。sExeRegInfo結構的定義如下:
Typedef struct sExeRegInfo{
DWORD dServerIpAddr;
UINT uServerPort;
std::string strServiceName;
Std::vector
}sExeRegInfo;
這里包含了帶請求服務所注冊的Carbon-Server地址信息,包含其IP地址和TCP端口號,以及具體服務的名稱和命令名稱、參數(shù)。
當前的性能測試主要以采用測試儀為主,外加單機版測試工具輔助的方法來進行,當測試工具的性能達不到要求時,極端情況下會采用多單機版工具同時運行的情況。但到指標相差太多時,此種方式基本無法適用??梢钥紤]基于智能云測試通信機制對大量單機版測試工具進行整合,在客戶端以TCL腳本的形式來驅動其執(zhí)行,如圖9所示。
圖9 Tcl驅動通信機制
Server1,Server2等對應不同的性能測試模塊,由客戶端TCL腳本的運行來統(tǒng)一驅動。好處:1)支持大量相同的性能測試模塊同時運行:通過TCL腳本,同時驅動大量的相同性能測試模塊來運行,相當于極大增加了單機版性能測試模塊的性能指標;2)支持大量不同的性能測試模塊同時運行:可以較高的模擬大規(guī)模組網(wǎng),使得測試平臺能通過PC進行大規(guī)?;旌狭髁繙y試。
該分布式通信系統(tǒng)在任意單機版程序中經(jīng)過簡單改造后均能提供分布式的統(tǒng)一服務,其充分利用現(xiàn)有軟件資源及各類語言的特點來實現(xiàn)強大統(tǒng)一的工具平臺,并且Carbon-Server在一個比較便捷的分布式開發(fā)架構下,其管理機制以及開發(fā)接口都比較簡單,易于理解和實現(xiàn),功能強大的優(yōu)點。但在實際的應用中還存在不足之處,缺少GUI管理界面,命令執(zhí)行超時處理可靠性不夠,后續(xù)開發(fā)中應該解決這些問題。