接口自动化测试实战之Python操作数据库、接口关联及相关管理优化

288 篇文章 0 订阅
125 篇文章 0 订阅
一、前言

本文章主要会讲解接口自动化测试中Python如何操作数据库、为何要操作数据库,有哪些利弊,以及数据库断言、相关的接口关联的测试

二、自动化数据库理论与操作
2.1 接口自动化为何要操作数据库

接口自动化中操作数据库主要是根据业务层面决定的,部分情况例如查询手机号、或个人信息时需要操作数据库,有时候也有可能需要删除某个内容,通常而言不会这么做罢了。

2.2 接口自动化操作数据库的利弊
  1. """

  2. 利:

  3. 1、能够根据我们需要的业务情况来解决一定的业务问题

  4. 弊:

  5. 1、数据库的操作本身就会让自动化变得慢,需要建立连接 -- 查询 等等

  6. 2、数据库本身是一种依赖, 我们能不操作数据库尽可能不操作

  7. """

'

运行

运行

2.3 Python操作数据库

要操作数据库,需要先进行pymysql库的安装,按照对应语法填写好对应数据即可:

  1. import pymysql

  2. """

  3. 1、连接数据库:输入用户名,密码,地址,端口

  4. 2、游标:使用游标读取数据、修改数据(执行sql语句)

  5. 3、获取操作结果

  6. 4、关闭游标

  7. 5、关闭数据库连接

  8. """

  9. conn = pymysql.connect(user="future",

  10. password="XXXXXX",

  11. host="XX.XX.XX.XX",

  12. port=3306

  13. )

  14. cursor = conn.cursor()

  15. # 执行sql

  16. sql = "SELECT mobile_phone,id,reg_name FROM XXXXXXX.member WHERE mobile_phone = 137XXXXXXXX"

  17. cursor.execute(sql)

  18. # 获取一个结果每条记录用元组表示

  19. res = cursor.fetchone()

  20. print(res)

  21. # 关闭

  22. cursor.close()

  23. conn.close()

输出的数据是元组,元组数据不可修改,我们需要进行类型转换,如要输出字典,需要加上DictCursor:

  1. import pymysql

  2. from pymysql.cursors import DictCursor

  3. """

  4. 1、连接数据库:输入用户名,密码,地址,端口

  5. 2、游标:使用游标读取数据、修改数据(执行sql语句)

  6. 3、获取操作结果

  7. 4、关闭游标

  8. 5、关闭数据库连接

  9. """

  10. conn = pymysql.connect(user="future",

  11. password="XXXXXX",

  12. host="XX.XX.XX.XX",

  13. port=3306

  14. )

  15. cursor = conn.cursor(DictCursor)

  16. # 执行sql

  17. sql = "SELECT mobile_phone,id,reg_name FROM XXXXXXX.member WHERE mobile_phone = 137XXXXXXXX"

  18. cursor.execute(sql)

  19. # 获取一个结果每条记录用元组表示

  20. res = cursor.fetchone()

  21. print(res)

  22. # 关闭

  23. cursor.close()

  24. conn.close()

2.4 操作数据库封装

我们需要进行函数封装,数据库内容也属于公用内容,也可以放入至common包下,函数封装后:

  1. class DBHandler:

  2. def __init__(self, host=setting.db_host, port=setting.db_port,

  3. user=setting.db_user, password=setting.db_pwd):

  4. self.conn = pymysql.connect(user=user,

  5. password=password,

  6. host=host,

  7. port=port,

  8. autocommit=True

  9. )

  10. def query_one(self, sql, cursor_type=DictCursor):

  11. cursor = self.conn.cursor(cursor_type)

  12. cursor.execute(sql)

  13. data = cursor.fetchone()

  14. cursor.close()

  15. return data

  16. def query_all(self, sql, cursor_type=DictCursor):

  17. cursor = self.conn.cursor(cursor_type)

  18. cursor.execute(sql)

  19. data = cursor.fetchall()

  20. cursor.close()

  21. return data

  22. def query(self, sql, one=True, cursor_type=DictCursor):

  23. if one:

  24. return self.query_one(sql, cursor_type)

  25. return self.query_all(sql, cursor_type)

  26. def close(self):

  27. self.conn.close()

  28. # 自己实现上下文管理器

  29. # def __enter__(self):

  30. # return self

  31. #

  32. # def __exit__(self, exc_type, exc_val, exc_tb):

  33. # return self.close()

  34. db_module = DBHandler()

  35. if __name__ == '__main__':

  36. db = DBHandler()

  37. sql = 'select mobile_phone from futureloan.member limit 5'

  38. res = db.query(sql, one=False)

  39. db.close()

  40. print(res)

  41. #

  42. # with DBHandler_2() as db:

  43. # sql = 'select mobile_phone from futureloan.member limit 5'

  44. # res = db.query(sql, one=False)

  45. # print(res)

  46. # 数据库配置项

  47. db_host = "XX.XX.XX.XX"

  48. db_port = XXXX

  49. db_user = "future"

  50. db_pwd = "XXXXXX"

三、校验数据库、接口关联及项目优化

自动化测试用例执行后,判断成功的测试用例才进行数据库的校验:

  1. import unittest

  2. import requests

  3. import json

  4. from common.db import DBHandler, db_module

  5. from common.logger import log

  6. from common.excel import read_excel

  7. from common import helper

  8. from config import path_config

  9. from unittestreport import ddt, list_data

  10. from config import setting

  11. # 获取数据

  12. data = read_excel(path_config.case_path , 'XXXXXX')

  13. @ddt

  14. class TestRegister(unittest.TestCase):

  15. @classmethod

  16. def setUpClass(cls) -> None:

  17. """测试类的前置"""

  18. cls.db = DBHandler()

  19. @classmethod

  20. def tearDownClass(cls) -> None:

  21. """测试类的前置"""

  22. cls.db.close()

  23. @list_data(data)

  24. def test_register(self, case_data):

  25. print(case_data)

  26. json_data = case_data['json']

  27. if '#new_phone#' in json_data:

  28. new_phone = helper.generate_new_phone()

  29. json_data = json_data.replace('#new_phone#', new_phone)

  30. # 把json格式的字符串转化成字典

  31. json_data = json.loads(json_data)

  32. headers = json.loads(case_data['headers'])

  33. print("替换之后", json_data)

  34. resp = requests.request(

  35. method=case_data['method'],

  36. url= setting.host + case_data['url'],

  37. json=json_data,

  38. headers=headers

  39. )

  40. actual = resp.json()

  41. print(actual)

  42. try:

  43. self.assertEqual(case_data['expected'], actual['code'])

  44. except AssertionError as e:

  45. raise e

  46. """

  47. 1、判断是否是注册成功的测试用例

  48. 2、查询数据库是否包含了手机号的记录

  49. 3、判断数据库记录条数是否为1

  50. """

  51. if actual['msg'] == "OK":

  52. # 通过 setUp 创建数据库连接

  53. sql = f"select id from XXXX.XXXX where XXXXXX = {json_data['XXXXXX']}"

  54. result = self.db.query_all(sql)

  55. self.assertEqual(1, len(result))

往往项目中的接口都会存在接口关联,而我们就需要对接口进行单独处理:

  1. import unittest

  2. import requests

  3. import json

  4. from jsonpath import jsonpath

  5. from decimal import Decimal

  6. from common.db import DBHandler

  7. from common.logger import log

  8. from common.excel import read_excel

  9. from common import helper

  10. from config import path_config

  11. from unittestreport import ddt, list_data

  12. from config import setting

  13. # 获取数据

  14. from middle import api

  15. data = read_excel(path_config.case_path , 'XXXXXX')

  16. @ddt

  17. class TestRecharge(unittest.TestCase):

  18. @classmethod

  19. def setUpClass(cls) -> None:

  20. """

  21. 1,访问登录接口,得到返回值

  22. 2,从返回值当中提取数据:resp["data"]["id"]

  23. 3, 从返回值当中提取数据:resp["data"]["token_info"]["token"]

  24. 4, 设置成类属性,方便测试用例函数当中调用

  25. :return:

  26. """

  27. resp_data = api.login()

  28. # 提取方式1:

  29. cls.member_id = resp_data["data"]["id"]

  30. cls.token = resp_data["data"]["token_info"]["token"]

  31. # 提取方式2:jsonpath

  32. cls.member_id = jsonpath(resp_data, '$..id')[0]

  33. cls.token = jsonpath(resp_data, '$..token')[0]

  34. cls.before = jsonpath(resp_data, '$..leave_amount')[0]

  35. # 初始化数据库

  36. cls.db = DBHandler()

  37. @classmethod

  38. def tearDownClass(cls) -> None:

  39. pass

  40. @list_data(data)

  41. def test_recharge(self, case_data):

  42. """

  43. 1, 获取 case_data 当中的数据,headers, json 是要重点关注的。

  44. 2, 数据的预处理:数据替换,数据转化成 字典格式:headers, json, expected

  45. 3, 发送请求

  46. 4, 断言

  47. :param case_data:

  48. :return:

  49. """

  50. # 获取 case_data当中的数据,headers, json是要重点关注的。

  51. headers_string = case_data['headers']

  52. json_string = case_data['json']

  53. # 数据的预处理:数据替换,数据转化成字典格式:headers, json, expected

  54. if "#token#" in headers_string:

  55. headers_string = headers_string.replace("#token#", self.token)

  56. if "#member_id#" in json_string:

  57. json_string = json_string.replace("#member_id#", str(self.member_id))

  58. headers = json.loads(headers_string)

  59. json_data = json.loads(json_string)

  60. expected = json.loads(case_data['expected'])

  61. # 获取充值之前数据库当中用户的余额

  62. sql = f"select XXXXXXX from XXXX.XXXXX where id={self.XXXXX_id}"

  63. before = self.db.query_one(sql)

  64. # {"leave_amount": 200}

  65. # 3, 发送请求

  66. resp = requests.request(

  67. method=case_data['method'],

  68. url=setting.host + case_data['url'],

  69. json=json_data,

  70. headers=headers

  71. )

  72. # 4, 断言

  73. json_response = resp.json()

  74. try:

  75. for key, value in expected.items():

  76. self.assertEqual(value, json_response[key])

  77. except AssertionError as e:

  78. log.error(f"测试用例失败:{e}")

  79. raise e

  80. if json_response['msg'] == 'OK':

  81. print(json_response)

  82. # 通过数据库断言

  83. sql = f"select leave_amount from futureloan.member where id={self.member_id}"

  84. after = self.db.query_one(sql)

  85. money = str(json_data['amount'])

  86. after = str(after['leave_amount'])

  87. before = str(before['leave_amount'])

  88. self.assertEqual(Decimal(money), Decimal(after) - Decimal(before))

四、总结

关于接口自动化测试中Python如何操作数据库、为何要操作数据库,有哪些利弊,以及数据库断言、相关的接口关联的测试,笔者就说到这里了,喜欢的小伙伴可以收藏点赞评论,加关注哟,关注我每天给你不同的惊喜。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值