一.流程說明
二.配置config
1. 為什么要配置奕枢?
在接口測(cè)試過程中娄昆,會(huì)有好多參數(shù)需要指定,如果沒有一個(gè)統(tǒng)一的配置文件的話缝彬,數(shù)據(jù)會(huì)散落在各個(gè)測(cè)試用例中萌焰,后期維護(hù)的時(shí)候特別浪費(fèi)時(shí)間。
為了解決這個(gè)問題谷浅,我們?cè)黾恿艘粋€(gè)配置文件扒俯,python自帶的有一個(gè)配置文件的模塊為-ConfigParser,支持動(dòng)態(tài)配置數(shù)據(jù)一疯。
在測(cè)試過程中撼玄,為了區(qū)分測(cè)試環(huán)境和正式環(huán)境的數(shù)據(jù),我們配置了兩套文件墩邀,其中test_data.ini為測(cè)試環(huán)境的數(shù)據(jù)文件掌猛,formal_data.ini為正式環(huán)境的數(shù)據(jù)。
2. 如何配置眉睹?
2.1 ini文件配置格式
解釋說明:
[test]:為分組的名稱荔茬,不區(qū)分大小寫,不要與其他分組名稱重復(fù)辣往;一個(gè)分組下可以配置多個(gè)數(shù)據(jù)信息兔院,注意不要重名
username = test001: 為test組下的數(shù)據(jù)信息
password = 123456:也是test組下的數(shù)據(jù)信息殖卑,不要與同分組下的數(shù)據(jù)信息重名
2.2 讀取ini配置文件
文件位置:wechatInterfaceTestCases--parameters--common_config.py
讀取方法:
from parameters.common_config import CommonConfig
class Common(CommonConfig):
def test_useranme(self):
"""
讀取配置文件中的test分組中的username
:return:
"""
return self.cf.get("test", "username")
三.增加參數(shù)文件站削,獲取參數(shù)信息
1. 為什么要有參數(shù)文件?
參數(shù)文件是為了提取ini文件中的數(shù)據(jù)孵稽,參數(shù)文件對(duì)應(yīng)ini配置文件的分組信息许起,比如公共數(shù)據(jù)[test],對(duì)應(yīng)test.py文件菩鲜;test組下面的的username和password园细,對(duì)應(yīng)common.py的username和password方法。
如果直接把所有的數(shù)據(jù)存放到一個(gè)文件中接校,那這個(gè)文件會(huì)非常龐大猛频,如果遇到不同分組下的同名數(shù)據(jù),還會(huì)導(dǎo)致debugtalk調(diào)用的時(shí)候出現(xiàn)混亂的情況蛛勉。
像這樣分開設(shè)計(jì)鹿寻,可以更方便、直接的查找和調(diào)用自己需要的數(shù)據(jù)诽凌。
2. 如何增加參數(shù)文件毡熏?
ini文件中,當(dāng)在某個(gè)分組下增加數(shù)據(jù)的時(shí)候侣诵,就需要在對(duì)應(yīng)的配置文件下增加相應(yīng)的獲取參數(shù)信息方法痢法;當(dāng)新增一個(gè)分組的時(shí)候狱窘,就要?jiǎng)?chuàng)建一個(gè)參數(shù)文件,并增加獲取參數(shù)信息相應(yīng)的方法财搁。
配置位置:參數(shù)文件統(tǒng)一放置在parameters文件下
文件命名規(guī)則:一般為ini文件中的分組名稱蘸炸,例如:test.py
方法命名規(guī)則:一般為ini中分組下的數(shù)據(jù)名稱,例如:username
3. 如何獲取參數(shù)信息尖奔?
"""
獲取參數(shù)信息
:author: test <test@test.com>
"""
from parameters.common_config import CommonConfig
class Test(CommonConfig):
def username(self):
"""
用戶名
:return:
"""
return self.cf.get("test", "username")
def password(self):
"""
密碼
:return:
"""
return self.cf.get("test", "password")
文件中要增加注釋幻馁,首先是頂部注釋,注明文件的主要內(nèi)容越锈;其次是方法的注釋仗嗦,注釋此方法的內(nèi)容。
四.debugtalk
1. 什么是debugtalk甘凭?
文檔中是這樣說明的:
HttpRunner 的實(shí)現(xiàn)方式為稀拐,支持熱加載的插件機(jī)制(debugtalk.py),可以在 YAML/JSON 中調(diào)用 Python 函數(shù)丹弱。具體地做法德撬,我們可以在測(cè)試用例文件的同級(jí)或其父級(jí)目錄中創(chuàng)建一個(gè) debugtalk.py 文件,然后在其中定義相關(guān)的函數(shù)和變量躲胳。
2. 如何使用debugtalk蜓洪?
例如,我們需要一個(gè)獲取ini文件test分組中的username方法坯苹,可以定義一個(gè)test_useranme函數(shù)
from parameters.test import Test
test = Test()
def test_useranme():
"""
獲取test分組下的用戶名
:return:
"""
return test.username()
然后隆檀,我們?cè)?JSON 測(cè)試用例文件中,就可以對(duì)定義的函數(shù)進(jìn)行調(diào)用粹湃,對(duì)定義的變量進(jìn)行引用了恐仑。引用變量的方式仍然與前面講的一樣,采用{func($var)}裳仆。
"variables": [
{"username": "${test_username()}"}
]
五.編寫用例
1. 測(cè)試用例組織形式
在 HttpRunner 中,測(cè)試用例組織主要基于兩種概念(在不考慮用例分層概念的情況下):
測(cè)試用例集(testset):?jiǎn)蝹€(gè)或多個(gè)測(cè)試用例的集合孤钦,存儲(chǔ)形式為一個(gè) JSON 文件
測(cè)試用例(testcase):?jiǎn)未握?qǐng)求歧斟、響應(yīng)、校驗(yàn)過程偏形,對(duì)應(yīng) JSON 文件中的一個(gè) test
對(duì)于單個(gè) JSON 文件來說静袖,數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)為 list of dict 的形式,其中可能包含一個(gè)全局配置項(xiàng)(config)和若干個(gè)測(cè)試用例(test)壳猜;測(cè)試用例存在順序關(guān)系勾徽,運(yùn)行時(shí)將從前往后依次運(yùn)行。
[
{
"config": {...}
},
{
"test": {...}
}
]
config:作為整個(gè)測(cè)試用例集的全局配置項(xiàng)
test:對(duì)應(yīng)單個(gè)測(cè)試用例
2.用例組織結(jié)構(gòu)
config:
{
"config": {
"name": "小程序自考圈接口自動(dòng)化腳本",
"variables": [
{"openId":"${self_test_circle_openId()}"},
{"msgContent":"${self_test_circle_msgContent()}"},
{"zkTopicId":"${self_test_circle_zkTopicId()}"},
{"zkPersonId":"${self_test_circle_zkPersonId()}"}
],
"request": {
"base_url": "${base_url()}",
"headers":{
"mobile_type":"${mobile_type()}",
"Accept-Encoding":"${header_Accept_Encoding()}",
"User-Agent":"${header_User_Agent()}",
"Connection":"${header_Connection()}"
}
}
}
}
name:測(cè)試用例集的名稱,在測(cè)試報(bào)告中將作為標(biāo)題
variables:定義的全局變量喘帚,作用域?yàn)檎麄€(gè)用例集;在本測(cè)試框架中畅姊,測(cè)試用例集中用到的所有變量,統(tǒng)一放在config中的variables下吹由,test只調(diào)用若未,不再定義新的變量;目的是直接明了的知道該測(cè)試用例集下有多少個(gè)變量被使用了倾鲫,也方便后續(xù)的修改和優(yōu)化
request:request 的公共參數(shù)粗合,作用域?yàn)檎麄€(gè)用例集
base_url:測(cè)試用例集請(qǐng)求 URL 的公共 host,指定該參數(shù)后乌昔,test 中的 url 可以只描述 path 部分
headers:request 中 headers 的公共參數(shù)隙疚,作用域?yàn)檎麄€(gè)用例集;headers中的信息可以使用fiddler或者charles錄制出來磕道,一般需要指定Accept-Encoding供屉、User-Agent、Connection溺蕉;其他參數(shù)可以自己選擇是否需要伶丐。
test:
{
"test": {
"name": "22.2 自考百科問題列表api-問題類型-正常情況",
"parameters":[
{"type":["1", "2"]}
],
"request": {
"url": "/wechat/wiki/questionByType",
"method": "GET",
"params":{
"type":"$type"
}
},
"extract": [
{"status_code22_2": "status_code"}
],
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["headers.Content-Type",
"application/json;charset=UTF-8"]},
{"eq": ["content.state", 1]},
{"eq": ["content.alertMessage", "找到匹配數(shù)據(jù)。"]},
{"eq": ["content.message", "obtain success."]},
{"type_match": ["content.content", "dict"]},
{"type_match": ["content.content.data", "list"]},
{"type_match": ["content.content.data.0.id", "int"]},
{"type_match": ["content.content.data.0.reportKey", "str"]},
{"type_match": ["content.content.data.0.title", "str"]},
{"type_match": ["content.content.data.0.totalTimes", "int"]},
{"eq": ["content.content.data.0.type", "${str_transformt_int($type)}"]},
{"type_match": ["content.content.descript", "str"]},
{"type_match": ["content.content.total", "int"]},
{"eq": ["content.content.type", "${str_transformt_int($type)}"]},
{"eq": ["content.message", "obtain success."]}
]
}
}
name:測(cè)試用例的名稱疯特,在測(cè)試報(bào)告中將作為每一項(xiàng)測(cè)試的標(biāo)題
parameters:測(cè)試用例中定義的參數(shù)列表哗魂,作用域?yàn)楫?dāng)前測(cè)試用例,用于實(shí)現(xiàn)對(duì)當(dāng)前測(cè)試用例進(jìn)行數(shù)據(jù)化驅(qū)動(dòng)
request:HTTP 請(qǐng)求的詳細(xì)內(nèi)容
params:請(qǐng)求參數(shù)
extract:從當(dāng)前 HTTP 請(qǐng)求的響應(yīng)結(jié)果中提取參數(shù)漓雅,并保存到參數(shù)變量中(例如token)录别,后續(xù)測(cè)試用例可通過$token的形式進(jìn)行引用
validate:測(cè)試用例中定義的結(jié)果校驗(yàn)項(xiàng),作用域?yàn)楫?dāng)前測(cè)試用例故硅,用于實(shí)現(xiàn)對(duì)當(dāng)前測(cè)試用例運(yùn)行結(jié)果的校驗(yàn)
六.舉例說明
步驟一:配置ini文件
目錄位置:config/test_data.ini
test_data.ini文件:
[common]
base_url = https://www.sunlands.wang
openId = test0123456789
[header]
Accept-Encoding = gzip
User-Agent = Mozilla/5.0 (Linux; Android 7.1.1; OPPO R11 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043909 Mobile Safari/537.36 MicroMessenger/6.6.6.1300(0x26060636) NetType/WIFI Language/zh_CN MicroMessenger/6.6.6.1300(0x26060636) NetType/WIFI Language/zh_CN
content-type = application/x-www-form-urlencoded
content-type-two: application/json
Connection = Keep-Alive
mobile_type = android
步驟二:創(chuàng)建參數(shù)文件庶灿,調(diào)用ini中的數(shù)據(jù)
目錄位置:parameters/header.py;parameters/common.py
創(chuàng)建header.py文件
"""
header參數(shù)文件
:author: author <author@126.com>
"""
from parameters.common_config import CommonConfig
class Header(CommonConfig):
def Accept_Encoding(self):
"""
Accept_Encoding
:return:
"""
return self.cf.get("header", "Accept-Encoding")
def User_Agent(self):
"""
User_Agent
:return:
"""
return self.cf.get("header", "User-Agent")
def content_type(self):
"""
content_type
:return:
"""
return self.cf.get("header", "content-type")
def content_type_two(self):
"""
content_type_two
:return:
"""
return self.cf.get("header", "content-type-two")
def Connection(self):
"""
Connection
:return:
"""
return self.cf.get("header", "Connection")
def mobile_type(self):
"""
mobile_type
:return:
"""
return self.cf.get("header", "mobile_type")
創(chuàng)建common.py文件
"""
公共參數(shù)文件
:author: author <author@126.com>
"""
from parameters.common_config import CommonConfig
class Common(CommonConfig):
def base_url(self):
"""
base_url
:return:
"""
return self.cf.get("common", "base_url")
def openId(self):
"""
微信openId
:return:
"""
return self.cf.get("common", "openId")
步驟三:debugtalk獲取需要的測(cè)試數(shù)據(jù)
目錄位置:testCase/debugtalk.py
debugtalk.py文件:
"""
httprunner支持熱加載的插件機(jī)制,此函數(shù)供JSON測(cè)試用例文件調(diào)用
:author: author <author@126.com>
"""
from parameters.common import Common
from parameters.header import Header
common = Common()
header = Header()
def base_url():
"""
base_url
:return:
"""
return common.base_url()
def openId():
"""
微信openId
:return:
"""
return common.openId()
def mobile_type():
"""
終端類型
:return:
"""
return header.mobile_type()
def header_Accept_Encoding():
"""
:return:
"""
return header.Accept_Encoding()
def header_User_Agent():
"""
:return:
"""
return header.User_Agent()
def header_content_type():
"""
:return:
"""
return header.content_type()
def header_content_type_two():
"""
:return:
"""
return header.content_type_two()
def header_Connection():
"""
:return:
"""
return header.Connection()
步驟四:編寫測(cè)試用例
目錄位置:testCase/interface_test.json
創(chuàng)建interface_test.json文件
[
{
"config": {
"name": "測(cè)試用戶使用幫助相關(guān)接口自動(dòng)化腳本",
"variables":[
{"openId":"${openId()}"}
],
"request": {
"base_url": "${base_url()}",
"headers":{
"mobile_type":"${mobile_type()}",
"Accept-Encoding":"${header_Accept_Encoding()}",
"User-Agent":"${header_User_Agent()}",
"content-type":"${header_content_type_two()}",
"Connection":"${header_Connection()}"
}
}
}
},
{
"test": {
"name": "獲取是否彈出紅包-正常情況",
"request": {
"url": "/wechat/getIsThongbao",
"method": "GET",
"params":{
"openId":"$openId"
}
},
"extract": [
{"status_code": "status_code"}
],
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["headers.Content-Type",
"application/json;charset=UTF-8"]},
{"eq": ["content.state", 1]},
{"eq": ["content.message", "success"]},
{"type_match": ["content.content.flag", "int"]}
]
}
},
{
"test": {
"name": "獲取上一個(gè)test提取的status_code并檢查",
"request": {
"url": "/wechat/getIsThongbao",
"method": "GET"
},
"validate": [
{"eq": ["$status_code", 200]}
]
}
}
]
步驟五:運(yùn)行測(cè)試用例
運(yùn)行測(cè)試用例的命令為hrun吃衅,后面直接指定測(cè)試用例文件的路徑即可
hrun testCase/interface_test.json
步驟六:查看測(cè)試報(bào)告
目錄位置:report/*.html
七. 參考網(wǎng)址:
HttpRunner中文使用手冊(cè):http://cn.httprunner.org/
httprunner中validate的比較方法總結(jié):http://www.reibang.com/p/0367fb6ab5a2