testcase应该是完整且独立的,每条测试用例应该都是可以独立运行的。
首先通过charles对下面操作进行抓包
操作流程:
1.使用账号密码登录
2.新建文档
3.修改文档
使用charles过滤出与本次操作相关的请求数据,导出har包
将har包放到httprunner生成的脚手架项目中,使用har2case xx.har -2y命令解压成yml格式的用例
使用hrun xx.yml运行该用例,此时会运行失败,因为接口之间存在关联数据,而且这些关联数据是动态生成的(如每次执行新建文档都会生成一个新的文档id,后续的修改需要基于此id进行,而用例数据中的文档id是抓包时获取到的当时的id)。所以需要以参数的形式将这些数据进行关联并替换。替换完成后将数据按功能分为三条用例:login.yml、create_doc.yml和change_doc.yml,下面进行用例优化:
场景1:参数化
解决:使用extract将某个接口响应的数据作为参数,可以在其他接口中使用
场景2:用例有流程依赖时(如创建文档时需要先登录)
解决:在teststeps中使用testcase进行调用
场景3:用例有参数依赖时(如修改文档内容时,需要用到创建文档用例中的参数,documentId)
解决:在参数定义文件中使用export导出参数,并在调用文件中使用extract定义导出的参数
登录 login.yml (此处不涉及参数关联,具体内容省略不写了)
创建文档 create_doc.yml
config:
name: create doc # 用例名
variables: {}
verify: false # 开启charles代理时,不校验证书
base_url: https://mubu.com # 下面用例中用到的url会自动在base_url基础上扩展
teststeps: # 操作步骤
- name: login
testcase: testcases/login.yml # 调用登录用例,基于项目根目录使用相对路径【场景2】
export: # 导出参数,在其他文件中可以调用 【场景3】
- documentId
- name: /api/list/create_doc
request:
data:
folderId: '0'
type: '0'
headers:
content-type: application/x-www-form-urlencoded; charset=UTF-8
method: POST
url: /api/list/create_doc
extract: # 参数化 【场景1】
documentId: content.data.id # 取出响应数据中的documentId
- name: /doc${documentId} # 【场景1】通过${documentId}引用上面定义的参数
request:
headers:
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
method: GET
url: /doc${memberId} #通过${userId}引用上面定义的参数
validate:
- eq:
- status_code
- 200
修改文档 change_doc1.yml
config:
name: change doc
variables: {}
verify: false
teststeps:
# 创建文档
- name: create document
testcase: testcases/create_doc.yml # 修改文档前先创建文档,调用用例create_doc.yml
extract: # 【场景3】引用create_doc.yml 中定义的参数,与export对应
- documentId
# 修改文档
- name: /api/middleware/message
request:
headers:
document-id: '${documentId}'
request-id: MESSAGE:${userId}:${memberId}:33
json:
context:
appVersion: '0'
platform: web
data:
documentId: ${documentId}
method: POST
url: https://mubu.com/api/middleware/message
场景4:为了测试修改文档用例,不用像场景3,每次先新建再修改,可以直接使用已经存在的文档进行修改
解决:把文档documentId以全局参数写在文件中
修改文档 change_doc2.yml
config:
name: change doc
variables: # 【场景4】
documentId:cndfvek # 定义全局参数
verify: false
teststeps:
# 登录
- name: login
testcase: testcases/login.yml # 不需要重新创建但修改仍需在登录状态下操作
# 修改文档
- name: /api/middleware/message
request:
headers:
document-id: '${documentId}'
request-id: MESSAGE:${userId}:${memberId}:33
json:
context:
appVersion: '0'
platform: web
data:
documentId: ${documentId}
method: POST
url: https://mubu.com/api/middleware/message
场景5:httprunner默认对响应结果的一级内容做校验,实际工作中需要对深层次的某些具体响应字段做校验
解决:在validate中使用jsonpath定位字段进行校验,了解更多校验使用,参考https://debugtalk.com/post/HttpRunner-validator-optimization/
对response中的username进行校验
validate:
- eq:
- content.data.documents.0.userName
- tingjio
base_url的使用
场景:httprunner中提供了base_url,用例步骤中用到的url会自动在base_url基础上扩展,有些用例中包含多个url
解决:方法一:如果用例中需要用到多个url时,将url路径写全,则不会采用base_url的值
config:
name: create doc # 用例名
variables: {}
base_url: https://mubu.com # 下面用例中用到的缺省url会自动在base_url基础上扩展
teststeps:
- name: emo1
request:
method: POST
url: https://baidu.com # 全路径不会采用base_url的值
- name: demo2
request:
method: POST
url: /list # 在base_url基础上扩展
方法二:将多个url以不同的参数名定义在variables中,分别调用
config:
name: create doc # 用例名
variables:
url1: https://api.mubu.com # 有多个url时,可以在变量中定义
url2: https://test.mubu.com
url3: https://mubu.com
teststeps:
- name: emo1
request:
method: POST
url: ${url1}
- name: demo2
request:
method: POST
url: ${url2}
场景:正式/测试环境切换
解决:在debugtalk.py中定义切换函数,用例中调用切换函数
debugtalk.py
def get_base_url(env_type="prod"):
if env_type == 'prod':
return 'https://mubu.com'
else:
return 'https://test.mubu.com'
login.yml
config:
name: login
variables: {}
verify: false
base_url: ${get_base_url(test)} # 使用测试环境
使用环境变量env存储隐私变量
场景:测试用例涉及到登录时,登录账号和密码会以明文暴露在用例中,提交后会造成信息泄漏
解决:将隐私信息保存在env文件中,提交代码时不提交该文件,使用用例的人自己配置该文件
.env文件
USERNAME=18691335588
PASSWORD=zhouting414
login.yml
- name: demo
request:
data:
password: ${ENV(PASSWORD)} # 引用环境变量
phone: ${ENV(USERNAME)}
......