Skip to content

Commit

Permalink
Merge pull request #13943 from Expensify/Rory-SimplifyTestWorkflow
Browse files Browse the repository at this point in the history
[No QA] Simplify test workflow using Jest --shard flag
  • Loading branch information
roryabraham authored Feb 8, 2023
2 parents 363c2fd + ebd4fc9 commit 96a8085
Show file tree
Hide file tree
Showing 16 changed files with 16,637 additions and 14,015 deletions.
9 changes: 9 additions & 0 deletions .github/scripts/verifyPodfile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ title "Verifying that Podfile.lock is synced with the project"

declare EXIT_CODE=0

# Check Provisioning Style. If automatic signing is enabled, iOS builds will fail, so ensure we always have the proper profile specified
info "Verifying that automatic signing is not enabled"
if grep -q 'PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore' ios/NewExpensify.xcodeproj/project.pbxproj; then
success "Automatic signing not enabled"
else
error "Error: Automatic provisioning style is not allowed!"
EXIT_CODE=1
fi

PODFILE_SHA=$(openssl sha1 ios/Podfile | awk '{print $2}')
PODFILE_LOCK_SHA=$(awk '/PODFILE CHECKSUM: /{print $3}' ios/Podfile.lock)

Expand Down
65 changes: 20 additions & 45 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,69 +6,44 @@ on:
types: [opened, synchronize]
branches-ignore: [staging, production]

env:
# Number of parallel jobs for jest tests
CHUNKS: 3
jobs:
config:
runs-on: ubuntu-latest
name: Define matrix parameters
outputs:
MATRIX: ${{ steps.set-matrix.outputs.MATRIX }}
JEST_CHUNKS: ${{ steps.set-matrix.outputs.JEST_CHUNKS }}
steps:
- name: Set Matrix
id: set-matrix
uses: actions/github-script@v6
with:
# Generate matrix array i.e. [0, 1, 2, ...., CHUNKS - 1] for test job
script: |
core.setOutput('MATRIX', Array.from({ length: Number(process.env.CHUNKS) }, (v, i) => i + 1));
core.setOutput('JEST_CHUNKS', Number(process.env.CHUNKS) - 1);
test:
needs: config
jest:
if: ${{ github.actor != 'OSBotify' || github.event_name == 'workflow_call' }}
runs-on: ubuntu-latest
name: test (job ${{ fromJSON(matrix.chunk) }})
env:
CI: true
strategy:
fail-fast: false
matrix:
chunk: ${{fromJson(needs.config.outputs.MATRIX)}}

chunk: [ 1, 2, 3 ]
name: test (job ${{ fromJSON(matrix.chunk) }})
steps:
# This action checks-out the repository, so the workflow can access it.
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
with:
fetch-depth: 0
- uses: actions/checkout@885641592076c27bfb56c028cd5612cdad63e16d

- uses: Expensify/App/.github/actions/composite/setupNode@main

# If automatic signing is enabled, iOS builds will fail, so ensure we always have the proper profile specified
- name: Check Provisioning Style
run: |
if grep -q 'PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore' ios/NewExpensify.xcodeproj/project.pbxproj; then
exit 0
else
echo "Error: Automatic provisioning style is not allowed!"
exit 1
fi
- name: Get number of CPU cores
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@31e91de0f8654375a21e8e83078be625380e2b18

- name: Cache Jest cache
id: cache-jest-cache
uses: actions/cache@v1
uses: actions/cache@ac25611caef967612169ab7e95533cf932c32270
with:
path: .jest-cache
key: ${{ runner.os }}-jest

- name: All Unit Tests
if: ${{ fromJSON(matrix.chunk) < fromJSON(env.CHUNKS) }}
# Split the jest based test files in multiple chunks/groups and then execute them in parallel in different jobs/runners.
run: npx jest --listTests --json | jq -cM '[_nwise(length / ${{ fromJSON(needs.config.outputs.JEST_CHUNKS) }} | ceil)]' | jq '[[]] + .' | jq '.[${{ fromJSON(matrix.chunk) }}] | .[] | @text' | xargs npm test
- name: Jest tests
run: npx jest --shard=${{ fromJSON(matrix.chunk) }}/${{ strategy.job-total }} --max-workers ${{ steps.cpu-cores.outputs.count }}

shellTests:
if: ${{ github.actor != 'OSBotify' || github.event_name == 'workflow_call' }}
runs-on: ubuntu-latest
name: Shell tests
steps:
- uses: actions/checkout@885641592076c27bfb56c028cd5612cdad63e16d

- uses: Expensify/App/.github/actions/composite/setupNode@main

- name: Pull Request Tests
# Pull request related tests will be run in separate runner in parallel.
if: ${{ fromJSON(matrix.chunk) == fromJSON(env.CHUNKS) }}
- name: getPullRequestsMergedBetween
run: tests/unit/getPullRequestsMergedBetweenTest.sh
9 changes: 9 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ const metro = {
presets: [require('metro-react-native-babel-preset')],
plugins: [
'react-native-reanimated/plugin',

// This is needed due to a react-native bug: https://github.com/facebook/react-native/issues/29084#issuecomment-1030732709
// It is included in metro-react-native-babel-preset but needs to be before plugin-proposal-class-properties or FlatList will break
'@babel/plugin-transform-flow-strip-types',

['@babel/plugin-proposal-class-properties', {loose: true}],
['@babel/plugin-proposal-private-methods', {loose: true}],
['@babel/plugin-proposal-private-property-in-object', {loose: true}],
],
};

Expand Down Expand Up @@ -60,6 +68,7 @@ if (process.env.CAPTURE_METRICS === 'true') {
module.exports = ({caller}) => {
// For `react-native` (iOS/Android) caller will be "metro"
// For `webpack` (Web) caller will be "@babel-loader"
// For jest, it will be babel-jest
// For `storybook` there won't be any config at all so we must give default argument of an empty object
const runningIn = caller((args = {}) => args.name);
return ['metro', 'babel-jest'].includes(runningIn) ? metro : webpack;
Expand Down
36 changes: 36 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const testFileExtension = '[jt]s?(x)';
module.exports = {
// TODO: change this back to preset: 'react-native' once we upgrade to React Native >= 0.71.2
preset: '@testing-library/react-native',
testMatch: [
`<rootDir>/tests/ui/**/*.${testFileExtension}`,
`<rootDir>/tests/unit/**/*.${testFileExtension}`,
`<rootDir>/tests/actions/**/*.${testFileExtension}`,
`<rootDir>/?(*.)+(spec|test).${testFileExtension}`,
],
transform: {
'^.+\\.jsx?$': 'babel-jest',
},
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!react-native)/',
],
testPathIgnorePatterns: [
'<rootDir>/node_modules',
],
globals: {
__DEV__: true,
WebSocket: {},
},
fakeTimers: {
enableGlobally: true,
doNotFake: ['nextTick'],
},
testEnvironment: 'jsdom',
setupFiles: [
'<rootDir>/jest/setup.js',
],
setupFilesAfterEnv: [
'@testing-library/jest-native/extend-expect',
],
cacheDirectory: '<rootDir>/.jest-cache',
};
Loading

0 comments on commit 96a8085

Please sign in to comment.