• 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


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

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   三星于 3 月 20 日举办了年度股东大会,董事长韩钟熙发言称尽管 2024 年宏观经济环境依然存在诸多不确定因素,但已看到了通过技术创新实现增长的发展机遇。  韩钟熙在会上发言表示:“三星计划在智能手机、可折叠设备、配件和扩展现实(XR)在内的所有产品上部署 AI,为客户提供生成式 AI 以及本地 AI 的全新体验”。  三星于 2023 年 12 月成立了先进封装业务团队(Advanced Package Business Team),划分到设备解决方案业务集团(Device Solutions business Group)下。  三星联席首席执行官庆桂显表示,三星电子在先进封装产业...
            0 0 263
            分享
          • 测试用例的定义:是为某个业务目标,而编制的一组由测试输入,执行条件以及预期结果组成的案例测试用例模板:用例编号,用例模块,用例标题,优先级,前置条件,输入内容,操作步骤,预期结果,时间结果常见的编写测试用例的方法等价划分:等价类划分属于典型的功能测试方法,根据程序对数据的要求,把程序的输入域划分成若干个部分,区分出哪些数据是有效的,哪些数据是无效的。核心概念:1)有效等价类:对程序规格说明有效的、合理的、有意义的输入集合程序接收到有效等价类数据,应该正确计算、执行2)无效等价类:对程序的规格说明无效的、不合理的、无意义的输入集合(例:错误用户名或密码)边界值分析法:如果需求规定范围或者规定了取...
            0 1 4401
            分享
          • 软件质量评估模型:顾名思义,软件质量评估模型是用来评估软件的测试质量的,也就是说测试的效果是否符合预期。 软件质量评估模型是从3个方面对软件质量进行评估的,内容如下所示: 1.测试覆盖度评估 2.测试过程评估 3.bug结果分析 测试覆盖度评估主要是对需求的覆盖范围进行评估的。测试过程评估主要是对测试用例的执行情况进行评估的。而bug结果分析主要是对bug的修复情况,bug的趋势分析进行评估的,下面我们就对这些详细的说明一下。 测试覆盖度评估 测试覆盖度评估是测试能够对软件质量进行评估的基础,如果覆盖度不够,那会对产品质量造成直接的影响。 测试覆盖度主要就是测试需求覆盖度的评估,需求覆盖度是已...
            3 8 5300
            分享
          •   缘起  众所周知,系统测试是需要编写测试用例的,它是保证测试执行正确性、有效性的基础。但是,大家可能很难想象神秘的黑客在挖掘漏洞的时候会提前编写测试用例,然后按照用例去执行。因为他的漏洞挖掘思路是存在脑海中,并且不断的根据实际情况进行调整的。  当然,关于黑客单打独斗挖掘漏洞的这种想象,显然已不大符合当前安全界的实际情况。从网络及信息安全的攻击角度来说,恶意攻击分子已经逐渐形成了目标精准、分工明确、技术先进的网络黑色产业链条,相应的从安全保护和防御角度来说,国家加大了对网络攻击等犯罪行为的打击力度,企业也逐渐加大了网络安全投入。  那么,当安全测试成为企业安全建设中的一个重要环节,安全测试...
            0 0 1665
            分享
          • 一、为什么要制定流程?先谈谈为什么要制定流程及流程对于工作拿到好结果的重要性。首先问大家五个问题:流程是什么?因人、团队、业务类型、迭代速度、资源紧张程度而异。我觉得流程是保障团队目标达成的最佳实践。为什么要有流程?没有流程会导致团队中个体各自为战,目标不统一,进度不协调,资源配给失衡而导致交付质量下降。流程能解决什么问题?保证团队大方向一致,尽可能降低由于人员能力、认知水平、资源不足、意外情况导致的项目延期或质量下降。流程能带来什么保障?保障团队中大部分人的利益不受影响和保障工作中遇到沟通或争执时可以据理力争;保障工作过程中的最佳实践可以最大程度保留并执行。如何高大上的理解流程?风险可识别+...
            0 0 1582
            分享
      • 51testing软件测试圈微信