zoukankan      html  css  js  c++  java
  • 使用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

     

  • 相关阅读:
    详解 final 和 static
    详解 方法的覆盖 —— toString() 与 equals()的覆盖
    详解 继承(上)—— 工具的抽象与分层
    详解 继承(下)—— super关键字 与 多态
    Java 基础讲解
    矩阵 的实现
    C语言 贪吃蛇
    巨大数——三则运算(+、-、*)
    浅谈 循环数组
    人体对电流的反应
  • 原文地址:https://www.cnblogs.com/wang-mengmeng/p/11774673.html
Copyright © 2011-2022 走看看