【问题标题】:How to run Postgres tests in parallel with NodeJS, Jest and Knex?如何与 NodeJS、Jest 和 Knex 并行运行 Postgres 测试?
【发布时间】:2018-04-28 20:46:36
【问题描述】:

我有一个项目是在生产/登台中使用 Postgres 和在开发中使用 Sqlite 开发的。使用 Sqlite,我们能够在 13 秒内并行运行所有测试。

这对于最初的开发来说是一个很好的策略,但是有些事情是 Sqlite 无法做到的(例如,删除列和添加新的外键)。所以我认为我们应该放弃 Sqlite 并只使用 Postgres。

测试套件运行大约需要一分钟,如果测试失败,我通常必须手动删除迁移表。它不能提供良好的测试体验。

您对使用 NodeJS、Knex 和 Jest 在 Postgres 数据库上并行运行测试有什么建议吗?

【问题讨论】:

  • 使用标准测试框架,像这样执行测试:coderwall.com/p/axugwa/…,并配置测试框架以并行运行测试。这一切都很标准。还有:github.com/yandex/mocha-parallel-tests,或者使用类似的解决方案。
  • 感谢您的回复!我在每次测试之前运行迁移并在每次测试后回滚迁移。唯一的问题是当我犯了错误而迁移失败,或者我在迁移回滚之前取消了测试。并行运行失败,因为我不知道通过 knex 使用多个数据库的好方法。
  • @user3654410 顺便说一句。关于 sqlite 速度,你可能会遇到这个问题? “...SQLite 在普通台式计算机上每秒可以轻松地执行 50,000 或更多的 INSERT 语句。但它每秒只会执行几十个事务...选项是运行 PRAGMA synchronous=OFF。此命令将导致 SQLite不要等待数据到达磁盘表面......”但不确定内存数据库是否会发生这种情况。子弹 19 @sqlite.org/faq.html

标签: node.js postgresql testing jestjs knex.js


【解决方案1】:

在每次测试之前运行迁移并回滚它们真的很慢,甚至可能需要几秒钟才能运行。因此,您可能不需要能够并行运行测试以达到足够好的速度。

如果您设置测试的方式是在开始运行测试之前删除/创建/迁移一次,并且在测试之间只截断表中的所有数据并用新数据填充它应该快 10 倍(截断通常需要大约不到 50 毫秒)。您可以轻松截断所有表格,例如使用 knex-db-manager 包。

如果您真的喜欢并行运行 postgresql 测试,那么您需要与运行并行测试一样多的测试数据库。您可以创建测试数据库的“池”(testdb-1、testdb-2、testdb-3,...),并且在每个 jest 测试中,您首先必须从测试数据库池中请求数据库,以便您可以真正运行多个测试同时,它们不会干扰同一个数据库。

最后,在测试数据库中重置数据的另一种非常快速的方法是使用pg-dump / pg-restore 和二进制数据库转储。在某些情况下,它可能比仅运行填充脚本更快或更容易处理。特别是在您在每次测试中使用相同的初始数据的情况下。

通过这种方式,您可以在开始运行测试之前为测试数据库创建初始状态并进行转储。为了转储和恢复,我编写了这些小助手,我可能会在某个时候将其添加到 knex-db-manager

转储/恢复的参数有点棘手(特别是设置密码),所以这些 sn-ps 可能会有所帮助:

倾销:

      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);
    }
  });

【讨论】:

  • 感谢您提供详尽而详尽的回答!我不知道迁移是如此缓慢,并且会尝试将其与 trancating 交换!我期待再次获得快速测试!
猜你喜欢
  • 2020-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 2016-01-19
  • 2015-12-21
  • 1970-01-01
相关资源
最近更新 更多