網絡設備自動化測試框架

                網絡設備自動化測試框架
          NATFNetsork automation test frame
   

第1章 概述

隨着internet的發展,網絡設備功能日漸複雜和多樣,測試消耗的資源也越來越龐大,測試本身是無窮的,而智能化的人力資源卻是有限的,所以如何將有限的人力精兵投入到複雜的測試中去而避免在細小的功能驗證上耗費人力是每一個測試人員的理想。那麼要做到這一點行之有效的方法就是細分測試種類,將簡單的功能性測試由自動化完成,性能及複雜的組合、異常等等的測試有人力完成,這樣一方面可以提高測試資源的利用率,一方面可以擴大測試的覆蓋率。形成系統的測試閉環。
近年來,自動化測試被越來越多的重視並實踐,當前主流網絡設備廠商已經在自動化測試領域取得了很大的成績,自動化測試覆蓋率也逐漸在提高。而各個廠商自動化測試的平臺是不同的,測試框架也就肯定是不同的,聯想網禦主要使用SecureCRT作爲測試平臺,SecureCRT本身提供了Jscript和VBscript兩種腳本語言的支持。所以在SecureCRT的基礎之上便誕生了NATF的框架。
網絡設備自動化測試框架NATF(Network automation test frame)旨在設計出一種用命令行完成配置的網絡設備(如防火牆、路由器、交換機等)的自動化功能性測試框架。整個框架可以分爲如下幾個部分:
測試牀文件:該文件描述了實際物理設備的物理連接、組網及相關配置。
邏輯拓撲文件:因爲在實際的測試過程中不同的模塊的測試組網不盡相同,而爲不同的模塊來搭建不同的物理網絡環境就顯得耗時費力不實際,邏輯拓撲將測試組網跟實際組網環境脫離,多個邏輯拓撲文件共用一個測試牀文件,在腳本執行過程中自動完成邏輯設備到物理設備的映射。這樣做有兩方面的好處:一方面只要完成了測試牀環境的搭建,不許改變環境便可以完成多個模塊的測試;另一方面爲腳本的移植帶來極大的方便,只需自行設計測試牀而無需動用邏輯拓撲及具體的腳本文件。
測試腳本:原則上每一個測試用例可以用一個測試腳本來實現。而測試腳本的設計既要考慮到測試用例的粒度,既不能過於單一也不能過於繁瑣,單一會造成不緊湊的感覺,繁瑣又會給定位帶來很大的不便。
測試集:同一模塊的多個腳本及多個模塊的測試集可以組成一個測試集文件。
整個測試框架實質上是一個分層的結構:
clip_image001
在測試的過程之中,測試的文件的解析是由下往上的,先解析測試牀文件完成設備基本配置工作,然後解析邏輯拓撲文件完成邏輯設備到物理設備的映射(手動/自動),接着執行單個的測試腳本,最後等所有測試腳本完成之後便完成了測試集的解析執行。測試文件的執行恰好是由上往下的,以測試集文件作爲入口文件開始執行,然後分別執行每個獨立的腳本文件,在每個腳本文件執行的過程中會完成邏輯拓撲到測試牀的映射進而正確的執行腳本。在執行腳本的過程中,每一步都會將執行結果記入日誌文件,在測試集執行完畢之後系統會根據*.log的日誌文件生成測試結果的*.exl文件並以郵件的方式發送到管理員郵箱中,以便管理員可以及時的看到測試結果並對FAIL項進行定位。
在腳本的執行過程中,一般會經過如下幾個步驟:
1. 解析測試牀文件,完成物理設備的接口地址及靜態路由等的基本配置工作,保證物理組網環境正確暢通。
2. 解析測試集文件,按照順序執行測試集中的測試腳本。
3. 在執行測試腳本之前解析邏輯拓撲文件並完成邏輯設備到物理設備的映射,映射包括邏輯設備到物理設備的映射,邏輯接口到物理接口的映射。完成映射之後通過讀取邏輯設備接口信息可以得到實際的接口IP、掩碼等。
4. 具體的測試腳本的執行。腳本執行一般有如下幾個步驟:首先完成基本的配置,然後是每一步的功能檢查,最後清除配置保證測試環境乾淨。

第2章 NATF的基本組成

2.1 測試牀

測試牀文件從某一種意義上是實際物理組網拓撲的文件描述。也就是說用文件的方
方式把物理環境進行了描述,進而形成了自動化測試框架中的測試牀。測試牀文件一般來說相對較複雜且具有典型性,因爲它的設計要考慮到涵蓋各個模塊的組網環境,以求用最簡最完備的環境完成環境描述。
而測試牀文件的功能卻又不僅限於此,測試牀文件在完成物理拓撲描述的同時還必須肩負起基本網絡配置功能,也就是說在在解析測試牀文件的過程中呢必須識別環境中用到了那些設備、設備接口、接口的IP地址及基本路由等。並且在解析過程中自動完成接口IP地址的配置及基本路由的配置。這一部分是跟具體腳本無關的,因爲腳本文件中所有的接口都採用了物理的而非實際的。
下面是一個舉例的測試牀文件(*.tbd),從中可以看出測試牀文件的一些設計細節。
[TITLE]1.1.1 防火牆部分NAT模塊測試牀
[PHY-TOP]
"
F0/0 F0/1 F0/0
R1-------R2-------R3------R4
F0/0 F0/1 F0/0
"
[SESSION]
R1:Router1
R2:Router2
R3:Router3
[PHY-LINK]
R1 F0/0 1.1.1.1 255.255.255.0;R2 F0/0 1.1.1.2 255.255.255.0
R1 F0/1 2.1.1.1 255.255.255.0;R2 F0/1 2.1.1.2 255.255.255.0
R2 F1/0 3.1.1.1 255.255.0.0;R3 F1/0 3.1.1.2 255.255.0.0
R2 F2/0 4.1.1.1 255.255.0.0;R3 F2/0 4.1.1.2 255.255.0.0
[INIT]
R1:
ip route 3.1.1.0 255.255.255.0 1.1.1.2
ip route 4.1.1.0 255.255.255.0 2.1.1.2
R2:
R3:
ip route 1.1.1.0 255.255.255.0 3.1.1.1
ip route 2.1.1.0 255.255.255.0 4.1.1.1
[END]
說明: [TOPNAME]說明了該測試牀文件的名稱。
[LOGICTOP]描述了物理組網環境。
[SESSION]描述了具體的設備通過secureCRT連接的會話名稱
[LINK]描述了具體的物理設備的連接情況及IP情況。
[INIT]描述了每個物理設備需要進行的基本配置。一般包括基本路由、默認防火牆規則等。
測試牀文件爲*.tbd文件,在執行腳本過程中首先會進行測試牀文件的解析,在解析過程中對設備的接口IP、路由等進行配置。完成測試環境的初始化。

2.2 邏輯拓撲

邏輯拓撲是實際物理組網的一個抽象,因爲每個模塊功能是不同的,所以運用的環境也肯定是不同的,而在實際的測試過程中就不可能爲每個模塊都搞一套環境,所以將具體的測試環境抽象成爲邏輯拓撲跟測試牀獨立,在測試的過程中進行邏輯到物理的映射,如此在進行腳本移植的過程中只需物理環境根據需要自行設計而邏輯拓撲及腳本則不發生變化,這樣免去了很多的重複工作。
下面是一個邏輯拓撲的舉例:
[TITLE] 1.1.1 防火牆部分NAT模塊SNAT基本功能邏輯拓撲
[LOGIC TOP]
"
PORT1 PORT1
DUT1----------------DUT-------------DUT2
PORT2 PORT2
"
[LOGIC DEVICE]
DUT1 DUT DUT2
[LOGIC LINK]
DUT1 PORT1<--->DUT PORT1
DUT PORT3<--->DUT2 PORT1
[TOP END]
說明:[TITLE] 邏輯拓撲名稱
[LOGIC TOP]邏輯拓撲組網。組網中設備名及端口名均爲邏輯名。所有腳本
中涉及到的設備及接口名均爲該邏輯名。
[LOGIC DEVICE]邏輯設備名,最後需要跟物理設備映射對應。最終獲取到
具體物理設備的會話名。以便腳本中通過該會話在SecureCRT中訪問到設備。
[LOGIC LINK]邏輯設備之間的連接關係。在邏輯拓撲映射的過程中邏輯連
接要跟物理設備連接進行映射關聯,關聯之後呢通過訪問邏輯接口便可以
訪問到物理接口,進一步可以獲取物理接口ip地址等信息。

2.3 測試腳本

一般情況下,整個測試體系應當是一體的,在項目開發過程中開發人員需要提交相關的測試交付件,這些交付件一般會包括SRS,SOW,系統測試用例,缺陷文檔等等。在項目驗收測試過程中由測試人員完成測試點、測試用例的寫作,然後以測試用例爲藍本進行測試腳本的寫作,然後入庫形成基線。測試腳本作爲測試交付件,一個測試用例對應一個測試腳本或着多個測試腳本。
從測試的角度來看測試腳本可以這樣來理解,測試腳本主要完成三個功能:配置下發、功能檢查、結果輸出。下面以一個具體的實例來介紹:
# $language = "JScript"
# $interface = "1.0"
/*============引用接口庫文件並進行測試牀初始化===================*/
eval(Include("D:\\cyl\\Security&***\\security.js"));
/*===測試腳本頭部分:說明測試目的、功能概述並記錄日誌================*/
HEAD("1.1.1 防火牆部分NAT模塊SNAT基本功能測試","CHEYL 7765 2010-1-10");
/*=======基本配置部分:連接設備並完成命令行配置====================*/
sessionConnect(map.mapDevSess("DUT","s"));
setPcp("pcp","source-ip","net",map.mapInt("DUT1","PORT1",true,false),\
map.mapInt("DUT1","PORT1",false,true);
setSnatIp("pcp",map.mapInt("DUT1","PORT1",true,false));
sessionDisconnect();
/*=======檢查部分:利用Check接口完成多個step的檢查並將結果記錄日====*/
//步驟一:
STEP(1,"從DUT1到DUT2能不能ping通");
sessionConnect(map.mapDevSess('DUT1','s'));
Check("ping",map.mapInt("DUT","PORT1",true, false),"5","test");
Check("ping",map.mapInt("DUT2","PORT1",true, false),"5","test");
sessionDisconnect();
//步驟二:
STEP("2","從DUT1到DUT2能不能ping通");
sessionConnect(map.mapDevSess("DUT2","s"));
Check("ping",map.mapInt("DUT1","PORT1",true, false),"5","test");
Check("ping",map.mapInt("DUT","PORT1",true, false),"5","test");
sessionDisconnect();
/*===========配置清除部分:將配置清除爲初始化=====================*/
sessionConnect(map.mapDevSess("DUT","s"));
removePcp("pcp");
removeSnat("pcp");
sessionDisconnect();
/*=======================腳本結束==============================*/
從上面的腳本可以看出一個完整的測試腳本有如下幾部分組成:
1. 腳本語言及版本說明(作爲單獨的腳本執行時是必須的否則需要註釋掉)
2. 腳本頭文件:說明測試目的、功能概述、作者及日期等並記錄日誌
3. 基本配置部分:連接設備並完成命令行配置。該部分如果多個測試腳本共用可以移到測試集拓撲文件映射過程中。
4. 檢查部分:利用Check接口完成多個step的檢查並將結果記錄日誌。
5. 配置清除部分:將配置清除爲初始化。目的是爲了防止相關配置對後續功能檢查的影響。相關配置清除之後腳本執行也就結束了。
6. 除了以上5點之外最重要的就是記錄日誌:在腳本執行的過程之中會將相關步驟、腳本的執行結果記錄在日誌中,如果檢查失敗還會記錄失敗信息便於定位。

2.4 測試集

同一個模塊的相關測試腳本完成後便可以生成一個測試集文件。不同模塊的測試集文件也可以放在一起生成一個總的測試集文件。這樣做的目的便於管理。下面就是一個測試集文件的實例:
# $language = "JScript"
# $interface = "1.0"
/*======引用接口庫文件並進行測試牀初始化================*/
eval(Include("D:\\cyl\\Security&***\\BaseLIB.js"));
/*=======讀取測試牀文件並完成設備初始化=================*/
MODULE_TEST_SUIT_START();
/*========測試集文件:包含各個腳本文件並執行============*/
eval(Include("D:\\cyl\\Security&***\\script1.js"));
eval(Include("D:\\cyl\\Security&***\\script2.js"));
MODULE_TEST_SUIT_END()
分析上述測試集文件可以看出包含如下幾個步驟:
1. 腳本語言及版本說明。
2. 引用接口庫文件。庫文件中包含了各個模塊的接口。因爲其規模較大,可以按模塊劃分後綜合,這樣便於問題定位及管理。
3. 讀取測試牀文件並完成設備初始化。整個測試集執行過程中只進行一次測試牀文件解析及物理組網初始化。
4. 測試集文件:包含各個腳本文件並順序執行。
5. 測試集執行結束完成測試結果的彙總。這個過程會有一個很重要的功能,那就是生成測試結果。以郵件的方式發送到管理員郵箱之中。具體日誌格式及郵件格式請參見腳本日誌設計章節。
以上幾部分分別較爲詳細的介紹了NATF自動化測試框架的各個組成部件。但是並沒有涉及到具體的實現。下面將較爲詳細的介紹一下具體的實現及相關的腳本的寫作規範。

第3章 腳本接口設計規範

因爲我司普遍採用了SecureCRT作爲測試平臺,而SecureCRT只提供了Jscript、VBscript及PerlScript三種腳本語言。而沒有提供業界用的較多的tcl&tk腳本語言,所以只能選擇Jscript語言。我們的網絡設備的測試都是基於命令行的,所以自動化實現主要是完成配置命令的下發與功能的檢查兩部分。
要完成模塊配置的下發,就需要將命令行進行包裝,結合SecureCRT簡單的腳本功能開發出適合我司設備的接口庫,然後用這些接口庫文件編寫腳本實現自動化測試。
目前接口庫的接口設計主要有三類:set類、get類和chk類三種。每個接口均爲一個函數,主要包括兩個方面:1.接口說明,需要說明函數功能,參數、作者、日期、返回值及應用舉例等。2.函數體:主要實現相關功能。下面分別進行說明。

3.1 set/remove類

Set類接口主要完成配置的下發。
舉例如下:
//*********************************************************************
//函數功能:通過執行“interface Ge0/0/0 ”配置設備接口
//函數參數:arg1--刪除的接口名
// arg2--廠商標識(s爲思科,h爲華爲,默認爲網禦)
//作 者 :cheyl 2009-12-20
//返回值 :配置正確返回true,否則爲false
//舉 例: setInt("Ge0/0/0")
//*********************************************************************
function setInt(arg)
{
var viewTemp = new view();
viewTemp.viewCfg();
crt.screen.send("interface " + arg + "\r");
if(crt.screen.waitforstring("\(config-if\)#"))
{
return true;
}
return false;
}
Remove主要完成配置的刪除,一般情況下跟set類是成對出現的,共同完成某個命令的下發與刪除。
Remove類舉例如下:
//*********************************************************************
//函數功能:通過執行undo interface Ge0/0/0 刪除設備邏輯接口,物理接口不可刪
//函數接口:arg2---廠商標識(s爲思科,h爲華爲,默認爲網禦)
//作 者 :cheyl 2009-12-20
//返回值 :配置正確返回true,否則爲false
//舉 例: removeInt("Ge0/0/0")
//*********************************************************************
function removeInt(arg1,arg2)
{
var viewTemp = new view();
viewTemp.viewCfg();
switch(arg2)
{
case "s":
crt.screen.send("no interface " + arg1 + "\r\n");
crt.screen.WaitForString("#");
break;
case "h":
crt.screen.send("undo interface " + arg1 + "\r\n");
crt.screen.WaitForString("#");
break;
default:
crt.screen.send("undo interface " + arg1 + "\r\n");
crt.screen.WaitForString("#");
break;
}
if(crt.screen.waitforstring("\(config\)#"))
{
return true;
}
return false;
}

3.2 get類接口

get類接口主要完成show信息的獲取,get是chk的基礎,chk一般會通過get類得到
信息經過比較,處理後以便確定模塊的功能的正確性。
//************************************************************************
//函數功能:通過執行“show int f0/0 ”來獲取某個接口的相關ip信息
//函數接口:arg1---接口
// arg2---需要獲取的信息(ip、mask、state、mac、speed、mtu、duplex、
// input、output)
// arg3---廠商選擇
//作 者:cheyl 2009-12-20
//返回值 :配置正確返回true,否則爲false
//舉 例: getIntInfo("f0/0","output","s");
//************************************************************************
function getIntInfo(arg1,arg2,arg3)
{
var rowTemp,result,resultTemp;
var viewTemp = new view();
var regTempIp = RegExp("(\\d{1,3}\.){3}\\d{1,3}");
var regTempMask = RegExp("/\\d*");
var regTempState = RegExp("\\bdown\\b|\\bup\\b");
var regTempMac = RegExp("(\\w{4}\.){3}");
var regTempSpeed = RegExp("10{1,4}");
var regTempMtu = RegExp("\\d+");
var regTempDuplex = RegExp("half|full","i");
var regTempInOutStatistcs = RegExp("\\d*");
var regTempConfig = RegExp("config");
switch(arg3)
{
case "s":
resultTemp = getIntInfoCisco();
break;
case "h":
resultTemp = getIntInfoH3c();
break;
default:
resultTemp = getIntInfoLeadsec();
break;
}
function getIntInfoCisco()
{
var rowTemp = crt.screen.CurrentRow;
var result = crt.screen.get(rowTemp, 1, rowTemp, 80);
var resultTemp;
if(regTempConfig.exec(result))
{
crt.screen.send("end"+"\r");
crt.screen.WaitForString("#");
}
crt.screen.send("show interface " + arg1 + "\r\r\r\r");
crt.screen.WaitForString("#");
var row = crt.screen.CurrentRow;
//arg1 = {ip、mask、state、mac、speed、mtu、duplex、input、output}
//regexp = regTempIpMask,regTempState,regTempMac,regTempSpeed,regTempMtu,regTempDuplex,regTempInOutStatistcs
switch(arg2)
{
case "ip":
result = crt.screen.get(row-24, 1, row-24, 80);
resultTemp = result.match(regTempIp)[0];
break;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章