当前位置: 首页 > news >正文

python测试工具: 实现数据源自动核对

测试业务需要:

现有A系统作为下游数据系统,上游系统有A1,A2,A3...

需要将A1,A2,A3...的数据达到某条件后(比如:A1系统销售单提交出库成功)自动触发MQ然后再经过数据清洗落到A系统,并将清洗后数据通过特定规则汇总在A系统报表中

现在需要QA同学验证的功能是:

A系统存储数据清洗后的库表(为切片表)有几十个,且前置系统较多,测试工作量也较多

需要核对清洗后A存库数据是否准确

清洗规则:(1)直接取数 (2)拼接取数 (3)映射取数

直接取数字段在2系统表中字段命名规则一致

so,以下测试工具是针对直接取数规则来开发,以便于测试

代码实现步骤:

(1)将表字段,来源系统表和切片表 数据库链接信息,查询字段 作为变量

将这些信息填入input.xlsx 作为入参

(2)读取表字段,根据来源系统表 数据库链接信息,查询字段

查询来源库表,将查询出字段值存储outfbi.xlsx

  (3)读取表字段,根据切片表 数据库链接信息,查询字段

查询切片库表,将查询出字段值存储outods.xlsx

(4)对比outfbi.xlsx,outods.xlsx的字段值

对比后生成result.xlsx文件,新增列校验结果

核对字段值一致校验结果为Success,否则为Fail

代码如下:

入参文件见附件

DbcheckApi.py
import os
import pymysql
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
import datetime
import ast"""测试数据路径管理"""
SCRIPTS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
GENERATECASE_DIR = os.path.join(SCRIPTS_DIR, "dbcheck")
inputDATAS_DIR = os.path.join(GENERATECASE_DIR, "inputdata")
outDATAS_DIR = os.path.join(GENERATECASE_DIR, "outdata")class DbcheckApi():def __init__(self,data):self.inputexcel=dataworkbook = load_workbook(filename=self.inputexcel)sheet = workbook['数据源']# 读取来源表-连接信息sourcedb_connection_info = ast.literal_eval(sheet['B3'].value)odsdb_connection_info = ast.literal_eval(sheet['B4'].value)source_db = sheet['C3'].value.strip()ods_db = sheet['C4'].value.strip()source_queryby = sheet['D3'].value.strip()ods_queryby = sheet['D4'].value.strip()print(sourcedb_connection_info)print(odsdb_connection_info)print(source_db)print(ods_db)print(source_queryby)print(ods_queryby)self.sourcedb = sourcedb_connection_infoself.odsdb = odsdb_connection_infoself.source_db = source_dbself.ods_db = ods_dbself.source_queryby = source_querybyself.ods_queryby = ods_querybydef source_select_db(self):host = self.sourcedb.get('host')port = self.sourcedb.get('port')user = self.sourcedb.get('user')passwd = self.sourcedb.get('passwd')db = self.sourcedb.get('db')if not host or not port or not user or not passwd or not db:error_msg = "连接信息不完整"return {"code": -1, "msg": error_msg, "data": ""}cnnfbi = pymysql.connect(host=host,port=port,user=user,passwd=passwd,db=db)cursor = cnnfbi.cursor()try:# 读取Excel文件df = pd.read_excel(self.inputexcel, sheet_name='Sheet1')# 获取第1列,从第2行开始读取的字段名fields = df.iloc[1:, 0].tolist()print(fields)# 构建查询SQL语句sql = "SELECT {} FROM {} WHERE {}".format(', '.join(fields), self.source_db, self.source_queryby)print(sql)# 执行查询语句cursor.execute(sql)except pymysql.err.OperationalError as e:error_msg = str(e)if "Unknown column" in error_msg:column_name = error_msg.split("'")[1]msg={"code": -1, "msg": f"列字段 {column_name} 在 "+self.source_db+" 表结构中不存在,请检查!", "data": ""}print(msg)return {"code": -1, "msg": f"列字段 {column_name} 在 "+self.source_db+" 表结构中不存在,请检查!", "data": ""}else:return {"code": -1, "msg": error_msg, "data": ""}print(error_msg)# 获取查询结果result = cursor.fetchall()# 关闭游标和连接cursor.close()cnnfbi.close()# 检查查询结果是否为空if not result:return {"code": -1, "msg": f"查询无数据,请检查sql: {sql}", "data": ""}else:# 将结果转换为DataFrame对象df = pd.DataFrame(result, columns=fields)odskey=self.source_db+'表-字段'odsvalue=self.source_db+'表-字段值'# 创建新的DataFrame对象,将字段和对应值放在两列df_new = pd.DataFrame({odskey: fields, odsvalue: df.iloc[0].values})outexcel = os.path.join(outDATAS_DIR,  'outputfbi.xlsx')# 导出结果到Excel文件df_new.to_excel(outexcel, index=False)def ods_select_db(self):host = self.odsdb.get('host')port = self.odsdb.get('port')user = self.odsdb.get('user')passwd = self.odsdb.get('passwd')db = self.odsdb.get('db')if not host or not port or not user or not passwd or not db:raise ValueError("连接信息不完整")cnnfbi = pymysql.connect(host=host,port=port,user=user,passwd=passwd,db=db)cursor = cnnfbi.cursor()try:# 读取Excel文件df = pd.read_excel(self.inputexcel, sheet_name='Sheet1')# 获取第1列,从第2行开始读取的字段名fields = df.iloc[1:, 0].tolist()print(fields)# 构建查询SQL语句sql = "SELECT {} FROM {} WHERE {}".format(', '.join(fields), self.ods_db, self.ods_queryby)print(sql)# 执行查询语句cursor.execute(sql)except pymysql.err.OperationalError as e:error_msg = str(e)if "Unknown column" in error_msg:column_name = error_msg.split("'")[1]return {"code": -1, "msg": f"列 {column_name} 不存在"+self.ods_db+" 表结构中,请检查!", "data": ""}else:return {"code": -1, "msg": error_msg, "data": ""}# 获取查询结果result = cursor.fetchall()# 关闭游标和连接cursor.close()cnnfbi.close()# 将结果转换为DataFrame对象df = pd.DataFrame(result, columns=fields)# 创建新的DataFrame对象,将字段和对应值放在两列odskey=self.ods_db+'表-字段'odsvalue=self.ods_db+'表-字段值'df_new = pd.DataFrame({odskey: fields, odsvalue: df.iloc[0].values})# 导出结果到Excel文件outexcel = os.path.join(outDATAS_DIR,  'outputfms.xlsx')df_new.to_excel(outexcel, index=False)def check_order(self):self.source_select_db()self.ods_select_db()outputfbi = os.path.join(outDATAS_DIR,  'outputfbi.xlsx')outputfms = os.path.join(outDATAS_DIR,  'outputfms.xlsx')df_a = pd.read_excel(outputfbi)df_b = pd.read_excel(outputfms)# 创建新的DataFrame对象用于存储C表的数据df_c = pd.DataFrame()# 将A表的列写入C表for col in df_a.columns:df_c[col] = df_a[col]# 将B表的列���入C表for col in df_b.columns:df_c[col] = df_b[col]odsvalue=self.ods_db+'表-字段值'fbivalue=self.source_db+'表-字段值'# 比对A2和B2列的值,如果不一致,则在第5列写入"校验失败"df_c['校验结果'] = ''for i in range(len(df_c)):if pd.notnull(df_c.at[i, fbivalue]) and pd.notnull(df_c.at[i, odsvalue]):fbivalue_rounded = df_c.at[i, fbivalue]odsvalue_rounded = df_c.at[i, odsvalue]if isinstance(fbivalue_rounded, (int, float)):fbivalue_rounded = round(fbivalue_rounded, 3)elif isinstance(fbivalue_rounded, datetime.datetime):fbivalue_rounded = round(fbivalue_rounded.timestamp(), 3)else:try:fbivalue_rounded = round(float(fbivalue_rounded), 3)except ValueError:passif isinstance(odsvalue_rounded, (int, float)):odsvalue_rounded = round(odsvalue_rounded, 3)elif isinstance(odsvalue_rounded, datetime.datetime):odsvalue_rounded = round(odsvalue_rounded.timestamp(), 3)else:try:odsvalue_rounded = round(float(odsvalue_rounded), 3)except ValueError:passif fbivalue_rounded != odsvalue_rounded:df_c.at[i, '校验结果'] = 'Fail'else:df_c.at[i, '校验结果'] = 'Success'# 将结果写入到C.xlsx文件df_c.to_excel('checkhead_result.xlsx', index=False)# 打开C.xlsx文件并设置背景色book = load_workbook('checkhead_result.xlsx')writer = pd.ExcelWriter('checkhead_result.xlsx', engine='openpyxl')writer.book = book# 获取C.xlsx的工作表sheet_name = 'Sheet1'ws = writer.book[sheet_name]# 设置背景色为红色red_fill = PatternFill(start_color='FFFF0000', end_color='FFFF0000', fill_type='solid')# 遍历校验结果列,将不一致的单元格设置为红色背景for row in ws.iter_rows(min_row=2, min_col=len(df_c.columns), max_row=len(df_c), max_col=len(df_c.columns)):for cell in row:if cell.value == 'Fail':cell.fill = red_fill# 保存Excel文件writer.save()writer.close()if __name__ == '__main__':inputexcel = os.path.join(inputDATAS_DIR,  'input.xlsx')DbcheckApi(inputexcel).check_order()

相关文章:

python测试工具: 实现数据源自动核对

测试业务需要: 现有A系统作为下游数据系统,上游系统有A1,A2,A3... 需要将A1,A2,A3...的数据达到某条件后(比如:A1系统销售单提交出库成功)自动触发MQ然后再经过数据清洗落到A系统,并将清洗后数据通过特定…...

要学习openfoam,c++需要掌握到什么程度?

要学习openfoam,c需要掌握到什么程度? 在开始前我有一些资料,是我根据自己从业十年经验,熬夜搞了几个通宵,精心整理了一份「c的资料从专业入门到高级教程工具包」,点个关注,全部无偿共享给大家&…...

web一些实验代码——Servlet请求与响应

实验4:Servlet请求与响应 1、在页面输入学生学号,从数据库中查询学生信息并显示。 (1)启动MySQL数据库服务,新建数据库,将student.sql文件导入到新建数据库(建立表,并插入3条数据&…...

GPT系列概述

OPENAI做的东西 Openai老窝在爱荷华州,微软投资的数据中心 万物皆可GPT下咱们要失业了? 但是世界不仅仅是GPT GPT其实也只是冰山一角,2022年每4天就有一个大型模型问世 GPT历史时刻 GPT-1 带回到2018年的NLP 所有下游任务都需要微调&#x…...

基于遗传算法的集装箱吊装优化,基于遗传算法的集装箱装卸优化

目录 背影 遗传算法的原理及步骤 基本定义 编码方式 适应度函数 运算过程 代码 结果分析 完整代码下载: 基于遗传算法的集装箱吊装优化,基于遗传算法的集装箱装卸优化(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88674652 背影 …...

postgreSQL单机部署

一、环境准备 架构操作系统IP主机名PG版本端口磁盘空间内存CPUsingle 单机centos7192.168.1.10pgserver01PostgreSQL 14.7543350G4G2 1、官网下载源码包 https://www.postgresql.org/download/2、操作系统参数修改 2.1 sysctl.conf配置 vi /etc/sysctl.conf kernel.sysrq …...

思维逻辑题3

题目1: 如果所有A都是B,且某个对象是B,那么它一定是A吗? 答案:不一定,尽管所有A都是B,但还有其他的对象可能也是B。 题目2: 如果A和B都是真,那么以下哪个选项是真&…...

强大的音乐乐谱控件库

2023 Conmajia, 2018 Ajcek84 SN: 23C.1 本中文翻译已获原作者首肯。 简介 PSAM 控件库——波兰音乐文档系统——是用于显示、排版乐谱的强大 WinForm 库,包含用于绘制乐谱的名为 IncipitViewer 控件,乐谱内容可以从 MusicXml 文件读取,或者…...

数据库——简单查询复杂查询

1.实验内容及原理 1. 在 Windows 系统中安装 VMWare 虚拟机,在 VMWare 中安装 Ubuntu 系统,并在 Ubuntu 中搭建 LAMP 实验环境。 2. 使用 MySQL 进行一些基本操作: (1)登录 MySQL,在 MySQL 中创建用户,…...

java虚拟机内存管理

文章目录 概要一、jdk7与jdk8内存结构的差异二、程序计数器三、虚拟机栈3.1 什么是虚拟机栈3.2 什么是栈帧3.3 栈帧的组成 四、本地方法栈五、堆5.1 堆的特点5.2 堆的结构5.3 堆的参数配置 六、方法区6.1 方法区结构6.2 运行时常量池 七、元空间 概要 根据 JVM 规范&#xff0…...

Hive实战:词频统计

文章目录 一、实战概述二、提出任务三、完成任务(一)准备数据文件1、在虚拟机上创建文本文件2、将文本文件上传到HDFS指定目录 (二)实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、基于HDFS文件创建外部表4、查询单词表&a…...

FairyGUI-Cocos Creator官方Demo源码解读

博主在学习Cocos Creator的时候,发现了一款免费的UI编辑器FairyGUI。这款编辑器的能力十分强大,但是网上的学习资源比较少,坑比较多,主要学习方式就是阅读官方文档和练习官方Demo。这里博主进行官方Demo的解读。 从gitee上克隆项目…...

LabVIEW利用视觉引导机开发器人精准抓取

LabVIEW利用视觉引导机开发器人精准抓取 本项目利用单目视觉技术指导多关节机器人精确抓取三维物体的技术。通过改进传统的相机标定方法,结合LabVIEW平台的Vision Development和Vision Builder forAutomated Inspection组件,优化了摄像系统的标定过程&a…...

【Linux】指令(本人使用比较少的)——笔记(持续更新)

文章目录 ps -axj:查看进程ps -aL:查看线程echo $?:查看最近程序的退出码jobs:查看后台运行的线程组fd 任务号:将后台任务提到前台bg 任务号:将暂停的后台程序重启netstat -nltp:查看服务及监听…...

032 - STM32学习笔记 - TIM基本定时器(一) - 定时器基本知识

032 - STM32学习笔记 - TIM定时器(一) - 基本定时器知识 这节开始学习一下TIM定时器功能,从字面意思上理解,定时器的基本功能就是用来定时,与定时器相结合,可以实现一些周期性的数据发送、采集等功能&#…...

轮廓检测与处理

轮廓检测 先将图像转换成二值 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图 ret, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 变为二值,大于127置为255,小于100置为0.使用cv2.findContours(thresh, cv2.RETR_TREE, cv2.…...

跟着LearnOpenGL学习11--材质

文章目录 一、材质二、设置材质三、光的属性四、不同的光源颜色 一、材质 在现实世界里,每个物体会对光产生不同的反应。 比如,钢制物体看起来通常会比陶土花瓶更闪闪发光,一个木头箱子也不会与一个钢制箱子反射同样程度的光。 有些物体反…...

Java guava partition方法拆分集合自定义集合拆分方法

日常开发中&#xff0c;经常遇到拆分集合处理的场景&#xff0c;现在记录2中拆分集合的方法。 1. 使用Guava包提供的集合操作工具栏 Lists.partition()方法拆分 首先&#xff0c;引入maven依赖 <dependency><groupId>com.google.guava</groupId><artifa…...

GLTF编辑器-位移贴图实现破碎的路面

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 位移贴图是一种可以用于增加模型细节和形状的贴图。它能够在渲染时针…...

多维时序 | MATLAB实现SSA-BiLSTM麻雀算法优化双向长短期记忆神经网络多变量时间序列预测

多维时序 | MATLAB实现SSA-BiLSTM麻雀算法优化双向长短期记忆神经网络多变量时间序列预测 目录 多维时序 | MATLAB实现SSA-BiLSTM麻雀算法优化双向长短期记忆神经网络多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现SSA-BiLSTM麻雀算法优化…...

docker安装Nacos和Rabbitmq

一、安装Nacos 首先需要拉取对应的镜像文件&#xff1a;&#xff08;切换版本加上对应版本号即可&#xff0c;默认最新版&#xff09; docker pull nacos/nacos-server 接着挂载目录&#xff1a; mkdir -p /mydata/nacos/logs/ #新建logs目录 mkdir -p …...

Android MVC 写法

前言 Model&#xff1a;负责数据逻辑 View&#xff1a;负责视图逻辑 Controller&#xff1a;负责业务逻辑 持有关系&#xff1a; 1、View 持有 Controller 2、Controller 持有 Model 3、Model 持有 View 辅助工具&#xff1a;ViewBinding 执行流程&#xff1a;View >…...

网络层解读

基本介绍 概述 当两台主机之间的距离较远(如相隔几十或几百公里&#xff0c;甚至几千公里)时&#xff0c;就需要另一种结构的网络&#xff0c;即广域网。广域网尚无严格的定义。通常是指覆盖范围很广(远超过一个城市的范围)的长距离的单个网络。它由一些结点交换机以及连接这些…...

js for和forEach 跳出循环 替代方案

1 for循环跳出 for(let i0;i<10;i){if(i5){break;}console.log(i) }在函数中也可以return跳出循环 function fn(){for(let i0;i<10;i){if(i5){return;}console.log(i)} } fn()for ... of效果同上 2 forEach循环跳出 break会报错 [1,2,3,4,5,6,7,8,9,10].forEach(i>…...

如何使用ArcGIS Pro自动矢量化建筑

相信你在使用ArcGIS Pro的时候已经发现了一个问题&#xff0c;那就是ArcGIS Pro没有ArcScan&#xff0c;在ArcGIS Pro中&#xff0c;Esri确实已经移除了ArcScan&#xff0c;没有了ArcScan我们如何自动矢量化地图&#xff0c;从地图中提取建筑等要素呢&#xff0c;这里为大家介绍…...

交互式笔记Jupyter Notebook本地部署并实现公网远程访问内网服务器

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下…...

41.坑王驾到第七期:uniapp开发微信小程序引用组件时报错!

一、错误再现 页面login引用了一个组件register&#xff0c;运行至小程序开发工具报错。 xxx.js 已被代码依赖分析忽略&#xff0c;无法被其他模块引用。 二、解决办法 在微信小程序的配置文件中找到setting节点&#xff0c;增加两个配置项。 “ignoreDevUnusedFiles”: fa…...

挂载与解挂载

一. 挂载 1.什么是挂载 将系统中的文件夹和磁盘做上关联&#xff0c;使用文件夹等于使用磁盘 2.mount 2.1 格式 mount [ -t 类型 ] 存储设备 挂载点目录 mount -o loop ISO镜像文件 挂载点目录 注意&#xff1a;指明要挂载的设备 设备文件&#xff1a;例如:/dev/sda5 卷…...

UGUI Panel的显示和隐藏优化

unity UI如何开启&#xff08;显示&#xff09;或者关闭&#xff08;隐藏&#xff09;Panel界面&#xff0c;相信大家都是知道的&#xff0c;但是如何做最好呢&#xff1f; 可能大家一般开启/关闭界面的方法就是直接SetActive吧。这样做通常是可以的&#xff0c;简答快速地解决…...

Linux:多文件编辑

多文件编辑 1.使用vim编辑多个文件 编辑多个文件有两种形式&#xff0c;一种是在进入vim前使用的参数就是多个文件。另一种就是进入vim后再编辑其他的文件。 同时创建两个新文件并编辑 $ vim 1.txt 2.txt默认进入1.txt文件的编辑界面 命令行模式下输入:n编辑2.txt文件&…...

黑龙江省住房和城乡建设厅/网络推广seo教程

两种常用的评价超分的指标:PSNR和SSIM PSNR(Peak Signal-to-Noise Ratio) SSIM&#xff08;Structure Similarity Index&#xff09; 这两个值越高代表重建结果的像素值和标准值越接近&#xff0c;常用的是PSNR。 PSNR&#xff08;Peak Signal to Noise Ratio&#…...

腾讯建站平台官网/百度竞价培训

如何打开文件Stud.txt&#xff0c;然后用"Orange"替换任何出现的"A"&#xff1f; 请(一如既往)遵循一般问题指南&#xff0c;说明任何特殊限制&#xff0c;显示您迄今为止尝试过的内容&#xff0c;并询问具体让您感到困惑的内容。 另外&#xff0c;请用[ho…...

杭州学网站建设/seo怎么做?

整体目标 在这一篇中&#xff0c;我们将使用Jenkins在此基础上构建一条完整的持续交付流水线&#xff0c;并且让团队不同成员能够基于该流水线展开基本的协作。开发&#xff1a; 持续提交代码并能够通过持续集成&#xff08;CI&#xff09;过程快速获取反馈&#xff0c;在通过C…...

web旅游网站开发/网络策划是做什么的

【芝麻代理】请添加链接描述做新媒体运营经常遇到的问题是&#xff0c;我的网站每天都发布新文章&#xff0c;被百度收录的文章却很少&#xff0c;不知道是什么原因&#xff0c;如何让我发布的文章被百度收录&#xff1f;就此问题&#xff0c;个人总结了如下十一条经验&#xf…...

广西高端网站建设公司/百度收录提交工具

1、使用printf应当说是类型不安全的。所以才引入了C的流输入输出。 比如&#xff1a; #include "stdint.h" #include "iostream" using namespace std; int main() { int64_t a 1; int b 2; uint32_t uin 1; printf("%p %p\n", &a, &…...

网站估值/网站功能开发

在我们的日常工作生活中&#xff0c;许多时候需要将手机中的图片文字提取出来&#xff0c;然而很多人都不会&#xff0c;只会照着手打出来&#xff0c;但是这样做不仅效率不高&#xff0c;也很耗时。那么安卓华为手机如何识别图片中的文字&#xff1f;有没有什么快速简单的方法…...