测试开发进阶(三十三)

测试开发进阶(三十三)

局部变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: 登录接口
variables:
username: ${ENV(USERNAME)}
password: ${ENV(PASSWORD)}
request:
url: http://127.0.0.1:8000/user/login/
method: POST
headers:
Content-Type: "application/json"
json:
username: $username
password: $password
validate:
- eq: ["status_code", 200]
extract:
- uname: content.username

可以修改variables定义变量,导入环境变量作为值

request中可以使用$变量名来获取variables区域下的变量

调用函数

可以调用debugtalk.py中的函数

例如在该文件中添加

1
2
3
def get_user_agent():
user_agents = ['Mozilla/5.0 AAA', 'Mozilla/5.0 BBB', 'Mozilla/5.0 CCC']
return random.choice(user_agents)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name: 登录接口
variables:
username: ${ENV(USERNAME)}
password: ${ENV(PASSWORD)}
request:
url: http://127.0.0.1:8000/user/login/
method: POST
headers:
Content-Type: "application/json"
User-Agent: ${get_user_agent()}
json:
username: $username
password: $password
validate:
- eq: ["status_code", 200]

使用${get_user_agent()}

这样就可以动态的使用User-Agent

校验

可以用的响应属性:

  • available
  • response
  • status_code
  • cookies
  • elapsed
  • headers
  • content
  • text
  • json
  • encoding
  • ok
  • reason
  • url
1
- eq: ["headers.Content-Type", "application/json"]
1
- {check: "headers.Content-Type",comparator: "eq",expect: "application/json"}

上面两种写法效果一致

  • check:指定断言哪一个字段(实际值)

python3.7/site-packages/httprunner/built_in.py

  • comparator:指定断言的规则
    • eq 等于
    • lt小于
    • lte
    • gt大于
    • gte
    • str_eq
    • len_eq长度等于
    • len_gt
    • contains 包含
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
""" 
built-in comparators
"""
def equals(check_value, expect_value):
assert check_value == expect_value

def less_than(check_value, expect_value):
assert check_value < expect_value

def less_than_or_equals(check_value, expect_value):
assert check_value <= expect_value

def greater_than(check_value, expect_value):
assert check_value > expect_value

def greater_than_or_equals(check_value, expect_value):
assert check_value >= expect_value

def not_equals(check_value, expect_value):
assert check_value != expect_value

def string_equals(check_value, expect_value):
assert builtin_str(check_value) == builtin_str(expect_value)

def length_equals(check_value, expect_value):
assert isinstance(expect_value, integer_types)
assert len(check_value) == expect_value

def length_greater_than(check_value, expect_value):
assert isinstance(expect_value, integer_types)
assert len(check_value) > expect_value

def length_greater_than_or_equals(check_value, expect_value):
assert isinstance(expect_value, integer_types)
assert len(check_value) >= expect_value

def length_less_than(check_value, expect_value):
assert isinstance(expect_value, integer_types)
assert len(check_value) < expect_value

def length_less_than_or_equals(check_value, expect_value):
assert isinstance(expect_value, integer_types)
assert len(check_value) <= expect_value

def contains(check_value, expect_value):
assert isinstance(check_value, (list, tuple, dict, basestring))
assert expect_value in check_value

def contained_by(check_value, expect_value):
assert isinstance(expect_value, (list, tuple, dict, basestring))
assert check_value in expect_value

def type_match(check_value, expect_value):
def get_type(name):
if isinstance(name, type):
return name
elif isinstance(name, basestring):
try:
return __builtins__[name]
except KeyError:
raise ValueError(name)
else:
raise ValueError(name)

assert isinstance(check_value, get_type(expect_value))

def regex_match(check_value, expect_value):
assert isinstance(expect_value, basestring)
assert isinstance(check_value, basestring)
assert re.match(expect_value, check_value)

def startswith(check_value, expect_value):
assert builtin_str(check_value).startswith(builtin_str(expect_value))

def endswith(check_value, expect_value):
assert builtin_str(check_value).endswith(builtin_str(expect_value))
  • expect预期结果

数据驱动

testcases/login.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
config:
name: "登录接口测试"
variables:
device_sn: "ABC"
username: ${ENV(USERNAME)}
password: ${ENV(PASSWORD)}
base_url: "http://127.0.0.1:8000"

teststeps:
-
name: 登录
api: api/login.yml
validate:
- eq: ["status_code", 200]

继承api/login.yml会与本区域定义的validate合并覆盖

一般api路径下的断言只进行基础类型的断言例如status_code

testcases会进行其他的断言

方式一:使用yaml

testsuites/api_testsuite.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
config:
name: 接口测试套件
base_url: "http://127.0.0.1:8000"

testcases:
-
name: 登录接口
testcase: testcases/login.yml
parameters:
# 方式一
# 多个具有关联性的参数,需要将其定义在一起,并且采用短横线进行连接
- title-username-password-status_code-contain_msg:
- ["正常登录", "zhongxin", "123456", 200, "token"]
- ["密码错误", "zhongxin", "1234567", 400, "non_field_errors"]
- ["账号错误", "zhongxin11", "123456", 400, "non_field_errors"]
- ["用户名为空", "", "123456", 400, "username"]
- ["密码为空", "zhongxin", "", 400, "password"]

运行

1
$ hrun testsuites/api_testsuite.yml

查看报告

报告

方式二:读取文件

新建一个csv文件

1
2
3
4
5
6
title,username,password,status_code,contain_msg
正常登录, zhongxin, 123456, 200, token
密码错误, zhongxin, 1234567, 400, non_field_errors
账号错误, zhongxin11, 123456, 400, non_field_errors
用户名为空, , 123456, 400, username
密码为空, zhongxin, , 400, password
1
- title-username-password-status_code-contain_msg: ${P(datas/accounts.csv)}

方式三:使用函数

debugtalk.py添加

1
2
3
4
5
6
def get_accounts():
accounts = [
{"title": "正常登录", "username": "zhongxin", "password": "123456", "status_code": 200, "contain_msg": "token"},
{"title": "密码错误", "username": "zhongxin", "password": "1234567", "status_code": 400, "contain_msg": "non_field_errors"},
]
return accounts
1
- title-username-password-status_code-contain_msg: ${get_accounts()}

使用py文件调用httprunner

1
2
3
4
5
6
7
8
9
10
11
from httprunner.api import HttpRunner

# 创建HttpRunner对象
# failfast:False 用例执行失败后不终止
runner = HttpRunner(failfast=False)
# 运行用例
# run方法支持如下参数
# yaml用例文件的路径
# 字典(用例的信息)
runner.run('/Users/zhongxin/Desktop/httprunner_learn/testcases/login.yml')
print(runner.summary)
 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
您的支持将鼓励我继续创作!