HttpRunner 的測試用例分層機制

發表于:2017-12-27來源: DebugTalk作者:DebugTalk點擊數: 標簽:HttpRunner
在 HttpRunner 中,測試用例引擎最大的特色就是支持 YAML/JSON 格式的用例描述形式。采用 YAML/JSON 格式編寫維護測試用例,優勢還是很明顯的:

在 HttpRunner 中,測試用例引擎最大的特色就是支持 YAML/JSON 格式的用例描述形式。

采用 YAML/JSON 格式編寫維護測試用例,優勢還是很明顯的:

  • 相比于表格形式,具有更加強大的靈活性和更豐富的信息承載能力;
  • 相比于代碼形式,減少了不必要的編程語言語法重復,并最大化地統一了用例描述形式,提高了用例的可維護性。

以最常見的登錄注銷為例,我們的測試用例通常會描述為如下形式:

- config:
name: demo-login-logoff
variable_binds:
- UserName: test001
- Password: 123456
request:
base_url: http://xxx.debugtalk.com
headers:
Accept: application/json
User-Agent: iOS/10.3

- test:
name: Login
request:
url: /api/v1/Account/Login
method: POST
json:
UserName: $UserName
Pwd: $Password
VerCode: ""
validators:
- eq: ["status_code", 200]
- eq: ["content.IsSuccess", True]
- eq: ["content.Code", 200]

- test:
name: Logoff
request:
url: /api/v1/Account/LoginOff
method: GET
validators:
- eq: ["status_code", 200]
- eq: ["content.IsSuccess", True]
- eq: ["content.Code", 200]

相信大家已經對該種用例描述形式十分熟悉了。不過,該種描述形式的問題在于,接口通常會出現在多個測試場景中,而每次都需要對接口進行定義描述,包括請求的URL、Header、Body、以及預期響應值等,這就會產生大量的重復。

例如,在某個項目中存在三個測試場景:

  • 場景A:注冊新賬號( API_1/2 )、登錄新注冊的賬號( API_3/4/5 )、查看登錄狀態( API_6 );
  • 場景B:登錄已有賬號( API_3/4/5 )、注銷登錄( API_7/8 );
  • 場景C:注銷登錄( API_7/8 )、查看登錄狀態( API_6 )、注冊新賬號( API_1/2 )。

按照常規的接口測試用例編寫方式,我們需要創建3個場景文件,然后在各個文件中分別描述三個測試場景相關的接口信息。示意圖如下所示。

在本例中,接口( API_1/2/6 )在場景A和場景C中都進行了定義;接口( API_3/4/5 )在場景A和場景B中都進行了定義;接口( API_7/8 )在場景B和場景C中都進行了定義??梢灶A見,當測試場景增多以后,接口定義描述的維護就會變得非常困難和繁瑣。

接口的分層定義描述

那要如何進行優化呢?

其實也很簡單,在編程語言中,如果出現重復代碼塊,我們通常會將其封裝為類或方法,然后在需要時進行調用,以此來消除重復。同樣地,我們也可以將項目的API進行統一定義,里面包含API的請求和預期響應描述,然后在測試場景中進行引用即可。

示意圖如下所示。

具體地,我們可以約定將項目的所有API接口定義放置在 api 目錄下,并在 api 目錄中按照項目的系統模塊來組織接口的定義;同時,將測試場景放置到 testcases 目錄中。

此時測試用例文件的目錄結構如下所示:

? tree tests
tests
├── api
│   └── v1
│       ├── Account.yml
│       ├── BusinessTrip.yml
│       ├── Common.yml
│       └── Leave.yml
├── debugtalk.py
└── testcases
    ├── scenario_A.yml
    ├── scenario_B.yml
    └── scenario_C.yml

而對于API接口的定義,與之前的描述方式基本一致,只做了兩點調整:

  • 接口定義塊( block )的標識為 api ;
  • 接口定義塊中包含 def 字段,形式為 api_name(*args) ,作為接口的唯一標識ID;需要注意的是,即使 api 沒有參數,也需要帶上括號, api_name() ;這和編程語言中定義函數是一樣的。
- api:
def: api_v1_Account_Login_POST($UserName, $Password)
request:
url: /api/v1/Account/Login
method: POST
json:
UserName: $UserName
Pwd: $Password
VerCode: ""
validators:
- eq: ["status_code", 200]
- eq: ["content.IsSuccess", True]
- eq: ["content.Code", 200]

- api:
def: api_v1_Account_LoginOff_GET()
request:
url: /api/v1/Account/LoginOff
method: GET
validators:
- eq: ["status_code", 200]
- eq: ["content.IsSuccess", True]
- eq: ["content.Code", 200]

有了接口的定義描述后,我們編寫測試場景時就可以直接引用接口定義了。

同樣是背景描述中的登錄注銷場景,測試用例就描述為變為如下形式。

- config:
name: demo
variable_binds:
- UserName: test001
- Password: 123456
request:
base_url: http://xxx.debugtalk.com
headers:
Accept: application/json
User-Agent: iOS/10.3

- test:
name: Login
api: api_v1_Account_Login_POST($UserName, $Password)

- test:
name: Logoff
api: api_v1_Account_LoginOff_GET()

不難看出,對API接口進行分層定義后,我們在測試用例場景中引用接口定義時,與編程語言里面調用函數的形式基本完全一樣,只需要指定接口的名稱,以及所需傳遞的參數值;同樣的,即使沒有參數,也需要帶上括號。

實現接口的分層定義描述后,我們就可以避免接口的重復定義。但是,我們回過頭來看之前的案例,發現仍然會存在一定的重復。

如上圖所示,場景A和場景C都包含了注冊新賬號( API_1/2 )和查看登錄狀態( API_6 ),場景A和場景B都包含了登錄已有賬號( API_3/4/5 ),場景B和場景C都包含了注銷登錄( API_7/8 )。

雖然我們已經將接口的定義描述抽離出來,避免了重復的定義;但是在實際業務場景中,某些功能(例如登錄、注銷)會在多個場景中重復出現,而該功能又涉及到多個接口的組合調用,這同樣也會出現大量的重復。

接口的模塊化封裝

玩過積木的同學可能就會想到,我們也可以將系統的常用功能封裝為模塊(suite),只需要在模塊中定義一次,然后就可以在測試場景中重復進行引用,從而避免了模塊功能的重復描述。

具體地,我們可以約定將項目的所有模塊定義放置在 suite 目錄下,并在 suite 目錄中按照項目的功能來組織模塊的定義。

后續,我們在 testcases 目錄中描述測試場景時,就可同時引用接口定義和模塊定義了;模塊和接口的混合調用,必將為我們編寫測試場景帶來極大的靈活性。

此時測試用例文件的目錄結構如下所示:

? tree tests
tests
├── api
│   └── v1
│       ├── Account.yml
│       ├── BusinessTrip.yml
│       ├── Common.yml
│       └── Leave.yml
├── debugtalk.py
├── suite
│   ├── BusinessTravelApplication
│   │   ├── approve-application.yml
│   │   ├── executive-application.yml
│   │   ├── reject-application.yml
│   │   └── submit-application.yml
│   └── LeaveApplication
│       ├── approve.yml
│       ├── cancel.yml
│       └── submit-application.yml
└── testcases
    ├── scenario_A.yml
    ├── scenario_B.yml
    └── scenario_C.yml

需要注意的是,我們在組織測試用例描述的文件目錄結構時,遵循約定大于配置的原則:

  • API接口定義必須放置在 api 目錄下
  • 模塊定義必須放置在 suite 目錄下
  • 測試場景文件必須放置在 testcases 目錄下
  • 相關的函數定義放置在 debugtalk.py 中

至此,我們實現了測試用例的 接口-模塊-場景 分層,從而徹底避免了重復定義描述。

腳手架工具

得益于約定大于配置的原則,在 HttpRunner 中實現了一個腳手架工具,可以快速創建項目的目錄結構。該想法來源于 Django 的 django-admin.py startproject project_name 。

使用方式也與 Django 類似,只需要通過 --startproject 指定新項目的名稱即可。

$ hrun --startproject helloworld
INFO:root: Start to create new project: /Users/Leo/MyProjects/helloworld
INFO:root:      created folder: /Users/Leo/MyProjects/helloworld
INFO:root:      created folder: /Users/Leo/MyProjects/helloworld/tests
INFO:root:      created folder: /Users/Leo/MyProjects/helloworld/tests/api
INFO:root:      created folder: /Users/Leo/MyProjects/helloworld/tests/suite
INFO:root:      created folder: /Users/Leo/MyProjects/helloworld/tests/testcases
INFO:root:      created file: /Users/Leo/MyProjects/helloworld/tests/debugtalk.py

運行之后,就會在指定的目錄中生成新項目的目錄結構,接下來,我們就可以按照測試用例的 接口-模塊-場景 分層原則往里面添加用例描述信息了。

總結

如果看到這里你還不明白測試用例分層的必要性,那也沒關系,測試用例分層不是必須的,你還是可以按照之前的方式組織測試用例。不過當你某一天發現需要進行分層管理時,你會發現它就在那里,很實用。

最后,在 HttpRunner 項目的 examples/HelloWorld 目錄中,包含了一份完整的分層測試用例示例,相信會對大家有所幫助。

原文轉自:http://debugtalk.com/post/HttpRunner-testcase-layer/

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97