python接口自动化测试(一)

一.既然我们有这些的接口测试工具,为什么要做接口做自动化?

1、敏捷开发,接口一般数量很大,团队实现接口测试,版本控制。
2、功能太死板,有些接口完全无法实现(复杂的加密接口,签名接口等)
3、接口项目当中有多种不同协议的接口。
4、排错,定位接口问题不方便,结合抓包实现。
5、没有办法生成美观的报告。
6、多接口串联,数据库验证,日志监控。
7、有些公司做web自动化+接口自动化。

二、python+requests模块

requests第三方库,主要用于发送http请求,做接口自动化。

#安装
pip install requests

三、接口自动化之requests全局观

请求
requests. get() 发送get请求
requests. post() 发送post请求
requests. delete() 发送delete请求
requests .put() 发送put请求
requests. request() 最核心的方法
import requests
rep = requests.request();
响应
rep.text 返回字符串的数据(文本格式)
rep.content 返回字节格式的数据(图片、文件)
rep.json() 返回字典格式的数据(json格式)
rep.status_code 状态码
rep.reason 返回状态信息
rep.cookies 返回cookie信息
rep.encoding 返回编码格式
rep.headers 返回响应头信息

四、接口实战

请求方式:get post put delete
请求参数类型: 键值对,JSON格式,文件格式

unittest、pytest管理用例框架:

前提是要安装pytest

pip install pytest

pytest默认规则:
1.py文件必须以test _ 开头或者 _ test结尾。
2类名必须以 Test 开头
3.测试用例必须以 test_ 开头

注意:

1、get请求通过params传递参数。
2、post请求通过json或者data传参。他们的区别是什么?
	data
		数据报文: dict字典类型,那么默认情况下请求头: application/x-www-form-urlencoded,
				表示以form表单的方式传参,格式: a=1&b=2&c=3
		数据报文: str类型,那么默认情况下: text/plain(如果是字典格式需要转换成str格式传参)
	json
		数据报文:不管是dict还是str类型,默认都是application/json ,格式: ({"a":1,"b".2)
		
data = {"tag": {"id": 134, "name": "广东人"}}
rep = requests.post(url=url, data=json.dumps(data))

json.dumps(data)序列化	把字典格式的数据转换成str格式.
json.loads(data)反序列化	把str格式转换成字典格式

总结:
data只能传递简单的只有键值对的dict或者是str格式。
json一般只能传dict格式(简单和嵌套都可以)
#3、文件传参files,且一定要open
data={
     "media":open(r"E:\shu.png","rb")
}
rep = requests.post(url=url, files=data)
#  以下代码运行不起来,但是写法没错
import pytest
import requests

class TestSendRequest:
    access_token=""
    def test_get_token(self):
        # 发送get请求
        url = "https://api.weixin.qq.com/cgi-bin/token"
        data = {
            "grant_type": "client_credential",
            "appid": "自己找素材",
            "secret": "自己找素材"
        }
        rep = requests.get(url=url, params=data)
        print(rep.json())
        TestSendRequest.access_token = rep.json()["access_token"]

    def test_edit_flag(self):
        # 发送post请求(data和json只需要传一个,data和json的区别)
        url = "https://api.weixin.qq.com/cgi-bin/token/tags/update?access_token=" + TestSendRequest.access_token + ""
        data = {"tag": {"id": 134, "name": "广东人"}}
        rep = requests.post(url=url, json=data)
        print(rep.json())

if __name__ == '__main__':
    #-vs 打印调试信息
    pytest.main(['-vs'])

1、cookie鉴权: 网页的接口基本上都要做cookie鉴权。(不常用)
给了token和请求头,但是请求还是fail,需要做cookie鉴权

import re
import pytest
import requests

class TestSendRequest:
    cks=""
    
    #需要带请求头的接口以及需要cookie关 联的接口如何测试?
    def test_start(self):
        url = "http://47.107.116.139/phpwind/"
        rep=requests.get(url=url)
        print (rep.text)
        #通过正则表达式获取鉴权码
        TestSendRequest.csrf_token= re.search( 'name="csrf_token" value="(.*?)"', rep.text)[1]
        print(TestSendRequest.csrf_token)
        TestSendRequest.cks=rep.cookies

    #请求需要带请求头的接口
    def test_login(self) :
        url = "http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
        data = {
            "username" : "msxy",
            "password" :"msxy",
            "csrf_token": TestSendRequest.csrf_token,
            "backurl": "http://47. 107.116.139/ phpwind/",
            "invite": ""
        }
        headers = {
            "Accept": "application/json,text/ javascript, / ; q=0.01",
            "X一Requested-With" : "XMLHttpRequest"
        }
        rep = requests. post (url=url, data=data , headers=headers,cookies=TestSendRequest.cks )
        print (rep.json() )


if __name__ == '__main__':
    #-vs 打印调试信息
    pytest.main(['-vs'])

2、通过session实现cookie鉴权(常用)

import re
import pytest
import requests

class TestSendRequest:
	csrf_token=""
    session = requests.session()
    
    #需要带请求头的接口以及需要cookie关 联的接口如何测试?
    def test_start(self):
        url = "http://47.107.116.139/phpwind/"
        rep=requests.get(url=url)
        print (rep.text)
        #通过正则表达式获取鉴权码
        TestSendRequest.csrf_token= re.search( 'name="csrf_token" value="(.*?)"', rep.text)[1]
        print(TestSendRequest.csrf_token

    #请求需要带请求头的接口
    def test_login(self) :
        url = "http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"
        data = {
            "username" : "msxy",
            "password" :"msxy",
            "csrf_token": TestSendRequest.csrf_token,
            "backurl": "http://47. 107.116.139/ phpwind/",
            "invite": ""
        }
        headers = {
            "Accept": "application/json,text/ javascript, / ; q=0.01",
            "X一Requested-With" : "XMLHttpRequest"
        }
        rep = TestSendRequest.session.post (url=url, data=data , headers=headers)
        print (rep.json() )


if __name__ == '__main__':
    #-vs 打印调试信息
    pytest.main(['-vs'])

接口自动化测试框架封装

第一步 统一请求方式

rep=requests.request(请求方式,地址,参数…)

def test_get_token(self):
        # 发送get请求
        url = "https://api.weixin.qq.com/cgi-bin/token"
        data = {
            "grant_type": "client_credential",
            "appid": "wx6b11b3efd1cdc290",
            "secret": "106a9c6157c4db5f602991873819529d"
        }
        rep = requests.request("get",url=url, params=data)
        print(rep.json())
        TestSendRequest.access_token = rep.json()["access_token"]

Pytest全局观

1、它可以和所有的自动化测试工具selenium、requests、appium结合实现web自动化、接口自动化以及app自动化;
2、跳过用例、失败用例重跑;
3、结合allure生成美观的测试报告;
4、和Jenkins持续集成;
5、有很多的强大插件。

1、常用操作(一)

项目的在根目录下创建requirements.txt文件
注意(#是我自己为了方便看代码的解释,复制请删除)

#pytest框架
pytest

#生产html测试报告
pytest-html

#多线程运行
pytest-xdist

#改变测试用例的执行顺序
pytest-ordering

#失败用例重跑
pytest-rerunfailures

#生产allure测试报告
allure-pytest
#在命令窗口使用 安装这个文件里面的插件
pip install -r requirements.txt	 

2、常用操作(二)运行方式

在根目录下创建python.ini文件

#提示这是pytest文件
[pytest]
#执行方法,-m "smoke" 只执行冒烟用例,要想执行其他用例  删除-m以及后面的
addopts = -vs -m "smoke"
#文件路径
testpaths = ./ui
#文件以test_开头
python_files = test_*.py
#类名以Test开头
python_classes = Test*
#用例以test_开头
python_functions = test_*

#对用例进行分组 在用例上@pytest.mark.smoke,就执行加了这样的用例
markers =
    smoke:maoyan

若没有建立python.ini文件
在主程序中输出结果如下表达:

if __name__ == '__main__':
    '''
    v   输出更加详细的运行信息
    -s  输出调试信息
    -n  多线程运行
    --reruns数字  失败用例重跑
    --html='报告的路径'
    '''

    #写了pytest.ini
    pytest.main()

    # pytest.main(['-vs','-n=2'])
    # pytest.main(['-vs','--reruns=2'])
    # pytest.main(['-vs','--html=./report.html'])
    

3、常用操作(三)前置后置

setUp()/tearDown() 在每个用例之前/之后执行一次
setUp_class()/tearDown_class() 在每个之前/之后执行一次

实现部分的前置

部分前置:
@pytest.fixture(scope=“作用域”,params=“数据驱动”,autouse=“自动执行”,ids=“自定义参数名”,name=“重命名”)
作用域: function(默认)、classmodulepackage/session

import requests
import re
import pytest

#部分前置
@pytest.fixture(scope="function")
def conn_database():
    print("连接数据库")
    
	#可以通过yield唤醒teardown的功能,就是返回,yield和return都有返回数据的意思
	#但是yield返回多次及多个数据,return只返回一次且return后面的代码不执行
    yield
    print("关闭数据库")```

class Test:
    def test_edit_flag(self,conn_database):
        url=''
        data={"tag":{"id":134,"name":"小李"}}
        rep=Test.session.request('post',url,json=data

一般情况下:
@pytest.fixture()conftest.py文件一起使用
conftest.py文件
1.conftest.py:文件是单独存放**@pytest.fixture()**的方法,可以实现多个py文件共享前置配置
2.conftest.py:不需要导入直接使用,可以直接使用
3.conftest.py:可以有多个,也可以有多个不同层级

import pytest
@pytest.fixture(scope="function")
def conn_database():
    print("连接数据库")
    yield
    print("关闭数据库")

4、接口自动化测试框架封装(接口关联封装)

1、创建 common 文件夹,创建 yaml_util.py 文件

import os
import yaml
class YamlUtil:
    #读取extract.yml文件
    def read_extract_yaml(self,key):
        with open(os.getcwd()+"./extract.yml",mode="r",encoding="utf-8") as f:
            value=yaml.load(stream=f,Loader=yaml.FullLoader)
            return value[key]

    #写入extract.yml文件
    def read_extract_yaml(self,data):
        with open(os.getcwd()+"./extract.yml",mode="w",encoding="utf-8") as f:
            yaml.dump(data=data,stream=f,allow_unicode=True)

    #清除extract.yml文件
    def clearn_extract_yaml(self):
        with open(os.getcwd()+"./extract.yml",mode="w",encoding="utf-8") as f:
            f.truncate()

2、创建extract.yml文件
3、创建conftest.py文件

import pytest
from common.yaml_util import YamlUtil

#autouse  自动执行,无需调用
#scope 作用域(session)
@pytest.fixture(scope="session",autouse=True)
def clearn_Yaml():
    YamlUtil().clearn_extract_yaml()

5、pytest断言

# result ==>{"errcode": 0,"message":"数据返回成功"}
result = rep.json()
# 第一种
assert result['errcode'] == 0
#第二种
assert 'errcode' in rep.json()
#比较多个或者用and
assert 'errcode' in rep.json()
assert 'message' in rep.json()
assert 'errcode' in rep.json() and 1==1

6、allure-pytest生成allure测试报告

6.1、官网下载allure:

https://github.com/allure-framework/allure2/releases
下载 .zip 的包,放到没有中文的路径下,然后把E:\allure-2.13.7\bin配置到环境变量的path里面哦

6.2、重启pycharm 通过:allure –version验证(若没有打开pycharm,则跳过)

6.3、执行命令

(1)在temp目录下生成临时的json文件的报告,在pytest.ini文件下写 – -alluredir ./temp
在当前目录下创建temp目录

[pytest]
#执行方法
addopts = -vs --alluredir ./temp
#文件路径
testpaths = ./ui
#文件以test_开头
python_files = test_*.py
#类名以Test开头
python_classes = Test*
#用例以test_开头
python_functions = test_*

(2)通过临时的json文件生成allure报告(在reports目录下),在all.py文件写
os.system(“allure generate temp -o reports –clean”)
在当前目录下创建 reports目录

import pytest

if __name__ == '__main__':
    pytest.main()
    os.system("allure generate temp -o reports --clean")

6.4、allure报告的定制

物联沃分享整理
物联沃-IOTWORD物联网 » python接口自动化测试(一)

发表评论