如何 运行 Postgres 与 NodeJS、Jest 和 Knex 并行测试?
How to run Postgres tests in parallel with NodeJS, Jest and Knex?
我有一个项目是在 production/staging 中使用 Postgres 开发的,在开发中使用 Sqlite。使用 Sqlite,我们能够 运行 在 13 秒内并行完成所有测试。
这对于最初的开发来说是一个很好的策略,但是 Sqlite 不能做我们需要的一些事情(例如删除列和添加新的外键)。所以我认为我们应该放弃 Sqlite 而只使用 Postgres。
测试套件大约需要一分钟 运行,如果测试失败,我通常必须手动删除迁移表。它没有提供良好的测试体验。
对于使用 NodeJS、Knex 和 Jest 在 Postgres 数据库上进行并行测试,您有什么建议吗?
运行 迁移并在每次测试之前回滚它们真的很慢,甚至可能需要几秒钟才能 运行。因此,您可能不需要 运行 并行测试即可达到足够快的速度。
如果您设置测试的方式是在开始 运行 测试之前删除/创建/迁移一次,并且在测试之间只是 t运行cate 表中的所有数据并填充它对于新数据,它应该快 10 倍(t运行cate 通常需要不到 50 毫秒)。您可以 运行 轻松地分类所有表格,例如使用 knex-db-manager
包。
如果你真的喜欢 运行 postgresql 并行测试,你需要的测试数据库与你正在 运行 进行的并行测试一样多。您可以创建 "pool" 个测试数据库(testdb-1、testdb-2、testdb-3,...),并且在每个玩笑测试中,您首先必须从测试数据库池中请求数据库,这样您才能真正 运行 同时进行多项测试,它们不会干扰同一个数据库。
最后一种在测试数据库中重置数据的更快速的方法是使用 pg-dump
/ pg-restore
和二进制数据库转储。在某些情况下,它可能比 运行ning 填充脚本处理起来更快或更容易。特别是在您在每个测试中使用相同初始数据的情况下。
通过这种方式,您可以在开始 运行 测试并转储它之前为测试数据库创建初始状态。为了转储和恢复,我写了这些小帮手,我可能会在某个时候添加到 knex-db-manager
。
转储/恢复参数有点棘手(特别是设置密码)所以这些片段可能会有所帮助:
倾销:
shelljs.env.PGPASSWORD = config.knex.connection.password;
const leCommand = [
`pg_dump -a -O -x -F c`,
`-f '${dumpFileName}'`,
`-d ${config.knex.connection.database}`,
`-h ${config.knex.connection.host}`,
`-p ${config.knex.connection.port}`,
`-U ${config.knex.connection.user}`,
].join(' ');
console.log('>>>>>>>> Command started:', leCommand);
shelljs.rm('-f', dumpFileName);
shelljs.exec(leCommand, (code, stdout, stderr) => {
console.log('======= Command ready:', leCommand, 'with exit code:', code);
if (code === 0) {
console.log('dump ready:', stdout);
} else {
console.log('dump failed:', stderr);
}
});
恢复:
shelljs.env.PGPASSWORD = config.knex.connection.password;
const leCommand = [
`pg_restore -a -O -x -F c`,
`-d ${config.knex.connection.database}`,
`-h ${config.knex.connection.host}`,
`-p ${config.knex.connection.port}`,
`-U ${config.knex.connection.user}`,
`--disable-triggers`,
`'${dumpFileName}'`,
].join(' ');
console.log('>>>>>>>> Command started:', leCommand);
shelljs.exec(leCommand, (code, stdout, stderr) => {
console.log('======= Command ready:', leCommand, 'with exit code:', code);
if (code === 0) {
console.log('restore ready:', stdout);
} else {
console.log('restore failed:', stderr);
}
});
我有一个项目是在 production/staging 中使用 Postgres 开发的,在开发中使用 Sqlite。使用 Sqlite,我们能够 运行 在 13 秒内并行完成所有测试。
这对于最初的开发来说是一个很好的策略,但是 Sqlite 不能做我们需要的一些事情(例如删除列和添加新的外键)。所以我认为我们应该放弃 Sqlite 而只使用 Postgres。
测试套件大约需要一分钟 运行,如果测试失败,我通常必须手动删除迁移表。它没有提供良好的测试体验。
对于使用 NodeJS、Knex 和 Jest 在 Postgres 数据库上进行并行测试,您有什么建议吗?
运行 迁移并在每次测试之前回滚它们真的很慢,甚至可能需要几秒钟才能 运行。因此,您可能不需要 运行 并行测试即可达到足够快的速度。
如果您设置测试的方式是在开始 运行 测试之前删除/创建/迁移一次,并且在测试之间只是 t运行cate 表中的所有数据并填充它对于新数据,它应该快 10 倍(t运行cate 通常需要不到 50 毫秒)。您可以 运行 轻松地分类所有表格,例如使用 knex-db-manager
包。
如果你真的喜欢 运行 postgresql 并行测试,你需要的测试数据库与你正在 运行 进行的并行测试一样多。您可以创建 "pool" 个测试数据库(testdb-1、testdb-2、testdb-3,...),并且在每个玩笑测试中,您首先必须从测试数据库池中请求数据库,这样您才能真正 运行 同时进行多项测试,它们不会干扰同一个数据库。
最后一种在测试数据库中重置数据的更快速的方法是使用 pg-dump
/ pg-restore
和二进制数据库转储。在某些情况下,它可能比 运行ning 填充脚本处理起来更快或更容易。特别是在您在每个测试中使用相同初始数据的情况下。
通过这种方式,您可以在开始 运行 测试并转储它之前为测试数据库创建初始状态。为了转储和恢复,我写了这些小帮手,我可能会在某个时候添加到 knex-db-manager
。
转储/恢复参数有点棘手(特别是设置密码)所以这些片段可能会有所帮助:
倾销:
shelljs.env.PGPASSWORD = config.knex.connection.password;
const leCommand = [
`pg_dump -a -O -x -F c`,
`-f '${dumpFileName}'`,
`-d ${config.knex.connection.database}`,
`-h ${config.knex.connection.host}`,
`-p ${config.knex.connection.port}`,
`-U ${config.knex.connection.user}`,
].join(' ');
console.log('>>>>>>>> Command started:', leCommand);
shelljs.rm('-f', dumpFileName);
shelljs.exec(leCommand, (code, stdout, stderr) => {
console.log('======= Command ready:', leCommand, 'with exit code:', code);
if (code === 0) {
console.log('dump ready:', stdout);
} else {
console.log('dump failed:', stderr);
}
});
恢复:
shelljs.env.PGPASSWORD = config.knex.connection.password;
const leCommand = [
`pg_restore -a -O -x -F c`,
`-d ${config.knex.connection.database}`,
`-h ${config.knex.connection.host}`,
`-p ${config.knex.connection.port}`,
`-U ${config.knex.connection.user}`,
`--disable-triggers`,
`'${dumpFileName}'`,
].join(' ');
console.log('>>>>>>>> Command started:', leCommand);
shelljs.exec(leCommand, (code, stdout, stderr) => {
console.log('======= Command ready:', leCommand, 'with exit code:', code);
if (code === 0) {
console.log('restore ready:', stdout);
} else {
console.log('restore failed:', stderr);
}
});