不仅是测试栏目,没有太多的高大上理念,只有一个话题,如何想办法解决你的问题.
从实践中学习,从实践中练习, 这些是领导不会告诉你的

测试人员习惯了别人准备好的环境,别人准备好的数据库,往往一有问题一方面担惊受怕,一方面有抱怨其他组为什么没有做好这些事情,而自己又很少有机会去尝试这些事情,而我刚好有一次小小的机会来进行构建一个测试环境数据库. 不做不知道,做完之后还是有点担惊受怕.

实践让你踩坑,也让你获得新的知识.

1. 缘起,构建测试环境了

由于是小团队,那么一开始就只有两个环境,一个 DEV,一个生产环境,随着规模的扩张,需要搭建一个测试环境,那么测试环境,就需要一个测试数据库.

所以目标很明确,就是:

  1. 复制 DEV 环境的数据库到测试环境
  2. 复制 DEV 环境的数据到测试环境

目前我们使用的是 postgresql 数据库,所以也就是对 postgresql 数据库做以上的操作

2.实施,踩坑记录

把 DEV 环境的数据库复制到一个新的环境,需要做的确实就是:

  1. 复制 DEV 环境的数据库到测试环境
  2. 复制 DEV 环境的数据到测试环境

在操作过程中, 主要遇到的坑:

  1. 直接通过 datagrip 复制数据的方式复制,发现表结构没有完全复制
  2. 通过 airbyte 同步数据的方式,发现表结构没有完全复制,同时还新加了很多字段

2.1 Datagrip 复制表的方式复制

关于使用 airbyte 同步数据的方式就不在这里介绍.主要介绍一下使用复制表方式的数据同步.
下图是通过复制表的方式进行复制,复制结果是表结构数据没有完全复制

  1. 直接选择一个 postgres 的 schema 进行复制

  2. 复制完发现类似表中的一些默认值,sequence,index,key,trigger 等都没有复制完成
    发现数据没有表结构没有复制完全,那是心慌,心慌的,因为:

  3. 一个一个表的去排查那是非常耗时间的,最少有 100 张表

  4. 修改还了知道会不会有删除数据或者需要重新导入,导入数据也很花时间

  5. 但是不管怎么样,至少数据是复制过去了,那么表结构的差别方式怎么来处理呢?
    在研究了半天之后,发现有一个 compare structure 工具,使用 compare structure 工具,可以直接对比表结构差别并且生成 SQL 语句:

直接运行下面的脚本,忽律了一些无关紧要的错误,运行成功了。数据也没有问题,那个心情真是不是一下子能描述的。

以上是一个复制数据和表结构的一个方法,数据量不是海量的情况下速度还是非常快。
然后事情并没有那么简单,突然发现复制过来的表不能插入数据了

2.2 不能插入数据的处理

不能插入数据,主要原因是每一个表的 sequence 从 0 开始的,所以就会发生 id 键冲突的情况?
怎么办,有时 100 多个 sequence,手动更新那会类似. 此时突然想到,python,顺手写一个设置 sequence 的代码,说干就干.

在 postgres 中设置 sequence 可以用如下 SQL:

select setval('calculator.unit_process_snapshot_id_seq'::regclass,max(id)) from unit_process_snapshot;

而一个 schema 的 sequeunce 直接可以复制得到,只要选择所有的 sequence,Ctrl+C 就可以把 sequence 名子全部复制得到
![[sql-sequence.png]]
那这样就是好办了,写一段 python,通过获得的 sequence 名字列表,直接生成更新的 SQL 就可以。

代码怎么写,其实可以很快就能写出来:

  1. 输入是: 类似于: unit_process_snapshot_id_seq 这样一个 sequence 名字
  2. 输出就是: selectsetval('calculator.unit_process_snapshot_id_seq'::regclass,max(id)) from unit_process_snapshot; ```
  3. 其实只要用 python string 的一个 format 方法就可以,string 的模版是: selectsetval('calculator.{}'::regclass,max(id)) from {} 然后简单生成一下表名称,也就是 sequence 去掉_id_seq 就可以生成了,同样这样也就可以批量生成了

最好 python 代码 3 分钟搞定:


seq = """  
activity_answer_id_seq  
task_id_seq  
unit_process_id_seq  
unit_process_snapshot_id_seq  
"""  


def generate_postgre_seqs(schema_name:str,seqs: str):  
    all_seq = seqs.split("\n")  
    result = []  
    for item in all_seq:  
        if len(item) > 1:  
            result.append(generate_postgres_seq(schema_name,item))  
    return result  


def generate_postgres_seq(schema_name:str,seq_name: str, table_name: str = None) -> str:  
    temp = 'select setval(\'{}.{}\'::regclass,max(id)) from {};'  
    if table_name is None:  
        table_name = seq_name.replace("_id_seq","")  
    return temp.format(schema_name,seq_name, table_name)  


def test_seq():  
    print(seq)  
    result = generate_postgre_seqs("calculator",seq)  
    for item in result:  
        print(item)

一个批量生成更新数据库 sequence 的脚本就这样完成了,把数据结果在数据库中执行,sequence 问题也就搞定了,100 多个 sequence 一转眼就完成了.

小结

通过以上的一个小例子,用了一些工具,辅助一些简单脚本,就可以把一件看起来很麻烦的事情解决了. 我们回顾一下做了什么事情:

  1. Datagrip 复制表数据,发现数据库的表结构没有完全复制
  2. Datagrip 通过构 Compare Structure 方式,完全同步表结构,并且不影响数据
  3. 通过一段 python 脚本,生成修改数据库 sequence 的代码,直接运行就把 sequence 同时改掉

文章同步发布在微信公众号: Datagrip/python 使用快速构建测试环境数据库


↙↙↙阅读原文可查看相关链接,并与作者交流