如何解决Github Actions 上的 Mocha 并行作业
我刚刚切换到 Mocha 中的并行测试,这很好用,但是,当我在 github 上运行它时,它似乎没有并行运行。我需要配置什么才能让 Mocha 在 Github Actions 上并行运行?
.mocharc.json // 摩卡 9.x
{
"timeout": 5000,"recursive": true,"ui": "mocha-cakes-2","parallel": true,"jobs": 4,"checkLeaks": true,"globals": [
"browser","mocha-cakes-2","regeneratorRuntime"
],"exit": true,"require": ["./test/helpers/setup.js"]
}
node.js.yml
name: Node.js CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test
解决方法
我设法让它工作:
- 通过
findAllTests.js
获取所有测试文件 - 然后我用
jq
将这个文件的输出分成 3 个相等的块。 - 然后我存储来自
npm run build
的工件并准备在下一阶段使用它们。 - 然后我连续启动 3 个测试运行程序(随着您的项目变大,可以轻松配置)
- 最后,无论之前的任何步骤是否失败,我都会删除这些工件(我们不需要它们)
findAllTests.js
"use strict";
const fs = require("fs");
const path = require("path");
const files = [];
function shuffleArray(unshuffledArray) {
// Schwartzian transform. Will eventually help in evening out the test-time for each chunk.
return unshuffledArray
.map((a) => ({ sort: Math.random(),value: a }))
.sort((a,b) => a.sort - b.sort)
.map((a) => a.value);
}
/**
* Traverses through all subdirectories of a given folder.
* Used for Github Actions in order to aggregate and chunk all tests into even sizes.
*/
function findAllTests(directory) {
fs.readdirSync(directory).forEach((file) => {
const absolute = path.join(directory,file);
if (fs.statSync(absolute).isDirectory()) {
return findAllTests(absolute);
}
if (absolute.endsWith(".js") && !/(findAllTests|\/data\/|\/helpers\/)/.test(absolute)) {
return files.push(absolute);
}
});
}
function isMocha(context) {
return ["afterEach","after","beforeEach","before","describe","it"].every((functionName) => {
return context[functionName] instanceof Function;
});
}
if (!isMocha(global)) {
findAllTests("./test/");
console.log(JSON.stringify(shuffleArray(files),null,2)); // eslint-disable-line
}
node.yml.js
name: Node.js CI
on: [push]
jobs:
setup:
runs-on: ubuntu-latest
name: Setup
strategy:
matrix:
node-version: [14.x]
outputs:
test-chunks: ${{ steps['set-test-chunks'].outputs['test-chunks'] }}
test-chunk-ids: ${{ steps['set-test-chunk-ids'].outputs['test-chunk-ids'] }}
steps:
- uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
- name: Install & Build
run: |
npm ci
npm run build --if-present
- name: ESLint
run: npm run lint:js
- name: Save build artifacts
uses: actions/upload-artifact@v2
with:
name: public
path: public
- id: set-test-chunks
name: Set Chunks
run: echo "::set-output name=test-chunks::$(node ./test/findAllTests.js | jq -cM '[_nwise(length / 3 | ceil)]')"
- id: set-test-chunk-ids
name: Set Chunk IDs
run: echo "::set-output name=test-chunk-ids::$(echo $CHUNKS | jq -cM 'to_entries | map(.key)')"
env:
CHUNKS: ${{ steps['set-test-chunks'].outputs['test-chunks'] }}
mocha:
runs-on: ubuntu-latest
name: Test (chunk ${{ matrix.chunk }})
needs: setup
strategy:
matrix:
node-version: [14.x]
chunk: ${{ fromJson(needs.setup.outputs['test-chunk-ids']) }}
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- uses: actions/checkout@v2
- run: npm ci
- name: Download build artifacts
uses: actions/download-artifact@v2
- name: Mocha
run: echo $CHUNKS | jq '.[${{ matrix.chunk }}] | .[] | @text' | xargs npm run mocha:ga
env:
CHUNKS: ${{ needs.setup.outputs['test-chunks'] }}
cleanup:
runs-on: ubuntu-latest
name: Cleanup
needs: [setup,mocha]
if: always()
steps:
- uses: geekyeggo/delete-artifact@v1
with:
name: public
failOnError: false
mocharc.json
{
"timeout": 5000,"recursive": true,"ui": "mocha-cakes-2","checkLeaks": true,"globals": [
"browser","document","mocha-cakes-2","regeneratorRuntime","WebSocket","window"
],"exit": true,"no-warnings": true,"require": ["./test/helpers/setup.js"]
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。