接口自动化测试之数据清洗/隔离/备份/恢复

在得到QQ:1301559180 得代码贡献之后,想到了通过ssh连接上服务器,然后进行数据库备份,数据库恢复, 主要使用了 paramiko

最终效果

  1. 测试开始前会进行数据备份,并在下面2个路径存储对应的数据库备份(目前备份的数据库是写死的为,测试连接的mysql数据库).sql文件

    数据库服务器: /root/backup_sql/

    本地(运行测试脚本的机器)当前目录下的 backup_sqls

    文件命名方式为: 数据库名+时间

如何使用

  1. 通过在config.yaml中配置对应得数据库信息,服务器必要得账号密码等信息(支持私钥文件登录,但个人未尝试),大致文件格式如下

    # 数据库校验- mysql
    database:
    host: localhost
    port: 3306
    user: root
    # 不用''会被解析成int类型数据
    password: '123456'
    db_name: test
    charset: utf8mb4 # 数据库所在的服务器配置
    ssh_server:
    port: 22
    username: root
    password: '123456'
    # 私有密钥文件路径
    private_key_file:
    # 如果使用的docker容器部署mysql服务,需要传入mysql的容器id/name
    mysql_container: mysql8
    # 数据库备份文件导出的本地路径, 需要保证存在该文件夹
    sql_data_file: backup_sqls/
  2. 然后在test/conftest.py做如下操作

    #!/usr/bin/env/python3
    # -*- coding:utf-8 -*-
    """
    @project: apiAutoTest
    @author: zy7y
    @file: conftest.py
    @ide: PyCharm
    @time: 2020/12/8
    @desc:
    """ import pytest from tools.data_clearing import DataClearing
    from tools.db import DB
    from tools.read_file import ReadFile @pytest.fixture(scope="session")
    def data_clearing():
    """数据清洗"""
    DataClearing.server_init()
    # 1. 备份数据库
    DataClearing.backup_mysql()
    yield
    # 2. 恢复数据库
    DataClearing.recovery_mysql()
    DataClearing.close_client() # 若不需要数据清洗功能,请把get_db()入参拿掉
    @pytest.fixture(scope="session")
    def get_db(data_clearing):
    """关于其作用域请移步查看官方文档"""
    try:
    db = DB()
    yield db
    finally:
    db.close() @pytest.fixture(params=ReadFile.read_testcase())
    def cases(request):
    """用例数据,测试方法参数入参该方法名 cases即可,实现同样的参数化
    目前来看相较于@pytest.mark.parametrize 更简洁。
    """
    return request.param

实现代码

#!/usr/bin/env python
# -*- coding: utf-8 -*- """
@Time : 2021/1/19 11:44
@Author : zy7y
@ProjectName : apiAutoTest
@File : data_clearing.py
@Software : PyCharm
@Github : https://github.com/zy7y
@Blog : https://www.cnblogs.com/zy7y
""" import os
from datetime import datetime
import paramiko
from tools.read_file import ReadFile
from tools import logger class ServerTools:
def __init__(self, host: str, port: int = 22, username: str = "root", password: str = None,
private_key_file: str = None):
# 进行SSH连接
self.trans = paramiko.Transport((host, port))
self.host = host
if password is None:
self.trans.connect(username=username, pkey=paramiko.RSAKey.from_private_key_file(private_key_file))
else:
self.trans.connect(username=username, password=password)
# 将sshclient的对象的transport指定为以上的trans
self.ssh = paramiko.SSHClient()
logger.success("SSH客户端创建成功.")
self.ssh._transport = self.trans
# 创建SFTP客户端
self.ftp_client = paramiko.SFTPClient.from_transport(self.trans)
logger.success("SFTP客户端创建成功.") def execute_cmd(self, cmd: str):
"""
:param cmd: 服务器下对应的命令, 可以是list,或者str
"""
stdin, stdout, stderr = self.ssh.exec_command(cmd)
error = stderr.read().decode()
logger.info(f"输入命令: {cmd} -> 输出结果: {stdout.read().decode()}")
logger.error(f"异常信息: {error}")
return error def files_action(self, post: bool, local_path: str = os.getcwd(), remote_path: str = "/root"):
"""
:param post: 动作 为 True 就是上传, False就是下载
:param local_path: 本地的文件路径, 默认当前脚本所在的工作目录
:param remote_path: 服务器上的文件路径,默认在/root目录下
"""
if post: # 上传文件
self.ftp_client.put(localpath=local_path, remotepath=f"{remote_path}{os.path.split(local_path)[1]}")
logger.info(f"文件上传成功: {local_path} -> {self.host}:{remote_path}{os.path.split(local_path)[1]}")
else: # 下载文件
file_path = local_path + os.path.split(remote_path)[1]
self.ftp_client.get(remotepath=remote_path, localpath=file_path)
logger.info(f"文件下载成功: {self.host}:{remote_path} -> {file_path}") def ssh_close(self):
"""关闭连接"""
self.trans.close()
logger.info("已关闭SSH连接...") class DataClearing:
settings = ReadFile.read_config('$.database')
server_settings = settings.get('ssh_server')
server = None # 导出的sql文件名称及后缀
file_name = f"{settings.get('db_name')}_{datetime.now().strftime('%Y-%m-%dT%H_%M_%S')}.sql" @classmethod
def server_init(cls, settings=settings, server_settings=server_settings):
cls.server = ServerTools(host=settings.get('host'), port=server_settings.get('port'),
username=server_settings.get('username'),
password=server_settings.get('password'),
private_key_file=server_settings.get('private_key_file'))
# 新建backup_sql文件夹在服务器上,存放导出的sql文件
cls.server.execute_cmd("mkdir backup_sql") @classmethod
def backup_mysql(cls):
"""
备份数据库, 会分别备份在数据库所在服务器的/root/backup_sql/目录下, 与当前项目文件目录下的 backup_sqls
每次备份生成一个数据库名_当前年_月_日T_时_分_秒, 支持linux 服务器上安装的mysql服务(本人未调试),以及linux中docker部署的mysql备份
"""
if cls.server_settings.get('mysql_container') is None:
cmd = f"mysqldump -h127.0.0.1 -u{cls.settings.get('username')} -p{cls.settings.get('password')} {cls.settings.get('db_name')} > {cls.file_name}"
else:
# 将mysql服务的容器中的指定数据库导出, 参考文章 https://www.cnblogs.com/wangsongbai/p/12666368.html
cmd = f"docker exec -i {cls.server_settings.get('mysql_container')} mysqldump -h127.0.0.1 -u{cls.settings.get('user')} -p{cls.settings.get('password')} {cls.settings.get('db_name')} > /root/backup_sql/{cls.file_name}"
cls.server.execute_cmd(cmd)
cls.server.files_action(0, f"{cls.server_settings.get('sql_data_file')}", f"/root/backup_sql/{cls.file_name}") @classmethod
def recovery_mysql(cls, sql_file: str = file_name, database: str = settings.get('db_name')): """
恢复数据库, 从服务器位置(/root/backup_sql/) 或者本地(../backup_sqls)上传, 传入的需要是.sql文件
:param sql_file: .sql数据库备份文件, 默认就是导出的sql文件名称, 默认文件名称是导出的sql文件
:param database: 恢复的数据库名称,默认是备份数据库(config.yaml中的db_name)
"""
result = cls.server.execute_cmd(f"ls -l /root/backup_sql/{sql_file}")
if "No such file or directory" in result:
# 本地上传
cls.server.files_action(1, f"../backup_sqls/{sql_file}", "/root/backup_sql/")
cmd = f"docker exec -i {cls.server_settings.get('mysql_container')} mysql -u{cls.settings.get('user')} -p{cls.settings.get('password')} {database} < /root/backup_sql/{sql_file}"
cls.server.execute_cmd(cmd) @classmethod
def close_client(cls):
cls.server.ssh_close()

源码地址

gitee: https://gitee.com/zy7y/apiAutoTest

github: https://github.com/zy7y/apiAutoTest

参考资料

https://www.cnblogs.com/wangsongbai/p/12666368.html
https://www.liujiangblog.com/blog/15/
https://blog.csdn.net/leorx01/article/details/71141643
http://docs.paramiko.org/en/stable/api/client.html
https://www.bilibili.com/video/BV1cQ4y1P7dg?p=4
# 详细的参考资料可以看这里
https://www.cnblogs.com/zy7y/p/14295902.html

最后

感谢遇见,欢迎讨论

apiAutoTest: 接口自动化测试的数据清洗(备份/恢复)处理方案的更多相关文章

  1. 接口自动化测试框架 (一) :APIAutoTest框架

    前言 随着测试技术的发展,接口自动化测试逐渐成为各大公司投入产出比最高的测试技术.介入时间早,执行效率高,稳定性高的优点,让越来越多的公司引入接口自动化测试. 框架简介 APIAutoTest是处理A ...

  2. 接口自动化测试框架 :APIAutoTest框架

    前言 随着测试技术的发展,接口自动化测试逐渐成为各大公司投入产出比最高的测试技术.介入时间早,执行效率高,稳定性高的优点,让越来越多的公司引入接口自动化测试. 框架简介 APIAutoTest是处理A ...

  3. python之接口自动化测试框架

    梳理python+unittest接口自动化测试框架的思路: 1.确定目录: cases:存放测试用例的py文件:config:存放一些数据库,环境地址等固定不变的信息: core:核心的文件, ca ...

  4. Oracle RMAN备份恢复指导书

    目 录 1 目的与范围... 1 2 术语和定义... 1 3 角色和职责... 2 4 使用RMAN备份数据库... 2 4.1.1 检查数据库模式... 2 4.1.2 连接到target数据库. ...

  5. 10.API 接口自动化测试的基本原理

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...

  6. python - 接口自动化测试 - RunTest - 测试用例加载执行/测试报告生成

    # -*- coding:utf-8 -*- ''' @project: ApiAutoTest @author: Jimmy @file: run_test.py @ide: PyCharm Com ...

  7. 云HBase备份恢复,为云HBase数据安全保驾护航

    摘要: 介绍了阿里云HBase自研备份恢复功能的基本背景以及基本原理架构和基本使用方法.   云HBase发布备份恢复功能,为用户数据保驾护航.对大多数公司来说数据的安全性以及可靠性是非常重要的,如何 ...

  8. Python接口自动化测试框架: pytest+allure+jsonpath+requests+excel实现的接口自动化测试框架(学习成果)

    废话 最近在自己学习接口自动化测试,这里也算是完成一个小的成果,欢迎大家交流指出不合适的地方,源码在文末 问题 整体代码结构优化未实现,导致最终测试时间变长,其他工具单接口测试只需要39ms,该框架中 ...

  9. MySQL 系列(四)主从复制、备份恢复方案生产环境实战

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...

随机推荐

  1. 图解Janusgraph系列-并发安全:锁机制(本地锁+分布式锁)分析

    图解Janusgraph系列-并发安全:锁机制(本地锁+分布式锁)分析 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步(超链):图数据 ...

  2. 移动端 rem和flexible

    一.rem布局 rem是相对于根元素的字体大小单位. 假设html的字体大小为16px,那么1rem = 16px; 一旦根元素html定义的font-size变化,整个页面中运用到的rem都会随之变 ...

  3. 多任务-python实现-使用生成器完成多任务(2.1.14)

    @ 目录 1.注意 2. 代码 关于作者 1.注意 先定义函数,函数里面放一个yiled 主函数生成该对象 执行while循环 调用生成器对象的next 因为每次调用next,不会继续执行,从而 完成 ...

  4. 弱肉强食——《哆啦A梦:大雄的新恐龙》观后感

    观看大雄的新恐龙不是在电影院观看的,由于时间的问题无法去电影院观看,是在家通过梦蓝字幕组翻译好的观看的,这个翻译好的视频已经由于版权原因没有发布了. 故事的开始与以往的情节十分相似:大雄因为不想被胖虎 ...

  5. 这个 bug 让我更加理解 Spring 单例了

    我是风筝,公众号「古时的风筝」,一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...

  6. Windows系统/office安装与激活

    一.Windows安装与激活 1.Windows7/8/10安装 提示:       重装系统时C盘会被格式化,故在重装系统前请先手动将重要资料转移到其他地方: 制作一个大白菜U盘winpe启动盘 查 ...

  7. SonarQube学习(一)- 使用Docker安装SonarQube(亲测可用)

    一.前言 不得不吐槽下,现在的博客写的真太扯淡了,就网上写的使用docker安装SonarQube而言,搜到十篇文章,最少9篇照着操作配置都不可用,卡在SonarQube无法启动.自然,我也是被折磨的 ...

  8. 在IDEA中的cannot_resolve_method解决方法

    打开IDEA编辑器,点击编辑器左上角file,出现菜单栏,点击菜单栏中的Settings选项.   在出现的Settings窗口中的左侧菜单栏中找到Plugins选项,点击进入'Plugins'窗口. ...

  9. ubuntu安装nfs服务

    安装: sudo apt-get install nfs-kernel-server 修改配置文件 /etc/exports 增加以下内容: /NFS *(rw,sync,no_root_squash ...

  10. spring之ApplicationEvent 事件驱动

    什么是ApplicationContext? 它是Spring的核心,Context我们通常解释为上下文环境,但是理解成容器会更好些. ApplicationContext则是应用的容器. Sprin ...