Skip to content

Commit

Permalink
task: Add Unit test result check task (#3695)
Browse files Browse the repository at this point in the history
After a Team Retro, one of our squads felt like we needed more data on
our test suites. This is the first effort to make our test results
easier to grab. It uses the test-reporter action to add a github check
to our main build and PR builds with our test results.

This at least should make it easier to parse which tests are failing.
However, it does not give us trends. So it does not yet make it easier
to decide which tests are flaky just from a quick view.

---------

Co-authored-by: Gastón Fournier <gaston@getunleash.io>
  • Loading branch information
Christopher Kolstad and gastonfournier committed May 25, 2023
1 parent 417b335 commit 3409b0c
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Expand Up @@ -41,7 +41,7 @@ jobs:
- run: yarn
- run: yarn build:frontend
- run: yarn lint
- run: yarn run test
- run: yarn run test:report # This adds test results as github check to the workflow
env:
CI: true
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/build_prs.yaml
Expand Up @@ -20,4 +20,3 @@ jobs:
- run: yarn install --frozen-lockfile --ignore-scripts
- run: yarn lint
- run: yarn build:backend
#- run: yarn build:frontend # not needed
45 changes: 45 additions & 0 deletions .github/workflows/build_prs_test_report.yaml
@@ -0,0 +1,45 @@
name: TestReport
on:
pull_request:
paths-ignore:
- website/**
- coverage/**

jobs:
testreport:
runs-on: ubuntu-latest
services:
# Label used to access the service container
postgres:
# Docker Hub image
image: postgres
# Provide the password for postgres
env:
POSTGRES_PASSWORD: postgres
# Set health checks to wait until postgres has started
ports:
- 5432:5432
options: >-
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v3
- name: Use Node.js 18
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'yarn'
- run: yarn install --frozen-lockfile --ignore-scripts
- run: yarn build:backend
- run: yarn test:report
env:
CI: true
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
- name: Upload test report to build # Done this way since external PRs would not be able to write the check. See https://github.com/marketplace/actions/test-reporter#recommended-setup-for-public-repositories
uses: actions/upload-artifact@v3
if: success() || failure()
with:
name: test-results
path: ./reports/jest-junit.xml
16 changes: 16 additions & 0 deletions .github/workflows/pr_add_test_results.yaml
@@ -0,0 +1,16 @@
name: 'Attach Test report'
on:
workflow_run:
workflows: [TestReport]
types:
- completed
jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: dorny/test-reporter@v1
with:
artifact: test-results # artifact name
name: Unit Tests # Name of the check run which will be created
path: '*.xml' # Path to test results (inside artifact .zip)
reporter: jest-junit
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -56,3 +56,4 @@ frontend/build
# Generated docs
website/docs/reference/api/**/sidebar.js
website/docs/generated
reports/jest-junit.xml
12 changes: 12 additions & 0 deletions package.json
Expand Up @@ -50,6 +50,7 @@
"test": "NODE_ENV=test PORT=4243 jest",
"test:unit": "NODE_ENV=test PORT=4243 jest --testPathIgnorePatterns=src/test/e2e --testPathIgnorePatterns=dist",
"test:docker": "./scripts/docker-postgres.sh",
"test:report": "NODE_ENV=test PORT=4243 jest --reporters=\"default\" --reporters=\"jest-junit\"",
"test:docker:cleanup": "docker rm -f unleash-postgres",
"test:watch": "yarn test --watch",
"test:coverage": "NODE_ENV=test PORT=4243 jest --coverage --testLocationInResults --outputFile=\"coverage/report.json\" --forceExit --testTimeout=10000",
Expand All @@ -61,6 +62,16 @@
"preversion": "./scripts/check-release.sh",
"heroku-postbuild": "cd frontend && yarn && yarn build"
},
"jest-junit": {
"suiteName": "Unleash Unit Tests",
"outputDirectory": "./reports",
"outputName": "jest-junit.xml",
"uniqueOutputName": "false",
"classNameTemplate": "{classname}-{title}",
"titleTemplate": "{classname}-{title}",
"ancestorSeparator": "",
"usePathForSuiteName": "true"
},
"jest": {
"automock": false,
"maxWorkers": 4,
Expand Down Expand Up @@ -193,6 +204,7 @@
"fetch-mock": "9.11.0",
"husky": "8.0.3",
"jest": "29.5.0",
"jest-junit": "^16.0.0",
"lint-staged": "13.2.2",
"nock": "13.3.1",
"openapi-enforcer": "1.22.3",
Expand Down
1 change: 1 addition & 0 deletions src/lib/__snapshots__/create-config.test.ts.snap
Expand Up @@ -149,6 +149,7 @@ exports[`should create default config 1`] = `
"preHook": undefined,
"preRouterHook": undefined,
"prometheusApi": undefined,
"publicFolder": undefined,
"secureHeaders": false,
"segmentValuesLimit": 1000,
"server": {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/app.ts
Expand Up @@ -40,7 +40,7 @@ export default async function getApp(
const app = express();

const baseUriPath = config.server.baseUriPath || '';
const publicFolder = findPublicFolder();
const publicFolder = config.publicFolder || findPublicFolder();
let indexHTML = await loadIndexHTML(config, publicFolder);

app.set('trust proxy', true);
Expand Down
1 change: 1 addition & 0 deletions src/lib/create-config.ts
Expand Up @@ -497,6 +497,7 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
clientFeatureCaching,
accessControlMaxAge,
prometheusApi,
publicFolder: options.publicFolder,
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib/types/option.ts
Expand Up @@ -116,6 +116,7 @@ export interface IUnleashOptions {
flagResolver?: IFlagResolver;
accessControlMaxAge?: number;
prometheusApi?: string;
publicFolder?: string;
}

export interface IEmailOption {
Expand Down Expand Up @@ -203,4 +204,5 @@ export interface IUnleashConfig {
clientFeatureCaching: IClientCachingOption;
accessControlMaxAge: number;
prometheusApi?: string;
publicFolder?: string;
}
4 changes: 3 additions & 1 deletion src/lib/util/load-index-html.ts
Expand Up @@ -17,7 +17,9 @@ export async function loadIndexHTML(
indexHTML = await res.text();
} else {
indexHTML = fs
.readFileSync(path.join(publicFolder, 'index.html'))
.readFileSync(
path.join(config.publicFolder || publicFolder, 'index.html'),
)
.toString();
}

Expand Down
3 changes: 1 addition & 2 deletions src/lib/util/rewriteHTML.test.ts
@@ -1,10 +1,9 @@
import fs from 'fs';
import path from 'path';
import { rewriteHTML } from './rewriteHTML';
import { findPublicFolder } from './findPublicFolder';

const input = fs
.readFileSync(path.join(findPublicFolder(), 'index.html'))
.readFileSync(path.join(__dirname, '../../test/examples', 'index.html'))
.toString();

test('rewriteHTML substitutes meta tag with existing rewrite value', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/util/rewriteHTML.ts
Expand Up @@ -11,7 +11,7 @@ export const rewriteHTML = (
const faviconPrefix = cdnPrefix ? 'https://cdn.getunleash.io' : '';
result = result.replace(/::faviconPrefix::/gi, faviconPrefix);

result = result.replace(/::uiFlags::/gi, uiFlags);
result = result.replace(/::uiFlags::/gi, uiFlags || '{}');

result = result.replace(
/\/static/gi,
Expand Down
4 changes: 3 additions & 1 deletion src/test/config/test-config.ts
Expand Up @@ -6,6 +6,7 @@ import {
} from '../../lib/types/option';
import getLogger from '../fixtures/no-logger';
import { createConfig } from '../../lib/create-config';
import path from 'path';

function mergeAll<T>(objects: Partial<T>[]): T {
return merge.all<T>(objects.filter((i) => i));
Expand All @@ -28,7 +29,8 @@ export function createTestConfig(config?: IUnleashOptions): IUnleashConfig {
embedProxyFrontend: true,
},
},
publicFolder: path.join(__dirname, '../examples'),
};
const options = mergeAll<IUnleashOptions>([testConfig, config]);
const options = mergeAll<IUnleashOptions>([testConfig, config || {}]);
return createConfig(options);
}
2 changes: 1 addition & 1 deletion src/test/e2e/services/group-service.e2e.test.ts
Expand Up @@ -104,7 +104,7 @@ test('adding a root role to a group with a project role should fail', async () =
description: 'root_group',
});

stores.accessStore.addGroupToRole(group.id, 1, 'test', 'default');
await stores.accessStore.addGroupToRole(group.id, 1, 'test', 'default');

await expect(() => {
return groupService.updateGroup(
Expand Down
Binary file added src/test/examples/favicon.ico
Binary file not shown.
26 changes: 26 additions & 0 deletions src/test/examples/index.html
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="::faviconPrefix::/favicon.ico" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="baseUriPath" content="::baseUriPath::" />
<meta name="cdnPrefix" content="::cdnPrefix::" />
<meta name="uiFlags" content="::uiFlags::" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="unleash" />
<title>Unleash</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Sen:wght@400;700;800&display=swap"
rel="stylesheet"
/>
<script type="module" crossorigin src="/static/index-6328a762.js"></script>
<link rel="stylesheet" href="/static/index-66c635eb.css">
</head>
<body>
<div id="app"></div>

</body>
</html>
20 changes: 20 additions & 0 deletions yarn.lock
Expand Up @@ -4466,6 +4466,16 @@ jest-haste-map@^29.5.0:
optionalDependencies:
fsevents "^2.3.2"

jest-junit@^16.0.0:
version "16.0.0"
resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-16.0.0.tgz#d838e8c561cf9fdd7eb54f63020777eee4136785"
integrity sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==
dependencies:
mkdirp "^1.0.4"
strip-ansi "^6.0.1"
uuid "^8.3.2"
xml "^1.0.1"

jest-leak-detector@^29.5.0:
version "29.5.0"
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz#cf4bdea9615c72bac4a3a7ba7e7930f9c0610c8c"
Expand Down Expand Up @@ -7322,6 +7332,11 @@ uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==

uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==

uuid@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
Expand Down Expand Up @@ -7485,6 +7500,11 @@ write-file-atomic@^4.0.2:
imurmurhash "^0.1.4"
signal-exit "^3.0.7"

xml@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==

xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
Expand Down

0 comments on commit 3409b0c

Please sign in to comment.