通用技术 造数 - 我的理解与落地实践

Kilmer · 2022年12月12日 · 最后由 Kilmer 回复于 2023年01月31日 · 14286 次阅读
本帖已被设为精华帖!

“造数工厂” 是什么?

理解思考造数工厂是什么之前,我们先需要搞清楚业务功能(前端、服务,数据)之间的关系

在业务系统中,业务数据一般由用户发起业务流程产生,也就是由功能产生,这是所谓的正向数据流,例如 “新建” 相关的功能。而产生的数据为后续的业务功能提供基础支撑,例如 “查询”,“更新”,“内存运算” 等,这是所谓的逆向数据流。用户的操作产生数据,产生的数据根据业务要求进行一系列的操作和加工又反馈给用户。所以在业务系统中,我们可以把功能划分为三大类:

  1. 产生数据的功能
  2. 使用数据的功能
  3. 产生和使用数据的功能

通过上图可以看到:

  1. 功能 A 类似 “新建” 或 “数据接入” 的功能,纯产生数据。
  2. 功能 B,功能 C 类似 “编辑”,“删除” 的功能,使用其他功能产生的数据,并进行操作数据进行增、删、改。
  3. 功能 D 类似 “查询” 的功能,对已经存在数据根据业务要求进行查询,聚合,内存运算,当然这种功能业务产生数据,但这些数据都是存放在内存中,并不会持久化下来,一定时间后会被清理掉。 通过上图也可以看出一些基本常识,在业务系统中功能和功能之间、数据和数据之间,功能和数据之间存在依赖。 正是这个 “依赖” 为 “造数工厂” 的定义提供了有效的参考。我个人理解造数工厂是一种在软件生产过程中为功能直接快速提供业务数据支撑,缩短业务链路,丰富数据样本的能效工具。在文章后续的内容中,会围绕这个定义进行展开。

为什么生产过程中需要类似 “造数工厂” 工具的存在?意义是什么?

我们站在开发、测试两个角色去看待这个问题。

开发:

  1. 又要联调了,开发环境没有支撑联调的数据啊?
  2. 开发 A:“我的功能要依赖开发 B 负责的功能产生的数据,我不是很了解,开发 B 你帮我弄一下呗”。 开发 B:“我没时间哦,我还要搞其他需求”。
  3. 联调过程中, 前端开发:“接口 500,后端看一下” 后端开发:“数据缺失了,我补一下,你再看看” 前端开发:“接口还是 500,后端看一下” 后端开发:“数据还有缺失了,我补一下,你再看看” 前端开发:“接口依然 500,后端看一下” 后端开发:“数据怎么还有缺失啊,那个后端开发,你帮我看看” 10 分钟过去了,接口还没 200

现在很多微服务基于 DDD,后端开发各自专注于自己的领域中,对依赖服务的内部逻辑和数据结果并不关注,只关注交互接口提供的数据结构和含义。这就导致了很明显的问题,开发环境进行联调时,花费大量时间在依赖数据的构造中,效率极低。

测试:

  1. 我的目标测试对象是功能 X,但是功能 X 依赖其他功能路径和对应的数据,难道我一定要把其他功能路径跑一遍后,我才能测功能 X?

如果测试人员在迭代中为了生成目标功能依赖的业务数据,而去把代码未发生任何变动的功能都跑一遍,这种方式是低效率无意义的。在整个测试过程中,只有阶段 2 才是有效的测试。

如果有造数工厂,你的工作流程会变更为:

你可以在测试设计阶段中,在造数工厂中将你测试过程中需要的数据先准保好,在测试开始的时候直接在造数工厂中生成依赖的业务数据就好。

  1. 我的 UI 自动化测试用例,接口自动化测试用例都需要非常多的前置条件,搞得我的脚本内容好多,维护成本大大提升题。

在自动化测试的实践过程中,以下问题会阻碍自动化测试落地:
* 用例和用例之间不独立,依赖严重
* 测试点小、用例大
* 维护脚本成本大
这三个问题背后的原因很大层度都是被 “测试场景构建” 的问题影响:
* 下一个测试用例的测试场景构建,依赖上一个测试用例的执行
* 为了构造测试场景,不得不做很多额外的操作,导致脚本步骤增多,从而导致整个自动化测试的稳定性下降
* 用例无效内容多,不同用例关联关系紧密,与测试点无关的功能变动有可能也会导致用例运行失败
通过造数工厂的能力,将自动化测试脚本强依赖的测试场景构建从自动化测试本身抽离出来,自动化测试的用例只需要调用造数工厂进行测试场景构建。从而解决以上三个问题。

“造数工厂” 应该具备哪些核心能力

  • 数据源管理能力
    • 用能依赖的数据可能来源于不同的数据源,例如:Mysql、Clickhouse、Redis、ES 等,因此需要支持不同数据源的造数。
  • 业务系统中常用、通用数据抽象能力
    • 多种造数过程中会使用到相同的数据内容,因此这些数据需要抽象出来,可以复用在不同的造数过程中。
  • 造数逻辑编写、组织能力
    • 我们采用自行编写语言的方式对造数过程进行设计,并对造数过程中依赖的内容进行组织和管理。
  • 造数过程中中间数据记录和传递能力
    • 造数过程中,步骤和步骤直接需要数据的传递,因此造数过程中需要具备保存、记录中间数据的能力。
  • 造数过程随意在开发、测试环境切换的能力
    • 同一个造数过程可以在不同的环境中使用,相同功能的数据不需要在不同的环境中都具备造数过程。
  • 造数过程拼搭能力
    • 不同的造数过程可以随意的拼搭,组织,这样可以保证造数过程在不同功能中的复用。

我的 “造数工厂” 核心功能长啥样

  • 数据源管理: 新建数据源,目前支持 mysql,kafka,mq

新建 kafka 数据源

新建 MQ 数据源

新建 Mysql 数据源:

在数据源管理页面中你可以创建、编辑、查询你造数流程中会使用到数据源。

  • 通用数据抽象:变量管理 变量采用 json 格式进行编写,保存,方便在造数过程中的使用

新建/编辑变量:

我们使用 codemirror6 的组件编写 json 的编辑器,并且在编辑器中提供了一些使用函数

函数在编辑器中会自行提醒并补全

有时候,一个变量 json 内容会非常多,在当前看到编辑器中编写不是很方便,因此我们提供一个放大功能,就是标题旁边那个蓝色的小按钮

在当前这个纯净的编辑窗口中编写就会非常的舒服啦

  • 造数逻辑编写、组织能力 #### 新建消息模板

消息模板采用 JSON 格式进行编写,主要针对业务系统通过消息通道(KAFKA,MQ)接收上游业务系统推数后产生业务数据的造数。这样在测试过程中,就不需要依赖上游业务系统的推送,我们自己按照约定编写业务消息,进行推数验证我们自己业务系统处理消息的业务逻辑就行。

消息模板列表页面

通过消息模板的列表页面对存量的消息模板进行维护

新建数据模板

处理针对消息队列的消息模板外,我们还提供了针对 Mysql、ClickHouse 的数据模板

在一个数据模板中,可以有多个步骤:

通过添加按钮添加步骤,删除按钮删除步骤;

每个步骤都对应一个数据源,因为一个功能依赖的数据可能来自不同的数据源;

每个步骤都可以拥有他自己的变量,可以是多个。

在数据模板中使用变量

先为当前步骤选择变量,再编写 SQL 语句的时候可以直接引用

编写 SQL 的时候,变量的内容不需要手动编写,编辑器会为你做代码提示

同样 SQL 的编辑器也提供了纯净编写的功能,并且两个不同的编写器的内容相互同步

  • 造数过程中中间数据记录和传递能力 在数据模板中使用上下文,在造数过程中,下一个步骤可能会使用到上一个步骤产生的内容,因此我们设计了给步骤添加上下文的功能,当前步骤产生的结果数据会存放在指定的上下文中,后续的步骤可以到指定的地方获取上下文中需要的数据。

  • 造数过程拼搭能力 一个造数过程可以是多个数据模板和多个消息模板组成,因此我们抽象除了,工人和生产线的概念,在这两个概念上,数据模板和消息模板就变成具体的工作内容,而模板中的步骤则变成了具体的工作细节。

在一个工人中可以设置多个数据模板,他们的序号就是他们工作的顺序,模板中的上下文作用域只能在当前模板中,不能跨模板使用。

同理一个生产线中也可以有多个工人,他们的需要就是工人之间的工作顺序。

这样通过在工人中设置数据模板和消息模板,在生产线中设置工人并实现了造数过程中的拼搭能力。

综上所述,我们可以看到整个造数过程中数据结构的层级关系是:

所以按照上述内容,为了使你的造数可用性,复用性更高,应该尽量做到以下几点:

  1. 尽可能的将通用数据抽象成变量维护
  2. 数据模板和消息模板中的步骤尽可能的不要太多,方便模板在不同工人中的复用
  3. 工人中的数据模板和消息模板尽可能的不要太多,方便工人在不同生产线中的复用

当前在项目中的落地情况

因为我们业务系统属于数据密集型系统,无论是后端和前端在开发环境中联调,还是测试执行过程中的提效,自动化测试中场景的构建,对造数工厂都有强烈的需求。目前在项目中已经使用起来,切实帮助测试解决了很大的问题,提升了测试效率,特别是数据模板和消息模板积累起来后,使用效率和带来的效果越来越大。

后续功能:

  1. 数据模板中,将消息模板,ClickHouse 打通,在一个消息模板中往 Mysql 中造数的同时也可以往消息队列中发送消息,也可以往 ClickHouse 中造数。在一个数据模板中支持多种数据源。
  2. 上下文可以跨数据模板使用。
  3. 新增工作空间,不同的登录用户具备自己的工作空间。
最佳回复

功能设计的挺好,这也是我一直想做但是没做的东西,之前也设计过这块,但是苦于一直没机会开发,我分享下我自己对数据工厂/造数工厂的一些功能的想法:
1、可以新建不同的数据池(主要用于不同的测试场景,包括功能测试业务场景,自动化测试集,性能测试等),定义自己需要的字段,支持 string,file 类型,这个有点类似数据库的表;
2、针对这个数据池,配置池中数据的造数规则/策略,比如:池中数据量的最大最小值,满足何种条件时自动触发数据生成,定时触发生成策略以及池数据扫描的时间间隔等;
3、针对这个池子,可配置不同的测试环境,每个环境中的造数详细规则不相同(主要用于同个业务测试会在不同环境下执行);
4、创建造数步骤,支持生成,还原,销毁,预处理这些类型的步骤,每种类型的步骤适用的场景不同,根据字面意思能够理解,比如生成就是生成测试数据,预处理就是数据提供给别人之前的处理操作;
5、针对不同类型的造数步骤,编写详细的步骤操作,提供尽可能多的方式来方便用户去处理数据(这里的处理包括生成,还原,销毁,预处理等操作),比如 groory 脚本执行器,MOCKJS,数据库 SQL 执行器,HTTP 请求器,JSON 提取器等,用户也可以自己上传 jar 包来编写造数策略;
6、除了上面自动化的造数策略,也支持手动新增,excel 上传等操作来增加池中的数据,支持批量下载导出不同格式的文件用于支持自动化测试(properties),性能测试 (csv),开发测试 (json) 等,也可以手动触发生成,还原,销毁等策略;
7、与其他自动化模块以及第三方系统的集成使用,在本系统内部,应该可以方便在其他模块快速引用池中数据,自动化测试执行时,自动向数据池索要数据,数据池自行根据策略来判断是否需要触发造数规则;针对第三方系统也要提供方便快捷的接口以供调用;
8、支持给功能测试提供页面也快速查询到自己测试业务要使用到的数据,支持给性能测试提供大批量造数,以及导出能力;

共收到 17 条回复 时间 点赞

优秀~

提两个小建议:

  1. 是否可以根据业务接口来造数据,从上面的介绍看,主要还是依赖于手写数据,这就对测试人需要对对应的表结构或者 MQ 的报文结构非常熟悉才可以做到,特别是上下文依赖。比较容易出错,通过接口调用会好些。

  2. 造出来的数据,如何与测试脚本关联起来?需要使用人员再去查询一次么?

造数确实是测试活动中非常重要的痛点,希望看到更多优秀的解决方案。

很优秀,但是存在相当程度的上手成本,建议可以在易用性方面再补充做考虑,1.是否可以将数据模板固化下来,因为对于一般测试同学,可能只需要存在某种类型的数据,而不是每种数据都需要自己进行配置

CKL的思考 回复

接口当然也是可以的,但是接口存在以下问题:

1、接口分上层接口和底层原子接口,例如在微服务领域模型下,bff 层通常提供的是业务聚合接口,如果使用这种接口造数,那么接口本身对其他业务数据会有依赖,会导致接口依赖接口的情况。

2、如果是底层原子接口,通常并不会在网络上暴露,服务和服务直接通常都是通过走服务发现的方式相互调用和依赖,如果为了测试需要暴露大量底层接口,可能开发层面也不是特别的方便。

关于怎么和测试脚本关联起来的问题,我把你说的测试脚本理解成自动化相关的脚本
在文章中有提到生产线的概念,每个生产线都有对应的 id,造数工厂提供了一个对外调用的 API,可以传入对应的生产线 id 和验签参数,这样在你的脚本的 methd setup 方法中直接调用对应生产线来生产你测试脚本依赖的场景数据。

😀

沫沫sir 回复

我觉的你说的很正确。

之所以我在实践过程中构造出了 “变量” 这个功能,目的其实就是将通用、常用的数据抽离出来。数据模板只是一个架子,在生产数据的过程中,通过变量往架子中填充数据,后期数据层面有说变动,只需要改变对应变量中的内容。

数据模板是固化下来的,但是这个固化会有一个过程,其实是一个滚雪球的过程,伴随项目迭代的时间越长,用的人越多,数据模板会越来越多,到时候测试人员之间只需要分享各自的数据模板和变量就行。

功能设计的挺好,这也是我一直想做但是没做的东西,之前也设计过这块,但是苦于一直没机会开发,我分享下我自己对数据工厂/造数工厂的一些功能的想法:
1、可以新建不同的数据池(主要用于不同的测试场景,包括功能测试业务场景,自动化测试集,性能测试等),定义自己需要的字段,支持 string,file 类型,这个有点类似数据库的表;
2、针对这个数据池,配置池中数据的造数规则/策略,比如:池中数据量的最大最小值,满足何种条件时自动触发数据生成,定时触发生成策略以及池数据扫描的时间间隔等;
3、针对这个池子,可配置不同的测试环境,每个环境中的造数详细规则不相同(主要用于同个业务测试会在不同环境下执行);
4、创建造数步骤,支持生成,还原,销毁,预处理这些类型的步骤,每种类型的步骤适用的场景不同,根据字面意思能够理解,比如生成就是生成测试数据,预处理就是数据提供给别人之前的处理操作;
5、针对不同类型的造数步骤,编写详细的步骤操作,提供尽可能多的方式来方便用户去处理数据(这里的处理包括生成,还原,销毁,预处理等操作),比如 groory 脚本执行器,MOCKJS,数据库 SQL 执行器,HTTP 请求器,JSON 提取器等,用户也可以自己上传 jar 包来编写造数策略;
6、除了上面自动化的造数策略,也支持手动新增,excel 上传等操作来增加池中的数据,支持批量下载导出不同格式的文件用于支持自动化测试(properties),性能测试 (csv),开发测试 (json) 等,也可以手动触发生成,还原,销毁等策略;
7、与其他自动化模块以及第三方系统的集成使用,在本系统内部,应该可以方便在其他模块快速引用池中数据,自动化测试执行时,自动向数据池索要数据,数据池自行根据策略来判断是否需要触发造数规则;针对第三方系统也要提供方便快捷的接口以供调用;
8、支持给功能测试提供页面也快速查询到自己测试业务要使用到的数据,支持给性能测试提供大批量造数,以及导出能力;

徐汪成 回复

我觉得你的提议很好,和我的规划有不谋而合的地方:

针对 “数据池”:
在现有的功能的中"变量"其实就是狭义的 “数据池”。
但我理解配合 “数据池” 的概念中还需要有两部分内容 “数据结构定义” 和 “使用策略”
在功能层面的理解更类似下图

徐汪成 回复

针对第 4 点的内容:

在现在的设计中其实已经体现了:
1、数据模板中可以存在多个步骤,每个步骤根据真实情况设置具体的内容,可以是纯生成,可以是还原,等等
2、一个数据工人中可以有多个数据模板,一个生产线中可以有多个功能。随意拼搭。

但在我的规划中其实还是希望在数据模板中的多个步骤之间存在语义逻辑处理,可以简单的理解为:if else 或 for 。这样可以更加灵活的处理造数过程中的逻辑

如果想在项目中普及,建议是可以能够让测试上手成本降低,因为很多测试构造数据的目的是为了快速且符合测试要求,如果上手成本过高,可能会觉得是不是我自己写一个适合自己使用的构造数据的 python 或者 shell 脚本就足够了,还有模板的问题,老实说我们自己项目就是用了类似的技术,但是上传模板需要太多步骤,导致实际在测试中使用的人很少

因为我理解的这个平台主要的受众其实是功能测试的测试群体,实际开发或者其他测开可能有更好构造数据的方法,你凭什么让他们都来使用,上手成本低易学习我想是一个比较大的亮点

Kilmer 回复

这个逻辑方面我确实没有考虑到,可能但是更多的是希望在脚本里面对数据进行精细的处理,其他类似数据库查询,接口查询等只是抓取数据的方式,最后加工出来的数据是符合数据池数据结构的还是想依靠脚本去处理的。

我觉得 8/9 楼这个说的很正确,怎么降低上手门槛,让不同类型的测试人员,包括开发人员都能够去使用它,比如功能测试人员可能技术能力较弱,人家可能会先从数据库查询一批数据,然后通过文件导入这种方式,自动化测试人员可能会使用 SQL 语句去查询,性能测试人员可能会使用模板造数(因为需要大量数据),开发人员可能就直接写 jar 包或者写脚本了。所以在构造数据这块,要提供尽可能多的方式以对应不同类型的使用者。这样对平台的推广比较重要。
另外就是与功能测试,自动化测试,性能测试,开发调试要更加无缝的集成使用,无需其他繁琐的操作就能享受造数工厂提供的能力,比如自动化脚本不管是平台化还是没有平台化,都能通过简单的方式接入造数工厂,开发在自己的单元用例中,是否可以通过引入你们提供的 SDK 快速接入造数工厂,这块都可以研究下。

徐汪成 回复

是的,易用性在一定程度上面需要提升,我也在考虑提供 SDK 来方便其他框架的调用

Kilmer #13 · 2022年12月16日 Author

@Lihuazhang 申请加个精

49875183 将本帖设为了精华贴 12月16日 14:48

楼主,文章中的图片好模糊呀~ 看着好难受。。。

我的造数平台界面,
我是一个不喜欢思考的人,一个产品如果需要我做太多的思考,我会放弃使用
也不喜欢别人用我的产品还需要动用智力

跟我开源的数据工厂,方向不大一样,我的更注重业务接口来造数据
https://testerhome.com/topics/34512

达峰的夏天 Macaca DataHub 4.0 - 体验功能全新升级 中提及了此贴 01月28日 14:19
Kilmer #19 · 2023年01月31日 Author

使用接口造数也可以,但有几个问题:

1、你使用的是上层业务结构,还是底层原子接口

2、一个业务场景的数据会涉及到多个结构,因此一个业务场景的造数,使用接口的话,会有多个接口的调用顺序与上下文管理的问题

3、如果造数在中途失败,产生的 “半截” 脏数据应该如何处理

5、接口造数,那么接口的参数如何管理和动态更新维护。

欢迎和我探讨~

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册