找回密码
 会员注册
查看: 17|回复: 0

数据下载重构项目测试总结

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64021
发表于 2024-10-12 00:50:58 | 显示全部楼层 |阅读模式
背景最近收到了一个数据下载重构的测试需求,数据指标大概有400多个,其中包含一些简单指标(数据库透传)以及复杂指标(需要计算的),测试过程需要我们将指标以csv的形式下载下来,逐一验证指标的准确性。本文将对数据下载重构项目测试过程中的测试计划和效率化方案展开介绍。测试计划对于重构的项目,脑海中第一个想法就是跟老版本进行对比。鉴于重构之后的项目和历史的数据源不一致,测试环境两个数据源的数据没有打通,将两个版本进行对比意义不大,所以将新老版本对比工作放到了线上验证阶段。测试过程中最大的工作量是需要逐一验证字段的准确性,纯手工验证暴露如下问题:①. 文件较大,打开耗时,卡顿,影响验证效率②. 指标多、数据量大,只能通过抽样验证,无法保证验证的全面性基于以上两点,在测试环境,我们采用了自动化验证的方案,基于pytest框架,具体方案将在其他文章中展开,本文不做详述。在线上验证过程中,由于新老版本数据源以及数据范围的差异性,会导致新老版本的部分数据无法一一对应,基于这个问题我们将线上回归拆分为两个环节:①. 字段准确性:新老版本数据对比,保证共有记录字段的准确性②. 整体-对比总值:如果某一列值是数据类型,就纵向加和,与数据库总值进行比较;如果是非数值,统计各个取值出现的频率,跟数据库结果进行比对,保证整体的准确性。接下来将针对字段准确性环节用到的新老版本对比的自动化脚本进行详细讲解。对比脚本方案演进两个csv文件对比,需要将一个作为基础文件(后面统称“base文件”),另一个作为对比文件。遍历对比文件,到base文件中找到对应的记录,逐一比较对应的列值。因为顺序是随机的,所以将账户id作为对比的key值,具体步骤如下:01将两个csv文件转换成字典:将账户id列作为key值、其它列值作为value02从对比文件dict取出一行,获取key03去base文件的dict判断是否存在key,如果存在,取出来,计算处理+对比各个列值,如果都相等,则pass,否则,将错误信息打印出来04如果上一步不存在,直接打印错误信息电脑配置:● windows10操作系统● 8核CPU● 20G内存文件量级:20W(base文件) VS 20W(对比文件)01单进程直接写日志为了使运行结果看起来更加直观,第一个版本设计的时候引入了Python的日志组件loguru来打印过程数据。核心代码如下:为了清楚了解循环进度以及准确定位,加了较多日志,可以看到,每个循环都会去写日志。运行结束大概需要40多分钟,时间略长,排查了一下发现频繁写日志文件非常影响效率,所以接下来的版本采用集中写文件替换掉了日志模块。02单进程汇总写日志基于上一个版本的问题,做了两点改进:①. 去掉了无用的日志输出②. 将错误信息存储到error_list,运行结束之后统一将error_list写入文件,便于查看结果代码如下:运行结果:运行时间大概20分钟左右,运行效率翻了一倍,但是作为线上验证环节,我们还希望更快一些,接下来我们尝试一下并发策略。03并发-汇总写日志提到并发,就会想到线程和进程,线程与进程是操作系统里面的术语,简单来讲,每一个应用程序都有一个自己的进程。操作系统会为这些进程分配一些执行资源,例如内存空间等。在进程中,又可以创建一些线程,他们共享这些内存空间,并由操作系统调用,以便并行计算。进程是资源分配的最小单位,线程是程序执行的最小单位。相比进程,线程更加轻量,资源利用率高,且创建销毁更快。综上所述,优先选择Python的多线程方案。将对比文件通过numpy进行分块,分发给各个线程。核心代码如下:运行结果如下:从运行结果上看,并没有明显的加速效果,原因是因为Python的GIL(解释器全局锁)机制。不同线程同时访问资源时,需要使用保护机制,Python中使用GIL(解释器全局锁)。直观上,这是一个加在解释器上的全局(从解释器的角度看)锁。这意味着对于任何Python程序,不管有多少的处理器,任何时候都总是只有一个线程在执行。所以,在我们脚本几乎没有IO操作的情况下,python中的多线程并没有明显的优势。接下来我们看一下多进程的方案:● 使用Python第三方库numpy将对比文件的dict进行分块● 将分块的dict以及base文件的dict分发给各个进程行后续计算代码如下:运行结果:在文件大小不是特别大的情况下,加速效果明显:运行时间较之前缩短了一倍,大概10分钟以内就可以完成。但并不是所有量级的文件对比都有这种加速效果。受电脑资源的限制,当文件大小超过一定的体量以后(比如csv100多万条记录),每个进程都要创建自己独立的资源,进程所需内存的大小也变得很大,所以进程启动变得缓慢,甚至一个进程运行结束,另外一个进程还没有启动,效率不如预期。04共享内存-并发-汇总写日志我们看一个大文件的例子:文件量级:100W VS 100W单个进程运行的结果:多进程运行的结果:从日志结果可以看出,四个进程并没有实现并发的效果,因为base文件过大,每一个进程都需要为base文件创建所需的内存空间,进程占用内存大,导致进程启动缓慢。为了缓解进程空间过大的问题,尝试了Python中共享内存的方案,因为需要共享的字典较大,所以选择了mutiprocess 中的Manager类,Manager是一种较为高级的多进程通信方式,它能支持Python支持的任何数据结构。它的原理是:先启动一个ManagerServer进程,这个进程是阻塞的,它监听一个socket,然后其他进程(ManagerClient)通过socket来连接到ManagerServer,实现通信。使用了manager共享内存的代码如下:将较大的base文件的dict放入共享空间,进程无需再单独分配相关的空间,解决了资源较大的进程启动慢的问题,运行结果如下:从运行结果可以看出,进程是并行启动运行的,运行效率较单进程和非共享内存的多进程都有了显著的提升。另外,这里也可以将base文件和对比文件同时放入共享空间,感兴趣的同学可以实践一下。总结01在任务是计算密集型、小内存消耗的情况下,可以选用多进程提升运行效率02在任务是计算密集型、高内存消耗的情况下,可以将大块数据进行分割,如果无法分割,可以尝试共享内存的方案解决多进程启动慢的情况03多进程的情况下,频繁写日志会降低程序的运行效率,采用集中写日志可以有效缓解问题。另外,日志要尽可能的精简,去除冗余本文主要介绍了数据下载重构项目测试计划以及效率化方面的内容,希望能给大家在日常测试中提供一些测试的思路,有不合理或者可以优化的地方欢迎交流指正。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 00:27 , Processed in 0.972127 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表