目前软件测试的自动化主要是接口的自动化,如selnium等UI自动化工具仅仅在回归测试中有所应用……
接口API的自动化分为两种,一种是使用工具,另一种是使用Python代码自动化测试;
接口主流的测试自动化工具主要有:
- Postman
- Jemeter
- Fiddler
其他的测试工具大多使用4要素:
- url
- methord
- headers
- body
接口文档一般是必有的,由开发经理或者架构师产出。
API自动化常用库
- Requests—>用于Python发送接口访问的请求
- Pytest—>驱动数据,组织测试用例
- Logging—>日志库
- Pymysql—>Python读取数据库
目前常用的是阿里的oceanbase库
Python代码测试是必要的,nginx反向代理后无法使用抓包工具进行抓包
库环境的应用版本选择要互不冲突。
库的安装:
#!/bin/sh
# 1升级 python3.8 和 pip3
apt install -y python3.8
rm -rf /usr/bin/python3
ln -s /usr/bin/python3.8 /usr/bin/python3
# 2.安装课程需要的库
pip3 install requests==2.18.4
## 官方bug修复https://www.osgeo.cn/pytest/announce/release-6.0.1.html
pip3 install pytest==6.0.1
pip3 install pytest-html==3.1.1
#注意这里是对指定版本修复升级 不能下载最新版本 库之间不兼容的~!
pip3 install pytest==8.0.1
pip3 install attrs==19.1.0
pip3 install PyMySQL==1.0.2
pip3 install allure-pytest==2.9.45
Request 库
官方网站:https://pypi.org/
近期API:https://requests.readthedocs.io/en/latest/api/
库-对象名 | 对象API功能 |
requests | 发请求 |
1.1get (url=&拼接参数值,headers请求头) 1.2 post请求 1.2.1 发送请求体式字符串 post(url,headers请求头,data=请求体数据) 1.2.2 发送请求体json| 字典 post(url,headers请求头,json=请求体数据) | |
响应结果: encoding=’utf-8′ 2.1 状态码 status_code 2.2 响应头 结果.headers 2.3 响应体 2.3.1 字符串响应体 text 2.3.2 json响应体 json() |
上下游接口调试
#1 接口文档要素
import requests
# 运维服务器 + 接口地址
login_url="http://localhost:6088/api/User"
login_headers={'Content-Type':'application/json'}
login_method='post'
login_body={
"username": "admin" ,
"password": "123"}
# = 左边API表
# = 右边实际参数 来自于接口文档
shiji=requests.post(url=login_url,headers=login_headers,json=login_body)
print(shiji.status_code)
print(shiji.headers)
print(shiji.json())
# 下游代码---》一个值 环境变量~ 正则表达提取器 存 {{}} ${}引用
shouquanma=shiji.headers['Authorization']
print(shouquanma)
# 发出下游接口
# 运维服务器 + 接口地址
user_url='http://localhost:6088/api/User?IsEnabled=true&Page=1'
url_headers={'Authorization':shouquanma}
user_method='get'
# = 左边API表
# = 右边实际参数 来自于接口文档
shiji=requests.get(url=user_url,headers=url_headers)
print(shiji.status_code)
print(shiji.headers)
print(shiji.json())
requests 库提供了API(application program interface )
上游传递授权码时可以使用get+默认值的方式:
# 下游代码---》一个值 环境变量~ 正则表达提取器 存 {{}} ${}引用
shouquanma=shiji.headers.get('Authorization','error')
也可以使用try:
try:
# 提取json响应体
body=shiji.json()
except: # try 中报错执行本分支+ 断言 失败 执行本分支~
body="无结果~"
print("获取结果失败有bug~")
else: # try 中不报错执行本分支 +断言成功 执行本分支
print("获取结果成功无bug~")
finally: # 不管try 是否有异常 都要运行~
print(body)
print("获取结果结束~")
Pytest 库
和unitest一样的单元测试框架,但是更加方便,自带报告,更方便的ddt(数据驱动)
# 导入 pytest 测试框架
import pytest
# 定义 TestOrdering 类
class Test11():
# 定义 test_login11() 方法
def test_login11(self):
print(" 正在执行登录用例第一条 ")
# 定义 test_add() 方法
def test_login22(self):
print(" 正在执行登录用例第二条 ")
# 定义 test_del() 方法
def test_login33(self):
print(" 正在执行登录用例第三条 ")
if __name__ == '__main__':
'''
运行方式,直接在文件内执行以下命令
其中, -v 参数显示命令执行过程, -s 参数显示打印的信息
如不加 -s 参数,则 print() 函数打印的信息不会显示
'''
pytest.main(['-v','-s','jw1.py'])
if判断语句检测的是脚本是否是直接运行的,还是被导入的,只有直接运行时才会执行下面的测试用例执行器。
测试固件:(老版本只用setup,teardown)
# 导入 pytest 测试框架
import pytest
# 定义 TestOrdering
class Test11():
def setup_class(self):
print('all the test case preparation')
def teardown_class(self):
print('all the test case closure')
def setup_method(self):
print('test case preparation')
def teardown_method(self):
print('test case closure')
# 定义 test_login11() 方法
def test_login11(self):
print(" 正在执行登录用例第一条 ")
# 定义 test_add() 方法
def test_login22(self):
print(" 正在执行登录用例第二条 ")
# 定义 test_del() 方法
def test_login33(self):
print(" 正在执行登录用例第三条 ")
if __name__ == '__main__':
'''
运行方式,直接在文件内执行以下命令
其中, -v 参数显示命令执行过程, -s 参数显示打印的信息
如不加 -s 参数,则 print() 函数打印的信息不会显示
'''
pytest.main(['-v','-s','test.py'])
写用例,调用开发代码:
import pytest
from testdev import Count
class TestAdd():
def test_add(self):
# # design test case-->expect result
# a = 1
# b = 2
# expect = 3
# # #invoke development code,test procedure---->actual result
# c1 = Count(a, b)
# result = c1.add()
# # #result of assertion:
# assert result == expect
# #symplify the above code to:
assert Count(50,50).add()
if __name__ == '__main__':
pytest.main(['-v','-s','test2.py'])
练习,调用素数检查模块功能,使用真假断言,非断言:
import pytest
from tsetdev1 import is_prime
class TestCord:
def test_1(self):
assert is_prime(19)
def test_2(self):
assert not is_prime(9)
if __name__ == '__main__':
pytest.main(['-v', '-s', 'test3.py'])
pytest进行数据驱动:
每条用例的参数不同而过程相同时,可以进行参数化,方便ddt。
语法:
@pytest.mark.parametrize(‘参数名字’,[数据])
def test_xxx(self,参数名):(self是类的第一个固定参数,如果参数化的方法写到了类里面就必须加上self)
pass
参数的数据类型没有要求但是要一致。
列表中的数据个数决定了执行次数。
例子:
import pytest
@pytest.mark.parametrize('username', ['lucy', 'natsu', 'gray'])
class TestCode:
def test_1(username):
print(f'the test case is {username}')
if __name__ == '__main__':
pytest.main(['-s','-v','test4.py'])
数据为元组:
import pytest
from testdev import Count
class Test():
@pytest.mark.parametrize('Data',[(1,2,3),(2,3,5),(3,6,9)])
def test_1(self,Data):
print(f"current use case data :{Data}")
assert Data[2]==Count.add(Data[0],Data[1])
if __name__ == '__main__':
pytest.main(['-v','-s','test5.py'])
一条用例有多个数据的,比如有用户名密码和预期结果的时候:
1、单参数加字典实现:
import pytest
from testdev import Count
class Test():
@pytest.mark.parametrize('Data',[(1,2,3),(2,3,5),(3,6,9)])
def test_1(self,Data):
print(f"current use case data :{Data}")
assert Data[2]==Count.add(Data[0],Data[1])
if __name__ == '__main__':
pytest.main(['-v','-s','test5.py'])
2、多参数实现:
import pytest
@pytest.mark.parametrize('username',['natsu','gray','arsa'])
@pytest.mark.parametrize('pwd',['123','456','789'])
@pytest.mark.parametrize('expect',[True,True,False])
def test_login(username,pwd,expect):
print(f'current use case username:{username},pwd:{pwd},expect:{expect}')
if __name__ == '__main__':
pytest.main(['-sv','test7.py'])
多参数遍历了所有的参数,如上面这个代码遍历了27条用例,实际上不能很好的确定用例的预期结果。 需要使用pymysql代码。
数据驱动主要以单驱动为主。
发表回复