Skip to content

Commit

Permalink
feat: Make Jest unit tests run faster in GitHub actions (#25726)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25726?quickstart=1)

Based on #25680, by
migrating the jest unit tests from CircleCI to GitHub actions the time
to run unit tests has increased to 15 minutes from 5 minutes. This PR
makes Jest unit tests run faster in Github actions. This is achieved by
some improvements to the testing infrastructure.

1. **Sharding**: the tests are run on 6 machines in parallel, instead of
a single machine. This saves around ~8-9 minutes on average.
2. **Optimized coverage generation**: I removed the generation of html
reports in CI, as they are only used for local debugging. This should
also save some time, as unused files are not being generated on CI.
3. **Merged development tests**: The two small tests under
`build/transforms` were merged into the main test configuration. This
means that one less machine needs to be started (as the development
tests would require their own machine to run, due to the sharding
introduced in this PR), saving around approx. 2 minutes of compute time.
4. **Minor fixes**: Now the `run-unit-tests` workflow will also run on
push to the `develop` and `master` branches.

## **Related issues**

Fixes: #25680,

## **Manual testing steps**

1. Run CI and see that tests are running fast (between 5-7 mins on
average)

## **Screenshots/Recordings**

Not Applicable

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
itsyoboieltr authored Jul 12, 2024
1 parent 613b7a5 commit 24c95db
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 189 deletions.
44 changes: 32 additions & 12 deletions .github/workflows/run-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,52 @@
# WARNING! It is currently being investigated how to make this faster
# DO NOT blindly copy this workflow, not noticing the slow down,
# because suddenly our tests will take hours to pass CI.
# Hopefully this comment here will help prevent that.
# https://github.com/MetaMask/metamask-extension/issues/25680

name: Run unit tests

on:
push:
branches: [develop, master]
pull_request:
types: [opened,reopened,synchronize]

jobs:
test-unit-jest:
test-unit:
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3, 4, 5, 6]
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup environment
uses: ./.github/actions/setup-environment

- name: test:coverage:jest:dev
run: yarn test:coverage:jest:dev
- name: test:unit:coverage
run: yarn test:unit:coverage --shard=${{ matrix.shard }}/${{ strategy.job-total }}

- name: Rename coverage to shard coverage
run: mv coverage/coverage-final.json coverage/coverage-${{matrix.shard}}.json

- uses: actions/upload-artifact@v4
with:
name: coverage-${{matrix.shard}}
path: coverage/coverage-${{matrix.shard}}.json

report-coverage:
runs-on: ubuntu-latest
needs:
- test-unit
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: test:coverage:jest
run: yarn test:coverage:jest
- name: Download coverage from shards
uses: actions/download-artifact@v4
with:
path: coverage
pattern: coverage-*
merge-multiple: true

- uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
- name: Upload coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
7 changes: 7 additions & 0 deletions development/build/transforms/remove-fenced-code.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @jest-environment node
*/
const buildUtils = require('@metamask/build-utils');
const { createRemoveFencedCodeTransform } = require('./remove-fenced-code');
const transformUtils = require('./utils');
Expand Down Expand Up @@ -36,6 +39,10 @@ describe('build/transforms/remove-fenced-code', () => {
lintTransformedFileMock.mockImplementation(() => Promise.resolve());
});

afterEach(() => {
jest.resetAllMocks();
});

it('returns a PassThrough stream for files with ignored extensions', async () => {
const fileContent = '"Valid JSON content"\n';
const stream = createRemoveFencedCodeTransform(
Expand Down
3 changes: 3 additions & 0 deletions development/build/transforms/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @jest-environment node
*/
const { getESLintInstance } = require('./utils');

let mockESLint;
Expand Down
11 changes: 0 additions & 11 deletions development/jest.config.js

This file was deleted.

5 changes: 3 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ module.exports = {
'<rootDir>/app/scripts/**/*.(js|ts|tsx)',
'<rootDir>/shared/**/*.(js|ts|tsx)',
'<rootDir>/ui/**/*.(js|ts|tsx)',
'<rootDir>/development/build/transforms/**/*.js',
],
coverageDirectory: './coverage',
coveragePathIgnorePatterns: ['.stories.*', '.snap'],
coverageReporters: ['html', 'json'],
coverageReporters: process.env.CI ? ['json'] : ['html', 'json'],
reporters: [
'default',
[
Expand All @@ -26,7 +27,7 @@ module.exports = {
'<rootDir>/app/scripts/**/*.test.(js|ts|tsx)',
'<rootDir>/shared/**/*.test.(js|ts|tsx)',
'<rootDir>/ui/**/*.test.(js|ts|tsx)',
'<rootDir>/development/fitness-functions/**/*.test.(js|ts|tsx)',
'<rootDir>/development/**/*.test.(js|ts|tsx)',
'<rootDir>/test/e2e/helpers.test.js',
],
testTimeout: 5500,
Expand Down
12 changes: 4 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@
"dapp-chain": "GANACHE_ARGS='-b 2' concurrently -k -n ganache,dapp -p '[{time}][{name}]' 'yarn ganache:start' 'sleep 5 && yarn dapp'",
"forwarder": "node ./development/static-server.js ./node_modules/@metamask/forwarder/dist/ --port 9010",
"dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'",
"test:unit": "jest",
"test:unit:watch": "jest --watch",
"test:unit:global": "mocha test/unit-global/*.test.js",
"test:unit:coverage": "jest --coverage",
"test:integration": "jest --config jest.integration.config.js",
"test:integration:coverage": "jest --config jest.integration.config.js --coverage",
"test:unit": "node ./test/run-unit-tests.js --jestGlobal --jestDev",
"test:unit:jest": "node ./test/run-unit-tests.js --jestGlobal --jestDev",
"test:unit:jest:watch": "node --inspect ./node_modules/.bin/jest --watch",
"test:unit:global": "mocha test/unit-global/*.test.js",
"test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js",
"test:e2e:chrome:mmi": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --mmi",
"test:e2e:chrome:flask": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --build-type flask",
Expand All @@ -61,10 +61,6 @@
"test:e2e:firefox": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js",
"test:e2e:firefox:flask": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js --build-type flask",
"test:e2e:single": "node test/e2e/run-e2e-test.js",
"test:coverage:jest": "node ./test/run-unit-tests.js --jestGlobal --coverage",
"test:coverage:jest:dev": "node ./test/run-unit-tests.js --jestDev --coverage",
"test:coverage": "node ./test/run-unit-tests.js --jestGlobal --jestDev --coverage",
"test:coverage:html": "yarn test:coverage --html",
"ganache:start": "./development/run-ganache.sh",
"sentry:publish": "node ./development/sentry-publish.js",
"lint": "yarn lint:prettier && yarn lint:eslint && yarn lint:tsc && yarn lint:styles",
Expand Down
156 changes: 0 additions & 156 deletions test/run-unit-tests.js

This file was deleted.

0 comments on commit 24c95db

Please sign in to comment.