python接口自动化测试

python接口测试中阶篇(史无前例)

2019-07-18  本文已影响27人  6780441d2bcc
接口自动化中级篇

咱们书接上本:

接口测试基础篇(史上最详细):https://www.jianshu.com/p/eac7a9d2327f

设计思路
  1. 将测试用例封装成json格式,里面包含接口的各种信息

  2. 封装requests,能请求post get等类型的请求

  3. 执行用例,执行前,判断前置条件

  4. 判断用例是否跳过,然后在基础上增加allure测试报告


功能总结如下
  1. 微型框架能适应简单的各种接口请求 post get等等

  2. 断言只需要写一次,不需要重复的代码

  3. 抛开unittest和pytest等框架的约束,本次不使用这些框架!

  4. 执行测试用例的代码 封装成通用的,维护只需要维护json数据就可以了

  5. 设计思路简单而简约,先搭建简单的框架在搭建稍微复杂的

  6. 本次测试报告采用allure,自定义allure测试报告

  7. 可以适应大批量接口请求,维护简单

  8. 有断言,前置条件等功能


咱们的目的就是从0到1,到最后的接口自动化框架搭建,我会用自己最大的能力往框架里面带入,从简单略有难度,由浅到深的一个过程, 希望这个过程,大家能积极交流 互相学习 一起进步

allure官方文档:https://docs.qameta.io/allure

希望你能有看官方文档的习惯,因为再多的文章都不如官方文档详细,强烈建议哦!!!

请用你勤劳的双手,跟着敲一遍,不敲是学不会的哦~


第一步: 用例封装成json格式

项目下增加config.py

# 测试环境
base_url = 'http://suggest.taobao.com/'

# 假装是正式环境
# base_url = 'http://suggest.taobao.com/'

"""
title:用例的名称
condition:前置条件,写skip跳过这条用例
url:接口的链接
params:参数 如果是headers 就增加一个headers
type:请求类型 get post put 等等
isok:用例是否通过
time:这条用例是否需要等待
"""
# list里面嵌套 字典,通过循环读取获取里面的字典类型用例
httpurl_data = [
    # 1.注册接口 第一条用例
    {'title': '注册接口',  # 用例的名称
     'condition': '',  # 前置条件 写skip 跳过这个用例
     'url': '{}sug'.format(base_url),
     'params': {
         'code': 'utf-8',  # 接口需要传入编码格式
         'q': '裤子',  # 搜索条件 如 裤子等信息
         'callback': 'cb 用例'
     },
     'type': 'get',  # 请求的类型 get 就写get  post就写post
     'isok': '',  # 用例是否通过,通过是ok 不通过是 failure
     'time': '1'  # 用例等待的时间 秒 1就是等待1秒后执行
     },
    # 2.登录接口 第二条用例
    {'title': '登录接口',  # 用例的名称
     'condition': '',  # 前置条件 写skip 跳过这个用例
     'url': '{}sug'.format(base_url),
     'params': {
         'code': 'utf-8',  # 接口需要传入编码格式
         'q': '裤子',  # 搜索条件 如 裤子等信息
         'callback': 'cb 用例'
     },
     'type': 'get',  # 请求的类型 get 就写get  post就写post
     'isok': '',  # 用例是否通过,通过是ok 不通过是 failure
     'time': ''  # 用例等待的时间 秒 1就是等待1秒后执行
     }
]


总结: 这样写的好处就是,直接可以通过循环来执行每一条用例,并在执行过程中记录用例


第二步: 封装requests 先封装post和get类型的请求

项目下增加poshttp.py

import requests
import time


# 简单封装get请求  data={'title': '注册接口', 'condition': '', 'url': 'http://suggest.taobao.com/sug', 'params': {'code': 'utf-8', 'q': '裤子', 'callback': 'cb 用例'}, 'type': 'get', 'isok': '', 'time': '1'}
def get(data={}):

    # 发送请求
    r = requests.get(data['url'], data['params'])
    # 简单的判断接口的code码 等于200就让它通过
    if r.status_code == 200:
        # 改变字典里面的值
        data['isok'] = 'ok'
    # 打印请求的结果
    print(r.text)
    # 返回字典用于记录测试报告
    return data


def post(data={}):


    # 发送post请求
    r = requests.post(data['url'], data['params'])
    # 简单的判断接口的code码 等于200就让它通过
    if r.status_code == 200:
        # 改变字典里面的值
        data['isok'] = 'ok'
    # 打印请求的返回结果
    print(r.text)
    # 返回字典用于记录测试报告
    return data

总结:简单的封装了requests 请求完成后打印结果信息


第三步:执行用例,执行前,判断用例是否等待

项目下增加start.py

# 引入config里面的用例
from config import httpurl_data
# 引入请求
import poshttp
# time在这里的作用主要是等待的操作
import time

# 开始执行测试,并记录结果数据
result = []
# 开始执行用例
for data in httpurl_data:
    # 获取等待时间 没有的话就是0
    sltime = data.get('time', 0)
    # 判断时间有值在进行等待
    if sltime:
        # 使用sleep进行等待
        time.sleep(float(sltime))

    # 使用getattr函数进行反射调用接口 参数1:请求的对象,参数2:请求类型 get post 后面的小括号是进行传参
    case = getattr(poshttp, data['type'])(data)
    # 测试结果数据添加到list中
    result.append(case)

print('打印结果数据')
for r in result:
    print(r)

总结:这样写 可以执行大批量的接口请求,不用每一个用例就写一个test函数等信息,遵守一些规则,这里可以根据自己的想法去做一些事情

运行start.py 来看看结果:


image

前三步咱们已经简单的做完了,接下来进行第四步

第四步:判断用例是否需要跳过,然后在基础上增加allure测试报告

allure如何安装的这里不再叙述,网上有很多教程,咱们直接开始

junit 主要用于生产自定义的allure测试报告,这里需要引入from xml.dom.minidom import Document 主要用于生成xml数据源,提供给allure展示测试报告

增加junit.py

import timeit
from xml.dom.minidom import Document
from pathlib import Path
import time
from datetime import datetime


class Junit:
    def __init__(self, pstarttime):
        # 创建DOM文档对象
        self.doc = Document()
        self.pstarttime = pstarttime
        # 创建用例套件集
        self.testsuites = self.doc.createElement('testsuites')
        self.doc.appendChild(self.testsuites)
        # 当前时间
        self.nowtime = time.strftime("%Y%m%d_%H%M%S", time.localtime())
        # 创建用例套件
        self.testsuite = self.doc.createElement('testsuite')

    # 测试用例套件
    def suite(self, tests):
        # 项目的名称
        self.testsuite.setAttribute('hostname', 'exhibit')
        # 用例数量
        self.testsuite.setAttribute('tests', str(tests))
        # 项目类型
        self.testsuite.setAttribute('name', 'API')
        # 时间
        self.testsuite.setAttribute('timestamp', str(datetime.isoformat(self.pstarttime)))

    # 每条用例是一个case
    def case(self, title, time):
        # 创建case标签
        self.testcase = self.doc.createElement('testcase')
        # 用例的名称
        self.testcase.setAttribute('name', str(title))
        self.case_timer = time
    # 跳过用例的case
    def skip_case(self, message):
        skip = self.doc.createElement('skipped')
        skip.setAttribute('message', message)
        self.testcase.appendChild(skip)
    # 设置时间
    def settime(self):
        endtime = datetime.now()
        # 单个用例的执行时间
        td = endtime - self.case_timer
        time = float(
            (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6)) / 10 ** 6
        self.testcase.setAttribute('time', str(time))
        self.testcase.setAttribute('priority', 'M')
        self.testsuite.appendChild(self.testcase)

    # 失败的用例
    def failure(self, message):
        # 创建失败用例的标签
        failure = self.doc.createElement('failure')
        # 为什么失败了这个用例
        failure.setAttribute('message', str(message))
        # 类型为失败
        failure.setAttribute('type', 'Failure')
        # 添加到testcase下
        self.testcase.appendChild(failure)

    # 生成xml  是allure的数据源
    def write_toxml(self):
        # 计算执行的时间, 用当前时间-开始时间 是总耗时
        td = datetime.now() - self.pstarttime
        td_time = float(
            (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6)) / 10 ** 6
        self.testsuite.setAttribute('time', '%s' % td_time)
        self.testsuites.appendChild(self.testsuite)
        file = Path('junit') / ('API' + '-' + 'ReportJunit@' + self.nowtime + '.xml')
        f = open(file, 'w')
        self.doc.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='gbk')
        f.close()

接下来修改start.py 增加了跳过用例,和生成xml测试报告的代码,代码不是很多,注释很详细,贴代码大家来看看吧~

# 引入config里面的用例
from config import httpurl_data
# 引入请求
import poshttp
# time在这里的作用主要是等待的操作
import time
from datetime import datetime
# 引入junt
from junit import Junit
from pathlib import Path

files = ('junit',)
# 创建文件夹
for k in files:
    path = Path(k)
    # 如果文件不存在 则创建
    if not path.is_dir():
        path.mkdir()

# 获取程序执行的时间
start_time = time.strftime("%Y%m%d_%H%M%S", time.localtime())

# 获得junit实例
junit = Junit(datetime.now())

# 开始执行测试,并记录结果数据
result = []

# 开始执行用例
for data in httpurl_data:
    # 判断需要跳过的用例
    if data['condition'] == 'skip':
        # 写入跳过用例标题名
        junit.case(data['title'], datetime.now())
        # 跳过用例的信息
        junit.skip_case('This use case is skipped')
        junit.settime()
        # 跳过的用例也添加到结果里面
        result.append(data)
        # continue 跳出本次循环不会结束循环
        continue

    # 这条用例开始执行的时间
    case_time = datetime.now()

    # 首先判断此用例是否需要执行

    # 获取等待时间 没有的话就是0
    sltime = data.get('time', 0)
    # 判断时间有值在进行等待
    if sltime:
        # 使用sleep进行等待
        time.sleep(float(sltime))

    # 使用getattr函数进行反射调用接口 参数1:请求的对象,参数2:请求类型 get post 后面的小括号是进行传参
    case = getattr(poshttp, data['type'])(data)
    # 看结果里 接口是否为通过
    is_pass = case.get('isok', '')
    # 用例通过
    if is_pass == 'ok':
        # 写入xml测试报告
        junit.case(case['title'], case_time)
        junit.settime()
    # 用例不通过
    else:
        junit.case(case['title'], case_time)
        junit.failure('标题:' + case['title'] + '请求类型' + case['type'])
        junit.settime()

    # 测试结果数据添加到list中
    result.append(case)
# 生成xml数据源 提供给allure
# 生成测试套件 参数为用例的总数
junit.suite(len(httpurl_data))
junit.settime()
# 生成xml
junit.write_toxml()

执行完毕,在项目里面生产了junit文件夹,里面有xml测试报告 那么如何如何生成allure测试报告呢?,如果你配置好了,在当前项目的路径下执行:allure serve junit 就会生成allure测试报告了,在你已经配置好allure的情况下

进行如下操作:

image
输入:allure serve junit
image
会自动打开浏览器,展示allure测试报告 截图如下:
image
image
image

allure 已经增加完了,接下来增加接口的断言功能

在config.py下面增加assert字段

image

然后修改下poshttp.py就可以了,在里面增加一个断言的代码

poshttp.py修改完之后的如下

import requests
import time


# 简单封装get请求  data={'title': '注册接口', 'condition': '', 'url': 'http://suggest.taobao.com/sug', 'params': {'code': 'utf-8', 'q': '裤子', 'callback': 'cb 用例'}, 'type': 'get', 'isok': '', 'time': '1'}
def get(data={}):
    # 发送请求
    r = requests.get(data['url'], data['params'])
    # 简单的判断接口的code码 等于200就让它通过
    if r.status_code == 200:
        # 改变字典里面的值
        data['isok'] = 'ok'

    # 取出来需要断言 数据 取出来是个元祖类型,需要挨个去返回结果里面对比
    content = data.get('assert', '')

    for ct in content:
        # 每个字段和去街口的返回值去对比
        if ct in str(r.text):
            pass
        else:
            data['isok'] = 'failure'
            print(ct + '这个没有通过')

    # 打印请求的结果
    print(r.text)
    # 返回字典用于记录测试报告
    return data


def post(data={}):
    # 发送post请求
    r = requests.post(data['url'], data['params'])

    # 打印请求的结果
    print(r.text)
    # 简单的判断接口的code码 等于200就让它通过
    if r.status_code == 200:
        # 改变字典里面的值
        data['isok'] = 'ok'
        # 取出来需要断言 数据 取出来是个元祖类型,需要挨个去返回结果里面对比
        content = data.get('assert', '')
        for ct in content:
            # 每个字段和去街口的返回值去对比
            if ct in str(r.text):
                pass
            else:
                data['isok'] = 'failure'
                print(ct + '这个没有通过')

    # 打印请求的返回结果
    print(r.text)
    # 返回字典用于记录测试报告
    return data

总结:主要增加了 这几行代码 ,将返回的信息强转为str类型,然后用in 来判断返回的接口里面,有没有咱们想要的内容
content = data.get('assert', '')
for ct in content:
# 每个字段和去街口的返回值去对比
if ct in str(r.text):
pass
else:
data['isok'] = 'failure'
print(ct + '这个没有通过')
到这里一个微小型框架就已经差不多成型啦,能支持简单的请求了,有问题欢迎交流沟通

image

qq群:234922431 欢迎来交流互相学习

上一篇下一篇

猜你喜欢

热点阅读