使用python+pytest进行接口测试方法总结

项目源码可以访问我的GitHub获取(页面右上角有地址)

思路如下

1.先使用session = requests.session(),session.post调用登录接口,return出session(保持登录状态)

# -*- coding: utf-8 -*-
# @Time    : 2019/6/5 16:34
# @Author  : wangmengmeng

import requests
import json
from config.read_config import ReadConfig
import hashlib
from common.logger import Logger

class Login():
    def __init__(self):
        self.conf = ReadConfig()
        url = self.conf.get('login', 'address') + '/syscenter/api/v1/currentUser'
        username = self.conf.get('login','username')
        passwd = self.conf.get('login','password')
        m = hashlib.md5() # 创建md5对象
        m.update(passwd.encode()) #  生成加密字符串
        password = m.hexdigest()
        params = {"name": username, "password": password}
        headers = {'Content-Type': "application/json"}
        self.session = requests.session()
        # res = self.session.post(url, data=json.dumps(params), headers=headers)
        res = self.session.post(url, data=json.dumps(params), headers=headers)
        print(res.json())
        start_sf_url = self.conf.get('login', 'address') + '/auditcenter/api/v1/startAuditWork'  # 获取开始审方url
        res2 = self.session.get(url=start_sf_url)  # 开始审方
        print(res2.json())

    def get_session(self):
        return self.session


if __name__ == '__main__':
    a = Login()
    # res = a.get_session()
    # print(res)
实例代码

2.使用1中的session去封装http请求(如get、put、post等),封装http请求时注意需要将请求return出来,否则后续获取不到接口请求结果从而无法断言

# @Time : 2019/8/6 13:59
# @Author : wangmengmeng
import requests
import json
from common.login import Login
from common.logger import log
from requests import session


class HttpRequest:
    def __init__(self):
        login = Login()
        self.s = login.get_session()

    @staticmethod
    def post_xml(url, param):
        """
        不需要登录的post请求,且请求体为xml格式
        :param url:
        :param param:
        :return:
        """
        headers = {"Content-Type": "text/plain"}
        res = requests.post(url, data=param.encode("utf-8"), headers=headers)
        return res

    def post_json(self, url, param):
        data = param
        data = json.dumps(data)
        headers = {"Content-Type": "application/json"}
        res = self.s.post(url, data=data.encode("utf-8"), headers=headers).json()
        return res

    def get(self, url):
        return self.s.get(url).json()

    def put(self, url, param):
        data = param
        data = json.dumps(data)
        headers = {"Content-Type": "application/json"}
        return self.s.put(url, data, headers=headers)

    def req(self, url, method, data=None, params=None, headers=None):
        """封装post和get请求"""
        if method == 'post':
            return self.s.post(url=url, data=data, headers=headers)

        elif method == 'get':
            return self.s.get(url=url, params=params, headers=headers)

        else:
            return self.s.put(url=url, data=data, headers=headers)
示例代码

3.封装各业务请求接口,如入参中需要设置变量的,可以设置为变量。好处:方便测试用例中进行多接口场景测试;方便测试用例中数据驱动;

# -*- coding: utf-8 -*-
# @Time : 2019/8/6 16:28
# @Author : wangmengmeng
from common.request import HttpRequest
from config.read_config import ReadConfig
from common.send_data import SendData
from common.connect_db import ConnectDB
import time


def wait(func):
    # func(*args, **kw)可以使函数适配任意多的参数
    def wrapper(*args, **kw):
        time.sleep(3)
        return func(*args, **kw)

    return wrapper


class Ipt:
    def __init__(self):
        self.send = SendData()
        self.conf = ReadConfig()
        self.request = HttpRequest()
        self.db = ConnectDB()
        self.conn = self.db.connect(self.db.db_sys)
        self.cur = self.db.get_cur(self.conn)
        sql = self.conf.get('sql', 'zoneid')
        self.zoneid = (self.db.execute(self.cur, sql))[0]

    @wait
    def selNotAuditIptList(self):
        """
        待审住院列表根据患者号查询
        :return:   通过return结果可以获得以下数据:engineid res['data']['engineInfos'][0]['id']
        """
        # self.send.send('ipt', '医嘱一', 1)
        # time.sleep(3)
        url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/selNotAuditIptList'
        param = {
            "patientId": self.send.change_data['{{ts}}']
        }
        res = self.request.post_json(url, param)
        return res

    @wait
    def waitIptList(self):
        """
        待审住院列表根据患者号查询 作用同函数selNotAuditIptList(),是其优化版本
        :return:   通过return结果可以获得以下等数据:engineid res['data']['engineInfos'][0]['id']
        """
        # self.send.send('ipt', '医嘱一', 1)
        # time.sleep(3)
        url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/selNotAuditIptList'
        param = {
            "patientId": self.send.change_data['{{ts}}']
        }
        res = self.request.post_json(url, param)
        engineInfos = res['data']['engineInfos']  # 待审列表的医嘱数据
        engineMsg = []
        engineids = []
        if engineInfos is not None: # 待审列表有数据的时候执行下述语句
            engineMsg = res['data']['engineInfos'][0]['engineMsg']  # 医嘱对应的警示信息
            engineids = [i['id'] for i in res['data']['engineInfos']]  # 同一患者的所有引擎id
        return engineInfos, engineMsg, engineids

    def get_engineid(self, n):
        """
        待审列表获取引擎id
        :param n: 如果某患者有多条待审任务则会有多个引擎id,n代表取第几个引擎id
        :return:
        """
        res = self.selNotAuditIptList()
        return res['data']['engineInfos'][n - 1]['id']

    def audit_multi(self, *ids):
        """
        待审住院任务列表批量通过
        :param ids:  引擎id
        """
        url = self.conf.get('auditcenter', 'address') + '/api/v1/auditBatchAgree'
        param = {
            "ids": ids,
            "auditType": 3,  # 3指住院
            "auditWay": 2
        }
        self.request.post_json(url, param)

    def ipt_audit(self, gp, engineid, audit_type):
        """
        医嘱详情审核任务
        :param gp:
        :param engineid:
        :param audit_type: 0 审核打回  1 审核打回(可双签) 2 审核通过
        orderType : 1:药物医嘱; 2:非药物医嘱;3:草药医嘱
        """
        url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/auditSingle'
        param = ''
        if audit_type == 0:
            param = {
                "groupOrderList": [{
                    "auditBoList": [],
                    "groupNo": gp,
                    "auditInfo": "必须修改",
                    "auditStatus": 0,
                    "engineId": engineid,
                    "orderType": 1
                }]
            }
        elif audit_type == 1:
            param = {
                "groupOrderList": [{
                    "auditBoList": [],
                    "groupNo": gp,
                    "auditInfo": "打回可双签",
                    "auditStatus": 0,
                    "engineId": engineid,
                    "orderType": 1,
                    "messageStatus": 1
                }]
            }
        elif audit_type == 2:
            param = {
                "groupOrderList": [{
                    "auditBoList": [],
                    "groupNo": gp,
                    "auditInfo": "审核通过",
                    "auditStatus": 1,
                    "engineId": engineid,
                    "orderType": 1
                }]
            }
        self.request.post_json(url, param)

    def orderList(self, engineid, type):
        """
        获取药嘱信息
        :param engineid:
        :param type: 0 待审页面 1 已审页面
        :return:
        """
        if type == 0:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/orderList' + '?id=' + str(engineid)
        else:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/all/orderList' + '?id=' + str(engineid)
        return self.request.get(url)

    def herbOrderList(self, engineid, type):
        if type == 0:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/herbOrderList' + '?id=' + str(engineid)
        else:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/all/herbOrderList' + '?id=' + str(engineid)
        return self.request.get(url)

    def mergeEngineMsgList(self, engineid, type, gno):
        """获取医嘱详情右侧的审核记录、警示信息等信息"""
        ol = self.orderList(engineid, type)
        medicalIds = [i['id'] for i in ol['data'][gno]]
        medicalHisIds = [i['orderId'] for i in ol['data'][gno]]
        if type == 0:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/mergeEngineMsgList'
            param = {
                "auditWay": 2,
                "engineId": engineid,
                "zoneId": self.zoneid,
                "groupNo": gno,
                "medicalIds": medicalIds,
                "medicalHisIds": medicalHisIds,
                "herbMedicalIds": [],
                "herbMedicalHisIds": []
            }
        else:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/all/mergeEngineMsgList'
            param = {
                "engineId": engineid,
                "zoneId": self.zoneid,
                "groupNo": gno,
                "medicalIds": medicalIds,
                "medicalHisIds": medicalHisIds,
                "herbMedicalIds": [],
                "herbMedicalHisIds": []
            }
        return self.request.post_json(url, param)

    def get_patient(self, engineid, type):
        """获取住院患者信息"""
        if type == 0:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/iptPatient' + '?id=' + str(engineid)
        else:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/all/iptPatient' + '?id=' + str(engineid)
        return self.request.get(url)

    def get_operation(self, engineid, type):
        """获取住院手术信息"""
        if type == 0:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/operationList' + '?id=' + str(engineid)
        else:
            url = self.conf.get('auditcenter', 'address') + '/api/v1/ipt/all/operationList' + '?id=' + str(engineid)
        return self.request.get(url)


if __name__ == '__main__':
    ipt = Ipt()
    ipt.send.send('ipt', '医嘱一', 1)
    ipt.send.send('ipt', '医嘱二', 1)
    res = ipt.get_engineid(1)
    print(res)
    res = ipt.get_engineid(2)
    print(res)
示例代码

4.编写测试用例

数据驱动格式为:

    import pytest
  
@pytest.mark.parametrize("is_use,value,expected", [(0, 0, None), (0, 1, None), (1, 0, None), (1, 1, None)]) def test_implant_null(self, zy, implant_config, is_use, value, expected): implant_config.alter_default_setting(89, 'whether_Implanta', '是否有植入物', is_use, value) zy.send.send('ipt', 'audit512_1', 1) time.sleep(1) engineid = zy.get_engineid(1) actual = (zy.get_operation(engineid, 0))['data'][0]['isImplant'] assert actual == expected

5.post与get请求

post请求的参数有两种body(对应requests的data参数)和params(对应requests的params参数,一般就是拼接在url中)

get请求要么有参数,要么是params(对应requests的params参数,一般就是拼接在url中)

对于requests的post请求参数有data,json,这两种的区别是如果不指定headers,json默认headers是application/json,data默认是表单提交headers是application/x-www-form-urlencoded

 

原文地址:https://www.cnblogs.com/wang-mengmeng/p/11774673.html