• 0
  • 0
分享

python接口自动化实战

目标

  • 学习数据库相关,用例增加对数据库校验

  • 利用数据库完成对数据查询

  • 如何校验数据库数据,怎样添加校验让程序自己校验(充值、提现、投资接口对金额的校验)

知识补充

  • 用例之间关联性不要太强,比如每个模块的用例都需要登录状态,在每个模块最开始加上一次登录的用例即可。

  • 关于登录、充值啥的,用例里面的手机号最好不要写死,万一该手机号数据有脏数据,处理起来会很麻烦,所以一般在用例里面用变量,将数据放在指定的sheet里面方便读取与修改

  • 什么接口需要数据库校验?钱的变动、增减

数据库

  • 安装mysql.connector模块 pip2 install --user mysql-connector

  • 基本使用

1.png

import mysql.connector
db_config = {
    'host':'47.107.168.87',
    'user':'python',
    'password':'python666',
    'port':'3306',
    'database':'future'
}
#创建一个数据库连接
con = mysql.connector.connect(**db_config)
#建立游标cursor
cursor = con.cursor()
#写sql语句
query_sql = 'select * from member where MobilePhone = 13755120064'
#执行sql语句
cursor.execute(query_sql)
#获取结果,打印结果
# res = cursor.fetchone()  #元组  只对一条数据
res = cursor.fetchall()  #列表   多条数据
print res
#关闭游标
cursor.close()
#关闭连接
con.close()
  • 说明

query_sql = 'select * from member'

2.png

  • 因为数据库有很多数据,控制台只输出一条,还有报错,是因为cursor.fetchone()

  1. cursor.fetchone() 返回是元组,只针对一条数据

  2. cursor.fetchall() 返回是列表,针对多行数据,列表嵌套元组

  3. 要返回所有结果,就采用cursor.fetchall()

  • 前面说的初始化手机号的方法,可以通过数据库拿到目前最大的手机号进行+1操作,这样保证初始化的手机号不会和数据库里的号码有冲突

写一个对数据库操作的类

  • 在配置文件中配置数据库相关信息

[DB]
db_config = {
    'host':'47.107.168.87',
    'user':'python',
    'password':'python666',
    'port':3306,
    'database':'future',
    'buffered':True
    }  #这是正确写法

今天遇到一个错误,解决了一整天,心累,原因竟然是“配置文件括号缩进”的问题

3.png

这个是错误的写法,遇到的同学注意一下,这是个坑

[DB]
db_config = {
    'host':'47.107.168.87',
    'user':'python',
    'password':'python666',
    'port':3306,
    'database':'future',
    'buffered':True
}   #这个是错误的写法
  • 操作数据库的类

import json
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import mysql.connector
from project_path import *
from read_config import ReadConfig
class DoMysql:
    def do_mysql(self,query_sql,state='all'):  #query查询语句  state-->all  多天   one   一条
        db_config = eval(ReadConfig().get_config(case_config_path,'DB','db_config')) #利用这个类从配置文件里面读取db info
        #创建一个数据库连接
        con =mysql.connector.connect(**db_config)
        #建立游标cursor
        cursor = con.cursor()
        #执行sql语句
        cursor.execute(query_sql)
        # 获取结果,打印结果
        if state==1:
            res = cursor.fetchone()  # 元组  只对一条数据
        else:
            res = cursor.fetchall()  #列表   多条数据
        #关闭游标
        cursor.close()
        #关闭连接
        con.close()
        return res  #这个返回值要放在关闭游标、关闭连接之后

当第二个接口的参数是第一个接口的执行的结果时,该怎么处理

在请求之前完成loan_id的替换,因为loan_id是上一个接口返回的,所以不能在do_excel里面提前处理,t

est_http_request.py文件
import unittest
from http_request import HttpRequest
from ddt import ddt,data
from project_path import *
from do_excel import DoExcel
from get_data import GetData
from do_mysql import DoMysql
test_data = DoExcel().get_data(test_case_path)
from my_log import MyLog
my_logger = MyLog()
@ddt()
class TestHttpRequest(unittest.TestCase):
    def setUp(self):
        pass
    @data(*test_data)
    def test_api1(self,item):
        my_logger.info('开始执行用例{0}'.format(item['用例名称']))
        #在请求之前完成loan_id替换,因为loan_id是上一个接口返回的,所以不能在do_excel里面提前处理,
        if item['data'].find('${loan_id}') != -1:
            if getattr(GetData,'loan_id') == None:
                query_sql = 'select max(Id) from loan where MemberID={0}'.format(getattr(GetData,'loan_member_id'))
                loan_id = DoMysql().do_mysql(query_sql)[0][0]
                item['data'] = item['data'].replace('${loan_id}',str(loan_id))
                setattr(GetData,'loan_id',loan_id)  #利用这个反射做存储结果
            else:
                item['data'] = item['data'].replace('${loan_id}', getattr(GetData,'loan_id'))
        res = HttpRequest().http_request(item['url'],item['data'],item['method'])
        try:
            self.assertEqual(item['except'],res.json()['code'])
            TestResult = 'pass'   #成功
        except AssertionError as e:
            TestResult = 'Failed'   #失败
            raise e
        finally:
            DoExcel().write_back(test_case_path,item['sheet_name'],item['case_id']+1,str(res.json()),TestResult)
            print res.json()
            my_logger.debug('获取的结果是:{0}'.format(res.json()))
    def tearDown(self):
        pass

存储数据的脚本get_data.py文件

from project_path import *
import pandas as pd
from openpyxl import load_workbook
class GetData:
    Cookie = None
    loan_id = None
    # NotRegTel = int(pd.read_excel(test_case_path,sheet_name='init').ix[0,0])  #采用pandas获取excel里面的数据
    NotRegTel = load_workbook(test_case_path)['init'].cell(2,1).value
    normal_tel = load_workbook(test_case_path)['init'].cell(3,1).value
    admin_tel = load_workbook(test_case_path)['init'].cell(4,1).value
    loan_member_id = load_workbook(test_case_path)['init'].cell(5,1).value
    memberID = load_workbook(test_case_path)['init'].cell(6,1).value

对于需要进行数据库校验的接口,在请求前后进行数据库值对比。

如:充值前和充值后都要对数据库数据进行对照,应有的余额是否正确。那么在请求前需要查一次余额,请求后需要查一次余额

  • 解决:配置文件中新增配置,通过配置sheet_name来判断是否需要请求前后查询余额

[CHECKLEAVEAMOUNT]
check_list=["recharge","invest"]

使用

#get_data.py
check_list=eval(ReadConfig.get_config(case_config_path, "CHECKLEAVEAMOUNT", "check_list"))
#test_http_request.py
       
        if item['sheet_name'] in getattr(GetData,'check_list'):
            #请求之前,根据用户id查询数据库余额
            query_sql = 'SELECT a.LeaveAmount FROM member a WHERE a.MobilePhone={0}'.format(eval(item['data'])['MobilePhone'])
            Before_amount = DoMysql.do_mysql(query_sql)[0][0]
            res = HttpRequest().http_request(item['url'],item['data'],item['method'],getattr(GetData,'Cookie'))
            #请求之后,根据用户id再次查询数据库余额
            query_sql = 'SELECT a.LeaveAmount FROM member a WHERE a.MobilePhone={0}'.format(eval(item['data'])['MobilePhone'])
            After_amount = DoMysql.do_mysql(query_sql)[0][0]
            #判断(请求后余额-请求前余额)是否等于充值余额,存储判断结果
            if abs(Before_amount-After_amount) == eval(item['data'])['amount']:
                check_res = '金额正确'
            else:
                check_res = '金额错误'
                #上述方法相当于一个模块所有用例都要去check一次,但实际中并不一定需要。
        else:
            res = HttpRequest().http_request(item['url'],item['data'],item['method'],getattr(GetData,'Cookie'))
  • 另一种解决思路:

  1. 上述方法相当于一个模块所有用例都要去check一次,但实际中并不一定需要。

  2. 另一个解决思路:在excel中新增一个字段check_sql,格式:{sql:SELECT a.LeaveAmount FROM member a WHERE a.MobilePhone=1234},检测如果有query_sql就校验数据库,query_sql为None就不校验数据库

 #test_http_request.py
if item["check_sql"]!=None:
    query_sql=eval(item["check_sql"]["sql"])
    #TODO:请求之前数据库余额    
    res = HttpRequest().http_request(item['url'],item['data'],item['method'],getattr(GetData,'Cookie'))
    #TODO:请求之后数据库余额
    
    #TODO:判断(请求后余额-请求前余额)的绝对值是否等于充值余额,存储判断结果
    if (请求后余额-请求前余额)的绝对值==充值余额:
        check_sql_result="数据库校验通过"
    else:
        check_sql_result="数据库校验不通过"
    
    #TODO:将结果写回
    DoExcel().write_back_data(test_data_path,item["sheet_name"],item["case_id"]+1,10,str(check_sql_result))
else:
    res = HttpRequest().http_request(item['url'],item['data'],item['method'],getattr(GetData,'Cookie'))

把结果写回的函数修改,记得把result和TestResult字段的代码修改:

#do_excel.py
@staticmethod
def write_back_data(file_name,sheet_name,row,col,result):
    wb=load_workbook(file_name)
    sheet=wb[sheet_name]
    sheet.cell(row,col).value=result
    wb.save(file_name) #保存
#result写回
DoExcel.write_back_data(test_data_path,item["sheet_name"],item["case_id"]+1,8,str(json.dumps(res.json(), encoding="utf-8", ensure_ascii=False)))
#TestResult写回
DoExcel.write_back_data(test_data_path,item["sheet_name"],item["case_id"]+1,9,str(TestResult))
  • 怎么把数据库校验结果写到excel中?

思路:多一个CheckResult字段

  • 检查多个点,需要多个sql语句怎么办?

思路:[{sql1:xxxx},{sql2:xxx},…]

  • 技巧:代码调试时,多使用日志,写完后,可以通过改日志级别控制输出的日志。


作者:萌萌哒小宝宝

原文链接:https://blog.csdn.net/qq_38889350/article/details/107513544


  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • Dify 一词源自 Define + Modify,意指定义并持续改进你的 AI 应用。随着大型语言模型(LLM)不断涌现的各种能力,AI 应用的场景变得更加广阔。然而,对于大多数开发者而言,基于 GPT 等大型语言模型、Langchain 等技术框架开发 AI 应用仍然是一项门槛极高的任务。开发者必须花费大量时间学习各种晦涩的概念和技术研究,也无法进行 AI 应用的持续运营。是否有这样一个工具,开发者无需关注基础设施的底层原理,只需专注于将想象力转化为实际落地的 AI 应用并持续运营,可以将大型语言模型变成像云计算服务一样易于使用?基于这个问题,Dify.AI 诞生了。它是为你而做的(Do ...
            0 0 1707
            分享
          •   埃隆·马斯克周四晚间起诉他十年前参与创立的生成式人工智能公司 OpenAI,此举震惊业界。据最新报道,周五晚间 OpenAI 向员工发送了一份备忘录,驳斥了马斯克的指控,并对其提起诉讼的原因提出了另一种解释。  马斯克在诉讼文件中表示,OpenAI 违背了协议,不再像非营利组织那样开发 ChatGPT 等生成式人工智能产品。他指控该公司现在正在开发软件服务只是为了给微软赚钱,而微软此前向 OpenAI 投资了数十亿美元,并利用 OpenAI 帮助其开发 Copilot 等人工智能产品。  据 CNBC 报道,OpenAI 首席战略官 Jason Kwon 在周五向其在职员工发送了一份备忘录...
            0 0 736
            分享
          • ThreadLocal是Java中的一个类,全路径:java.lang.ThreadLocal,用于在多线程环境下存储线程本地变量。在多线程应用程序中,不同线程之间共享数据可能会引发线程安全问题。ThreadLocal通过为每个线程创建独立的变量副本,保证了线程间数据的隔离性,从而有效地解决了这一问题。线程之间的数据访问操作互不影响,提高了多线程应用程序的性能和可靠性。ThreadLocal通常与线程池、异步任务和Web应用程序等场景结合使用,使得在多线程编程时更加方便和安全。虽然ThreadLocal有这么多好处,但在之前的实际使用中用的并不多,只有在性能测试中的随机数性能问题探索和随机方法...
            0 0 1033
            分享
          •   一、负责测试组的工作组织和管理  1.参加软件产品开发前的需求调研和分析;  2.根据需求,概要设计和开发计划编写项目总体测试计划,详细测试计划,测试大纲和测试文档结构表(测试计划 a.已上线产品维护以及需求变更 b.后期新项目的开发);  3.测试流程、测试工作规范、工作流程标准的制定(测试流程 a. 新产品开发,敏捷测试高迭代 b.产品上线后,维护阶段,新需求开发严格按照流程规范执行);  4.合理安排测试工程师、功能测试、业务专家、自动化测试(回归测试)、性能测试;  5.组织搭建测试环境以及测试结束后组织整理测试文档,提交测试报告;  6.现阶段测试规划(自动化测试、性能测试)、未...
            0 0 1199
            分享
          •   在奇瑞昨日晚间举行的“讯飞星火认知大模型首搭星纪元 ES”发布会上,奇瑞汽车执行副总经理、汽车工程技术研发总院院长高新华接受 21 世纪经济报道采访,对奇瑞与华为的合作进行正面回应。  高新华表示,当日首发亮相的星途星纪元品牌车型主打舒适,相当于电动化的“奔驰”,而奇瑞与华为合作打造的新品牌 LUXEED 智界,则相当于电动化的“宝马”,两个品牌将针对不同人群。  奇瑞汽车今年 4 月重新梳理旗下品牌,形成奇瑞、捷途、星途和 iCAR 四大品牌布局。IT之家此前报道,奇瑞与华为的“baby”已经在工信部完成申报,悬挂 LUXEED 车标,车型名称为智界 S7。  工信部数据显示,这款新车拥...
            0 0 1106
            分享
      • 51testing软件测试圈微信