使用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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM