【问题标题】:Running multiple cypress instances locally results in unpredictable errors在本地运行多个 cypress 实例会导致不可预测的错误
【发布时间】:2021-12-01 11:58:27
【问题描述】:

我们的 CI 中有一个强大的服务器,我们希望利用它并在同一台机器上并行化我们的 cypress 测试套件。我们知道cypress doesn't encourage it,但这应该是可能的!

我们有一个 bash 脚本,它将所有测试文件拆分到 n 组中,并在后台的新端口上的每个组上运行 cypress:

npx cypress run --spec $specFiles --port $port --headless &

原则上,这应该可以工作,因为每个进程都将在单独的无头浏览器上运行其文件。但是,如果有超过 4 个工人,我们会遇到各种错误:

  • 未找到自定义命令
  • 通过单个工作人员的测试现在不确定地失败:
  • 语法错误?!? (代码在单个工作人员上正确运行)
  • 超时 - 这些不应该发生,因为网络服务器没有承受任何重大负载!

我们正在尽最大努力避免将每个 cypress 实例作为新的 docker 容器运行,以避免额外的 CI 复杂性,但如有必要,我们会深入研究。我们是否遗漏了一些明显的东西?

这是完整的脚本供参考:

#!/bin/bash

nThreads=3

print_usage() {
  printf "Usage:
    ./run_tests_parallel.sh -n <number of threads to use>
    Defaults to $nThreads threads\n"
  exit 0;
}

while true; do
  case "$1" in
    -n | --threads ) nThreads=$2; shift 2 ;;
    -h | --help ) print_usage ; shift ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

echo Using $nThreads threads

# Return non-zero if any of the subprocesses
# returns non-zero
set -eu

testFiles=`find . -name "*.test.ts" -not -path "./node_modules/*"`

# init testF
testFilesPerThread=()
for (( n=0; n<$nThreads; n++ )); do
    testFilesPerThread+=("")
done

i=0
for testFile in $testFiles; do
    testFilesPerThread[$i]="${testFilesPerThread[$i]} $testFile"
    i=$((($i + 1)%$nThreads))
done

pids=()
for (( i=0; i<${#testFilesPerThread[@]}; i++ )); do
    echo Thread $i has files: ${testFilesPerThread[$i]}
    # strip string and join files with ","
    specFiles=`echo ${testFilesPerThread[$i]} | xargs | tr -s "\ " ","`
    port=$((30001+$i))

    # run tests in background
    npx cypress run --spec $specFiles --port $port --headless &
    pids+=($!)
    echo "Spawned PID ${pids[${#pids[@]}-1]} for thread $i on port $port"
done


for pid in ${pids[@]} ; do
  echo "Waiting for PID $pid."
  wait $pid
done

echo DONE.

【问题讨论】:

    标签: bash parallel-processing frontend cypress race-condition


    【解决方案1】:

    正如 Fody 在this answer 中提到的:

    听起来好像发生了文件访问冲突

    所有这些错误都是由每个单独的后台进程编译我们的打字稿代码引起的竞争条件。有时,一个 cypress 实例会在另一个进程正在编译代码时尝试运行测试,这会导致各种错误,包括奇怪的语法错误。

    我们现在决定在自己的容器中运行每组测试,因为这是在自己的环境中隔离每个测试套件的唯一方法

    【讨论】:

      【解决方案2】:

      我不是专家,但“输入意外结束”听起来像是发生了文件访问冲突。也许两个进程试图写入同一个测试工件。

      我听说一般线程数不应该超过核心数 - 1。在我的 4 核机器上,指定 3 个线程可以让我在 20 种规格上提高约 15% 的吞吐量。

      我使用 NodeJS 脚本调用赛普拉斯模块 API,它允许在每个线程的基础上调整配置以避免文件写入冲突(请参阅reporterOptions)

      const path = require('path')
      const fs = require('fs-extra')
      const cypress = require('cypress')
      
      const walkSync = function(dir, filelist = []) {
        const files = fs.readdirSync(dir);
        files.forEach(function(item) {
          const itemPath = path.join(dir, item)
          if (fs.statSync(itemPath).isDirectory()) {
            filelist = walkSync(itemPath, filelist);
          }
          else {
            filelist.push(itemPath);
          }
        });
        return filelist;
      };
      const files = walkSync(path.join(__dirname, '../cypress/integration'))
      
      const groups= 3
      const groupSize = Math.ceil(files.length / groups)
      const groups = files.reduce((acc, file) => {
        if (!acc.length || acc[acc.length-1].length === groupSize) acc.push([]);
        acc[acc.length-1].push(file)
        return acc
      },[])
      
      console.time('process-time')
      const promises = groups.map((group, i) => {
        return cypress.run({
          config: {
            video: false,
            screenshotsFolder: `cypress/screenshots/group${i}`,
            reporterOptions: {
              mochaFile: `results/group${i}/my-test-output.xml`,
            }
          },
          spec: group.join(','),
        })
      })
      
      Promise.all(promises).then(results => {
        console.timeEnd('process-time')
      });
      

      另请参阅使用cypress-parallelIs there any way to run parallel cypress tests on local machine

      【讨论】:

        猜你喜欢
        • 2020-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-28
        相关资源
        最近更新 更多