关于接口功能自动化的思考

一、背景

目前接触的业务涉及web、APP(Android&IOS)以及H5小程序等多终端,但只要业务仍是TO G端的业务,涉及的只要是web端操作测试。上次进行UI自动化回归测试,如果涉及到页面改动比较频繁,页面中某些关键字会经常变更,导致元素定位每个版本都需要复查并修正关键字的定位,这样会消耗大量的人力物力,但往往事倍功半。

二、方案对比

2.1 Postman

对于真正的接口自动化测试而言,需要少量的代码即可完成接口自动化。相对而言,postman语言结构统一、易掌握,可以快速上手投入实战。

但针对我们的业务情况,对于TO G系统,这里没有做到前后端分离,故不是纯正的后端接口,有大量的jsp页面杂糅在一起,这种情况下多方考虑使用APP端的接口方案替换;还有一个问题是业务有很多关联业务和步骤,比如一个业务步骤涉及A、B、C其中A步骤中涉及A1接口、A2接口、A3接口;B、C同理。

目前在postman中暂时未找到比较好的解决方案,而JMeter也面临同样的问题。

所以,使用postman处理了部分自动化,后来实在是太折腾了,放弃了此方案。


2.2 RobotFrameWork

RobotFrameWork应用更广泛,使用于web、app、以及接口,此前关于UI自动化曾使用RobotFrameWork完成自动化回归工作,但是问题时跑完整个模块需要消耗大量的时间,而且脚本变动也比较频繁。


2.3 Seldom

此前曾使用此python二次封装的框架完成UI自动化工作,对于此框架比较熟悉,多方验证使用seldom同样可以完成接口自动化。还有一个优点在于提高了自动化的效率,UI自动化跑完一个模块(300个左右用例)大概需要1天甚至更久,而使用接口自动化则只需要2个小时左右,下图截图所示

image-20211029162147738

三、具体示例

处理的业务流程:

graph TD; 1.登录系统-->2.提交申请单; 2.提交申请单-->3.退出申请账号; 3.退出申请账号-->4.审批账号退出; 4.审批账号退出-->5.进入对应模块并查询对应待审批单据并审批通过;

3.1 登录代码如下

# -*- coding:utf-8 -*-
import seldom


class LoginTest(seldom.TestCase):
    
    """登录APP操作"""

    def start(self):
        pass

        

    def test_login(self):
        
	    # 登录请求接口url
        self.login_event = "/login"
        # 登录请求参数
        payload ={

            'mobileLogin':'1',
            'username':'6bcce5f671fd3f27672c13feef54c8f550aeab495e1d04fba86120d2e99c1beed54258a70145d0371c3a738bb2dd1d9232fed6235f9f2e8f2722c974caf42fe4777c4d51237e3274473d5188367058931eafae68e5b9d70c74824d864467117dfb03b9b818d4646772adec9eadbf7044b43e329e44d38dff4e15459198237ecc',
            'password':'7b54901eaa0e6b69ff603cb02a1aef7749567eeb5a61e5038e86eabccb7ba45d34e742572d70bb80ed8bb7e19f32fa9b9d93874b5419cb4512fe119c50878e4f126e53f67434c8a0441a57a65b6ea7df01e40352dfb95bc4e319f516ab42f662b569896f3d48e030793c65d31b4824cb55d8eb8fafd1c0092f8d1b47b0f125b2',
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807',
            'identifierId':'09eff7963d5c88c2',
            'validateCode':'',
            'loginType':'1'
        }
        """Cookie: accountSuitId=fa80c8f8b9ee43a79fdfa5ddf8d29807""" 

        headers = {
        # 从浏览器中复制过来的User-Agent
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
        # 从浏览器中复制过来的Cookie
        'Cookie': 'accountSuitId=fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }
        
        # 登录请求接口
        r_login = self.post(self.login_event,headers=headers,data=payload)
        self.assertStatusCode(200)
        login_response = self.response
        print(type(login_response))
        # 登录请求返回值
        login_token = self.response['rcm.session.id']
        print(login_token)

        return login_token


    def logout(self):
        """退出登录接口信息"""

        self.logout_url = '/logout'
        payload ={}
        # 退出接口信息
        r_userinfo = self.get(self.logout_url,data=payload)
        self.assertStatusCode(200)


if __name__ == '__main__':
    seldom.main()

3.2 个人信息接口代码

# -*- coding:utf-8 -*-
import seldom
from test_login import LoginTest


class UserInfoTest(seldom.TestCase):

    """"获取个人登录信息"""

    def setup(self):
        pass

        





    def test_user(self):
        """个人信息如下"""
        self.user_url = '/app/user/infoData'
        sign_login = LoginTest()
        user_token = sign_login.test_login()
        print(user_token)

        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':user_token,
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }


        # 个人信息接口
        r_userinfo = self.get(self.user_url,cookies=Cookies)
        self.assertStatusCode(200)
        user_response = self.response
        print(type(user_response))

        # 获取个人信息接口返回信息
        login_id = user_response['id']
        loginName = user_response['name']
        mobile = user_response['mobile']
        admin = user_response['admin']
        roleNames = user_response['roleNames']
        accountSuitAdmin = user_response['accountSuitAdmin']
        loginFlag = user_response['loginFlag']
        jobGrade = user_response['jobGrade']
        appLoginFlag = user_response['appLoginFlag']
        officeId = user_response['officeId']
        officeName = user_response['officeName']

        print("login_id:"+login_id)
        print("loginName:"+loginName)
        print("mobile:"+mobile)
        print("admin:"+str(admin))
        print("roleNames:"+roleNames)
        print("accountSuitAdmin:"+str(accountSuitAdmin))
        print("loginFlag:"+loginFlag)
        print("jobGrade:"+jobGrade)
        print("appLoginFlag:"+appLoginFlag)
        print("officeId:"+officeId)
        print("officeName:"+officeName)

        return login_id,loginName,mobile,admin,roleNames,accountSuitAdmin,loginFlag,jobGrade,appLoginFlag,officeId,officeName


      



if __name__ == '__main__':
    seldom.main()

3.3 完整申请单流程代码

展示了具体的申请-->提交审批--->审批人登录系统并审批整个操作流程,代码如下:
# -*- coding:utf-8 -*-
import seldom
import json
import time
from datetime import date
import random
import string
from faker import Faker
from test_userinfo import UserInfoTest
from test_login import LoginTest
from test_approval_login import LoginApprovalTest
from test_common_before import SelectApplyCommon



class BeforeApplyTest(seldom.TestCase):

    """"事前申请相关接口测试操作"""


    def setup(self):
        
        sign_login = LoginTest()
        user_token = sign_login.test_login()
        print(user_token)
        return user_token



    def test_before_apply_submit(self):
        """事前申请提交相关信息"""

        # 登录,获取个人信息
        user_info = UserInfoTest()
        user_info_data = user_info.test_user()
        user_info_data = list(user_info_data)
        print(user_info_data)

        login_id = user_info_data[0]
        login_name = user_info_data[1]
        mobile = user_info_data[2]
        admin = user_info_data[3]
        roleNames = user_info_data[4]
        accountSuitAdmin = user_info_data[5]
        loginFlag = user_info_data[6]
        jobGrade = user_info_data[7]
        appLoginFlag = user_info_data[8]    
        officeId = user_info_data[9]
        officeName = user_info_data[10]

        print(login_id)

        
        """第一步:获取预算指标信息,这里获取第一个指标"""
        self.before_budget_url = '/budget/budget/selector/listData?state=1'


        payload={
            'type': '',
            'controlType':'',
            'freezeFlag':'',
            'forwardFlag':'',
            'tempFlag':'',
            'delFlag':'0',
            'source':'10',
            'payProjectId':'',
            'applyUserId':login_id,
            'applyType':'101',
            'hasBudgetFlag':'1',
            'extIds':'',
            'forAdjust':'',
            'year':'2021',
            'name':'测试20210309001',
            'projectName':'',
            'budgetProject.id':'',
            'pageNo':'',
            'pageSize':'',
            'orderBy':''
        }

        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':self.setup(),
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }


        # 获取预算相关信息接口
        r_userinfo = self.post(self.before_budget_url,cookies=Cookies,data=payload)
        self.assertStatusCode(200)
        user_response = self.response
        print(type(user_response))

       

        """#第一步:获取预算指标信息,获取预算信息相关返回值信息"""

        indicators_project_id = user_response['list'][0]['id']
        indicators_budgetProject_id = user_response['list'][1]['id']
        indicators_name = user_response['list'][1]['name']
        indicators_budgetProject_type = user_response['list'][1]['type']
        indicators_budgetProject_payProject_id = user_response['list'][1]['payProject']['id']
        indicators_budgetProject_payProject_name = user_response['list'][1]['payProject']['name']
        indicators_budgetProject_money_id = user_response['list'][1]['moneySources'][0]['id']



        """"打印list-1"""
        print(user_response['list'][1])
        print("indicators_project_id:"+indicators_project_id)
        print("indicators_budgetProject_id:"+indicators_budgetProject_id)
        print("indicators_name:"+indicators_name)
        print("indicators_budgetProject_type:"+indicators_budgetProject_type)
        print("indicators_budgetProject_payProject_id:"+indicators_budgetProject_payProject_id)
        print("indicators_budgetProject_payProject_name:"+indicators_budgetProject_payProject_name)
        print("indicators_budgetProject_money_id:"+indicators_budgetProject_money_id)


        """# 第二步:获取可用金额信息/budexec/beforeApply/getAvailableBalance"""
        self.budget_get_alia_url = '/budexec/beforeApply/getAvailableBalance'
        payload = {
            'payProjectId': indicators_budgetProject_payProject_id,
            'budgetId': indicators_budgetProject_id,
            'projectId': indicators_project_id,
            'applyOfficeId': officeId,
            'applyUserId': login_id
        }

        # 获取预算可用金额接口
        r_userinfo = self.post(self.budget_get_alia_url,cookies=Cookies,data=payload)
        self.assertStatusCode(200)
        budget_aliableMoney = self.response
        print(type(budget_aliableMoney))
        print(budget_aliableMoney)

        """# 第三步:获取预算项目支付可用金额,/budexec/beforeApply/payAvailableBalance"""
        self.budget_get_pay_url = '/budexec/beforeApply/payAvailableBalance'
        payload={
            'budgetId': indicators_budgetProject_id,
            'payProjectId': indicators_budgetProject_payProject_id,
            'projectId': indicators_project_id
            }
        # 获取预算支付可用金额接口
        r_userinfo = self.post(self.budget_get_pay_url,cookies=Cookies,data=payload)
        self.assertStatusCode(200)
        budget_PaliableMoney = self.response
        print(type(budget_PaliableMoney))
        print(budget_PaliableMoney)
        

        
        """第四步:获取指标明细信息/app/selector/beforePayProjectDetailsInfo"""
        self.budget_detail_pay_url = '/app/selector/beforePayProjectDetailsInfo'
        
        payload = {
	        "payProject": {
		    "id": indicators_budgetProject_payProject_id,
		    "name": indicators_budgetProject_payProject_name,
		    
	        },
	        
	        "availableBalance": budget_PaliableMoney,
	        
	        "applyType": "101",
	        "budget": {
		        "type": indicators_budgetProject_type,
		        "name": indicators_name,
		        "id": indicators_budgetProject_id
	        },
	        "applyUser": {
		        "name": login_name,
		        "mobile": mobile,
		        "id":login_id,
		        "admin":admin,
		        "roleNames":roleNames,
		        "accountSuitAdmin":accountSuitAdmin,
		        "loginFlag": loginFlag,
		        "appLoginFlag": appLoginFlag,
		        "jobGrade":jobGrade,
		        
	        },
	        
        }

        # 先转成Json字符串
        data = json.dumps(payload,ensure_ascii=False)

        # 按照utf-8编码成字节码 
        data = data.encode("utf-8")
        # 获取预算支出明细接口
        r_userinfo = self.post(self.budget_detail_pay_url,cookies=Cookies,data=data,headers={'Content-Type': 'application/json;charset=UTF-8'})
        
        self.assertStatusCode(200)
        indicators_project = self.response
        indicators_project_controlName = indicators_project['data']['details'][0]['controlName']
        indicators_project_payProjectDetail_name = indicators_project['data']['details'][0]['payProjectDetail']['name']
        indicators_project_payProjectDetail_id = indicators_project['data']['details'][0]['payProjectDetail']['id']
        print(type(indicators_project))
        print(indicators_project)
        print(indicators_project_controlName)
        print(indicators_project_payProjectDetail_name)
        print(indicators_project_payProjectDetail_id)



        """"第五步:上传附件/sys/sysFile/upload"""
        self.file_upload_url = '/sys/sysFile/upload'
        payload={
            'businessCategory':'01a',
            'fileConfigCode': '1',
            'id': 'WU_FILE_0',
            'name': 'vpn选择指南.pdf',
            'type': 'application/pdf',
            'lastModifiedDate': 'Sat Jul 03 2021 16:21:29 GMT+0800 (中国标准时间)',
            'size': '1546424'}
        files=[
            ('file',('05.负载均衡_linux_v1.docx',open('C:\\Users\\admin\\Postman\\files\\05.负载均衡_linux_v1.docx','rb'),'application/vnd.openxmlformats-officedocument.wordprocessingml.document'))
        ]

        # 获取上传文件接口信息
        r_userinfo = self.post(self.file_upload_url,cookies=Cookies,files=files,data=payload)
        self.assertStatusCode(200)
        indicators_project = self.response
        file_id = indicators_project[0]
        print(file_id)

        """"第六步:提交事前申请/budexec/beforeApplyCommon/submit"""
        self.budget_apply_submit_url = '/budexec/beforeApplyCommon/submit'

        # 随机日期和字符串信息
        # 格式化成2016-03-20 11:45:39形式
        today_date = date.today()
        print(today_date.strftime("%Y-%m-%d"))
        apply_date = today_date.strftime("%Y-%m-%d")
        
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        rString = salt + localTime
        # num = ''.join(random.sample(string.digits, 8))
        # reveive_code = num + localTime
        
        
        fake = Faker(locale='zh_CN')
        abroad_num = fake.random_number(digits=3, fix_len=False)
        apply_amount_temp = fake.pyfloat(left_digits=3, right_digits=2, positive=True)
        apply_amount = str(apply_amount_temp)
        exchange_rate_temp = fake.pyfloat(left_digits=1, right_digits=1, positive=True, min_value=0, max_value=1)
        exchange_rate = str(exchange_rate_temp)
        print(apply_amount)
        


        payload={
            'id': ' ',
            'applyType': ' 101',
            'applyOverFlag': ' 0',
            'courseApplyId': ' ',
            'isSubmit': ' ',
            'generalReceiptFlag': ' ',
            'affiliates[0].applyType': ' 101',
            'affiliates[0].budget.type': ' 2',
            'affiliates[0].beforeAddition.id': ' ',
            'applyDate': apply_date,
            'applyUser.id': login_id,
            'applyUser.name': login_name,
            'applyOffice.id': officeId,
            'applyOffice.name': officeName,
            'operatorUser.id': login_id,
            'operatorUser.name': login_name,
            'operatorOffice.id': officeId,
            'operatorOffice.name': officeName,
            'hasBudgetFlag': ' 1',
            'affiliates[0].budgetAvailableBalance': budget_PaliableMoney,
            'affiliates[0].budget.id': indicators_budgetProject_id,
            'affiliates[0].budget.name': indicators_name,
            'affiliates[0].applyAmount': apply_amount,
            'affiliates[0].payProjectAvailableBalance': budget_PaliableMoney,
            'affiliates[0].payProject.id': indicators_budgetProject_payProject_id,
            'synthesizeFlag': ' 0',
            'affiliates[0].payProject.name': indicators_budgetProject_payProject_name,
            'affiliates[0].availableBalance': budget_aliableMoney,
            'affiliates[0].projectAvailableBalance': budget_PaliableMoney,
            'affiliates[0].project.id': indicators_project_id,
            'affiliates[0].moneySource.id': indicators_budgetProject_money_id,
            'applyReason': rString,
            'affiliates[0].details[0].id': ' ',
            'affiliates[0].details[0].payProjectDetail.id': indicators_project_payProjectDetail_id,
            'affiliates[0].details[0].payProjectDetail.name': indicators_project_payProjectDetail_name,
            'affiliates[0].details[0].payProjectDetail.isList': ' 0',
            'affiliates[0].details[0].overFlag': ' 0',
            'affiliates[0].details[0].controlAmount': ' ',
            'affiliates[0].details[0].controlDescription': ' ',
            'affiliates[0].details[0].controlName': indicators_project_controlName,
            'affiliates[0].details[0].applyAmount': apply_amount,
            'affiliates[0].details[0].remarks': rString,
            'f4e714b005f94389a6b55f4237658b3f': ' ',
            'fileIds': file_id,
            '01a': ' f4e714b005f94389a6b55f4237658b3f',
            'file': ''}
        files=[

        ]

        # 获取提交事前申请接口信息
        r_userinfo = self.post(self.budget_apply_submit_url,cookies=Cookies,data=payload,files=files)
        self.assertStatusCode(200)
        return file_id


    # # 跳过测试类
    # @seldom.skip()
    def test_before_apply_approval(self):

        """事前申请审批操作"""
        
        # 第一步:添加事前申请
        file_id = self.test_before_apply_submit()

        # 第二步:退出申请人账号
        self.logout_url = '/logout'
        payload ={}
        # 退出接口信息
        r_userinfo = self.get(self.logout_url,data=payload)
        self.assertStatusCode(200)

        # 第三步:登录审批人账号
        test_approval_login = LoginApprovalTest()
        cookie_token =test_approval_login.test_approval_login()

        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':cookie_token,
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }

        # 查看审批单信息
        self.before_find_apply_url = '/app/homepage/todoListDataPage'
        payload = {
            'pageNo':1,
            'pageSize':20,
            'taskName':'事前-事前申请',
            'applyUserName':'',
            'orderBy':5,
            'applyOfficeName':'',
            'applyReason':'',
            'budgetName':'',
            'receiverName':'',
            'minApplyAmount':'',
            'maxApplyAmount':''
        }

        # 获取待审批接口信息
        r_userinfo = self.get(self.before_find_apply_url,cookies=Cookies,params=payload)
        # print(r_userinfo.url)
        self.assertStatusCode(200)
        apply_advance = self.response['data'][0]
        apply_advance_processInstanceId_app = self.response['data'][0]['task']['processInstanceId']
        print(self.response)
        print(apply_advance)
        print(apply_advance_processInstanceId_app)

        # 第四步:审批人审批
        self.approval_apply_url = '/act/task/appSaveAudit'
        params = {
            'procInsId':apply_advance_processInstanceId_app,
            'flag':'yes',
            'comment':''
        }

        r_userinfo = self.post(self.approval_apply_url,cookies=Cookies,params=params)
        self.assertStatusCode(200)
        apply_advance = self.response
        print(self.response)
        print(apply_advance)
        assert_json = {'msg': '审批成功', 'code': 0}
        self.assertJSON(assert_json)
        # 第五步:审批账号退出
        
        payload ={}
        # 退出接口信息
        r_userinfo = self.get(self.logout_url,data=payload)
        self.assertStatusCode(200)

        return file_id



    def test_before_apply_invalidAndReset(self):

        """事前申请单作废重置操作"""
        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':self.setup(),
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }

        
        # 第一步:添加事前申请
        self.test_before_apply_submit()

        
        # 第二步:查询提交状态的单据信息
        test_select_approval = SelectApplyCommon()
        apply_list = test_select_approval.select_approval_form_web(self.setup())
        print(apply_list)
        apply_advance_id_reset = apply_list[0]

        

        #第三步:申请单据作废重置操作
        
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        rString = salt + localTime

        self.before_apply_reset_url = '/budexec/beforeApply/invalidAndReset'
        payload = {
            'id':apply_advance_id_reset,
            'invalidReason':rString
        }
        print(apply_advance_id_reset)
        # 申请单作废接口信息
        r_userinfo = self.post(self.before_apply_reset_url,cookies=Cookies,data=payload)
        self.assertStatusCode(200)

        assert_reset = {'code': 0}
        self.assertJSON(assert_reset)




    def test_before_apply_invalid(self):
        """申请单作废操作"""
        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':self.setup(),
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }

        
        # 第一步:添加事前申请
        self.test_before_apply_submit()

        
        # 第二步:查询提交状态的单据信息
        test_select_approval = SelectApplyCommon()
        apply_list = test_select_approval.select_approval_form_web(self.setup())
        print(apply_list)
        apply_advance_id_reset = apply_list[0]

        

        #第三步:申请单据作废操作
        
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        rString = salt + localTime

        self.before_apply_invalid_url = '/budexec/beforeApply/invalid'
        payload = {
            'id':apply_advance_id_reset,
            'invalidReason':rString
        }
        print(apply_advance_id_reset)
        # 申请单作废接口信息
        r_userinfo = self.post(self.before_apply_invalid_url,cookies=Cookies,data=payload)
        self.assertStatusCode(200)

        assert_reset = {'code': 0}
        self.assertJSON(assert_reset)




    def test_before_apply_recall(self):
        """申请单撤回操作"""
        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':self.setup(),
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }

        # 第一步:添加事前申请提交
        self.test_before_apply_submit()

        # 第二步:查询待审批的事前申请单
        select_approval_apply = SelectApplyCommon()
        apply_list = select_approval_apply.select_approval_form_web(self.setup())
        print(apply_list)
        apply_advance_recall_taskDefKey = apply_list[1]
        apply_advance_recall_activityId = apply_list[2]
        apply_advance_recall_taskId = apply_list[3]
        apply_advance_recall_procInsId = apply_list[4]
        apply_advance_recall_procDefId = apply_list[5]

        # 第三步:撤回事前申请单操作
        self.before_apply_recall_url = '/act/task/ajaxRecallPro'
        payload = {
            'targetTaskKey':apply_advance_recall_activityId,
            'taskDefKey':apply_advance_recall_taskDefKey,
            'procInsId': apply_advance_recall_procInsId,
            'procDefId':apply_advance_recall_procDefId,
            'taskId': apply_advance_recall_taskId
        }
        
        # 申请单撤回接口信息
        r_userinfo = self.post(self.before_apply_recall_url,cookies=Cookies,data=payload)
        self.assertStatusCode(200)

        assert_reset = {'code': 0}
        self.assertJSON(assert_reset)



    def test_before_apply_approval_no(self):
        """"事前申请退回操作"""
        # 第一步:添加事前申请
        self.test_before_apply_submit()

        # 第二步:退出当前账号
        test_logout = LoginTest()
        test_logout.logout()

        # 审批账号登录
        test_approval_login = LoginApprovalTest()
        cookie_token =test_approval_login.test_approval_login()

        Cookies = {

            # 从浏览器中复制过来的Cookie
            'rcm.session.id':cookie_token,
            'accountSuitId':'fa80c8f8b9ee43a79fdfa5ddf8d29807'
        }
        # 第三步:获取app待审批列表信息
        test_approval_app_list = SelectApplyCommon()
        apply_list = test_approval_app_list.select_approval_form(cookie_token)
        apply_advance_processInstanceId_app = apply_list
        # 第四步:审批退回操作
        self.approval_apply_url = '/act/task/appSaveAudit'
        params = {
            'procInsId':apply_advance_processInstanceId_app,
            'flag':'no',
            'comment':''
        }

        r_userinfo = self.post(self.approval_apply_url,cookies=Cookies,params=params)
        self.assertStatusCode(200)
        apply_advance = self.response
        print(self.response)
        print(apply_advance)
        assert_json = {'msg': '审批成功', 'code': 0}
        self.assertJSON(assert_json)
        # 第五步:审批账号退出
        test_logout = LoginTest()
        test_logout.logout()


if __name__ == '__main__':
    seldom.main()

以上是使用seldom进行部门接口自动化的示例信息,目前已完成系统60%常用模块的接口测试用例,代码部分已上传gitee上,具体使用请参考seldom版本手册。

四、总结

目前使用python框架可以很好的实现接口自动化,相比工具而言可能需要一定的时间成本,但是成效也非常显著!后期可以考虑集合jenkins完成一键部署测试,更好的实现自动化部署测试。

posted @ 2021-11-02 15:50  janehost  阅读(339)  评论(0编辑  收藏  举报