關於介面測試——自動化框架的設計與實現
一、自動化測試框架
在大部分測試人員眼中只要沾上“框架”,就感覺非常神祕,非常遙遠。大家之所以覺得複雜,是因為落地運用起來很複雜;每個公司,每個業務及產品線的業務流程都不一樣,所以就導致了“自動化測試框架”去完成自動化測試的時候產生很多不穩定因素,這樣就很難定位成一個固定的框架。其實不然,真正的自動化測試框架不是一個模式,而是一種思想和方法的集合,通俗的講就是一個架構。
二、自動化測試框架思想
為了更好的瞭解自動化測試框架,我們先從自動化測試的發展歷程說起;一般測試工作限在3年以上且接觸過自動化測試的應該對以下幾種自動化測試框架思想有一定的認知:
-
模組化思想
-
庫思想
-
資料驅動思想
-
關鍵字驅動思想
以上僅僅是代表了一種自動化測試的思想,並不能定義為框架。上面講到框架=思想+方法,於是演化了以下五種框架:
1、模組化測試指令碼框架
需要建立小而獨立的可以描述的模組、片斷以及待測應用程式的指令碼。這些樹狀結構的小指令碼組合起來,就能組成能用於特定的測試用例的指令碼。
2、測試庫框架
與模組化測試指令碼框架很類似,並且具有同樣的優點。不同的是測試庫框架把待測應用程式分解為過程和函式而不是指令碼。這個框架需要建立描述模組、片斷以及待測應用程式的功能庫檔案。
3、關鍵字驅動或表驅動的測試框架
這個框架需要開發資料表和關鍵字。這些資料表和關鍵字獨立於執行它們的測試自動化工具,並可以用來“驅動"待測應用程式和資料的測試指令碼程式碼,關鍵宇驅動測試看上去與手工測試用例很類似。在一個關鍵字驅動測試中,把待測應用程式的功能和每個測試的執行步驟一起寫到一個表中。
這個測試框架可以通過很少的程式碼來產生大量的測試用例。同樣的程式碼在用資料表來產生各個測試用例的同時被複用。
4、資料驅動測試框架
在這裡測試的輸入和輸出資料是從資料檔案中讀取(資料池,ODBC源,CSV檔案,EXCEL檔案,Json檔案,Yaml檔案,ADO物件等)並且通過捕獲工具生成或者手工生成的程式碼指令碼被載入到變數中。在這個框架中,變數不僅被用來存放輸入值還被用來存放輸出的驗證值。整個程式中,測試指令碼來讀取數值檔案,記載測試狀態和資訊。這類似於表驅動測試,在表驅動測 試中,它的測試用例是包含在資料檔案而不是在指令碼中,對於資料而言,指令碼僅僅是一個“驅動器”,或者是一個傳送機構。然而,資料驅動測試不同於表驅動測試,儘管導航資料並不包含在表結構中。在資料驅動測試中,資料檔案中只包含測試資料。
5、混合測試自動化框架
最普遍的執行框架是上面介紹的所有技術的一個結合,取其長處,彌補其不足。這個混合測試框架是由大部分框架隨著時間並經過若干專案演化而來的。
三、介面自動化測試框架策略
-
設計出來的框架是直接給測試人員,而且其他的測試人員只需要簡單的向裡面不斷的補充測試用例即可;所以我們的框架設計必須三簡化即操作簡單,維護簡單,擴充套件簡單。
-
設計框架的同時一定要結合業務流程,而且不僅僅靠技術實現,其實技術實現不難,難點對業務流程的理解和把握。
-
設計框架時要將基礎的封裝成公用的,如:get請求、post請求和斷言封裝成同基礎通用類。
-
測試用例要與程式碼分享,這樣便於用例管理,所以將我們選擇上面的資料驅動思想。
四、介面自動化測試框架設計
1、進行介面框架設計前,我們先看看當前的一些主流介面自動化工具框架
2、以上各工具特性
工具 | 學習 成本 | 錄製 | 持續整合 | 測試報告 | 用例管理 | 效能測試 | 擴充套件難度 | 最低要求 |
---|---|---|---|---|---|---|---|---|
Java+testng+Maven | 高 | 否 | 是 | 是 | 難 | 是 | 中 | Java |
Requests+Python | 低 | 否 | 是 | 是 | 難 | 是 | 中 | Python |
Robot Framework | 低 | 否 | 是 | 是 | 易 | 否 | 高 | 工具元件 |
HttpRunner | 低 | 是 | 是 | 是 | 易 | 是 | 低 | Python |
根據以上的特性可得我們優先考慮Python+Requests和HttpRunner;下面我們根據其兩個框架分別來分析下用例執行過程。
3、用例執行解析
Python的Requests庫針對所有的HTTP請求方法,採用的是統一的介面
requests.request(method, url, **kwargs)
其中,kwargs可以保護HTTP請求所有可能用到的資訊,例如:headers、cookies、params、data、auth等。所以,只要遵循Requests的引數規範,在介面測試用例中複用Requests引數的概念即可。而HttpRunner處理邏輯很簡單,直接讀取測試用例中的各項引數,傳遞給Requests發起請求。
1)Requests介面請求示例
def test_login(self):
url = "www.xxx.com/api/users/login"
data = {
"name": "user1",
"password": "123456"
}
resp = requests.post(url, json=data)
self.assertEqual(200, resp.status_code)
self.assertEqual(True, resp.json()["success"])
在該用例中,實現了HTTP POST請求,然後對響應結果進行判斷,檢查響應code等是否符合預期。
這樣的用例在實際專案中會存在兩個問題:
-
用例模式基本固定,會存在大量相似或重複的用例,用例維護有很大問題
-
用例與執行程式碼不分離,引數資料也未分離,同樣不易維護
2)HttpRunner使用json/yaml格式處理測試用例,分離後的用例描述如下
{
"name": "test login",
"request": {
"url": "www.xxx.com/api/users/login",
"method": "POST",
"headers": {
"content-type": "application/json"
},
"json": {
"name": "user1",
"password": "123456"
}
},
"response": {
"status_code": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"success": true,
"msg": "user login successfully."
}
}
}
3)HttpRunner用例執行引擎
def run_testcase(testcase):
req_kwargs = testcase['request']try:
url = req_kwargs.pop('url')
method = req_kwargs.pop('method')
except KeyError:
raise exception.ParamsError("Params Error")
resp_obj = requests.request(url=url, method=method, **req_kwargs)
diff_content = utils.diff_response(resp_obj, testcase['response'])
success = False if diff_content else True
return success, diff_content
4)從測試用例中獲取HTTP介面請求引數,testcase['request']
{
"url": "www.xxx.com/api/users/login",
"method": "POST",
"headers": {
"content-type": "application/json"
},
"json": {
"name": "user1",
"password": "123456"
}
}
5)發起Http請求
requests.request(url=url, method=method, **req_kwargs)
6)檢測測試結果,即斷言
utils.diff_response(resp_obj, testcase['response'])
五、介面自動化測試框架落地
根據簡單易用易維護原則我們使用HttpRunner工具設計框架。
1、HttpRunner簡介
主要特性:
-
集成了Requests的全部特性,滿足對http、https的各種測試需求
-
測試用例與程式碼分離,採用YAML/JSON的形式描述測試場景,保障測試用例具備可維護性
-
測試用例支援引數化和資料驅動機制
-
基於 HAR 實現介面錄製和用例生成功能
-
結合 Locust 框架,無需額外的工作即可實現分散式效能測試
-
執行方式採用 CLI 呼叫,可與 Jenkins 等持續整合工具完美結合
-
測試結果統計報告簡潔清晰,附帶詳盡統計資訊和日誌記錄
-
具有可擴充套件性,便於擴充套件實現 Web 平臺化
#### 2、環境準備
安裝HomeBrew(MacOs軟體包管理工具,類似apt-get、yum)
- 終端執行
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- 安裝pyenv並配置環境變數:python版本管理器,可同時管理多個Python版本(HttpRunner是基於Python開發,但是支援Python3.6.0以上)
brew install pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
exec $SHELL -l
- 安裝Python3.6
pyenv install --list //檢視可安裝的Python版本
pyenv install 3.6.0 //安裝3.6.0版本
pyenv rehash //更新pyenv
pyenv versions //檢視已經安裝的python版本,帶*號的是當前使用的版本
- 選擇Pyhton
pyenv global 3.6.0 //設定全域性版本,即當前系統使用的版本將切換為3.6.0
- 安裝HttpRunner並校驗
pip install httprunner
//執行如下命令,若正常顯示版本號,則說明httprunner安裝成功:
hrun -V
0.9.8
至此HttpRunner已搭建完成
3、用例管理
在HttpRunner中,測試用例引擎最大的特色就是支援Yaml/Json格式的用例描述形式;
採用YAML/JSON格式編寫維護測試用例,優勢還是很明顯的:
-
相比於表格形式,具有更加強大的靈活性和更豐富的資訊承載能力;
-
相比於程式碼形式,減少了不必要的程式語言語法重複,並最大化地統一了用例描述形式,提高了用例的可維護性。
Yaml格式
Json格式
以下以數瀾--數棲平臺2.X中的研發平臺為例(採取Json格式)
場景:專案空間後,需要快速支援建立Demo示例,即自動建立各種目錄和任務。
1)確定業務流程所使用到的介面並通過Postman或Jmeter除錯通過及分好類
-
查詢類(Get請求)介面:查詢任務目錄、查詢資源組、查詢工作流等
-
新增類(Post請求)介面:新建目錄、新建任務等
2)根據業務流程確定介面順序
- 如要在某個目錄下新建任務:則先要呼叫新建目錄介面再呼叫作建任務介面
3)向Json檔案裡按照規則填寫介面相關資訊
-
介面Base_Url
-
介面路徑
-
介面請求方式
-
介面請求引數
-
介面斷言
-
介面返回引數(關聯介面時會用到上一介面返回的引數)
以下是部分用例示例
4)用例填寫完成後,執行用例檔案,如Json檔案為task.json
hrun task.json
5)檢視執行結果
-
在此目錄下會自動生成一個reports檔案,進入該資料夾可看到生成帶時間的html(執行一次就會生成一個Html檔案)
)
- 開啟此Html檢視
全部通過
部分通過
- 點選Log,可檢視具體請求資訊和返回資訊
- 點選trackback可檢視定位錯誤資訊
[作者簡介:泫空,6年測試相關工作經驗,曾任微醫集團搜尋測試負責人,負責服務端測試、介面自動化、持續整合測試和效能測試及測試開發。曾參與中國移動政企能