Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cypress E2E Tests parallelization #3208

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
246d0b3
add sleep for agent heartbeat and a second loadScenario to have the a…
vicenteqa Dec 17, 2024
d8d8ccd
add yaml for parallelization testing purposes
vicenteqa Dec 17, 2024
8ddc6f1
align with master
vicenteqa Dec 17, 2024
0efd1d4
modify yaml name
vicenteqa Dec 17, 2024
00b728c
properly setup cypress-split
vicenteqa Dec 18, 2024
11dc3ce
fix cypress config, left undefined cypress split accidentally
vicenteqa Dec 18, 2024
d596413
add new selector and different assertion for better feedback and debu…
vicenteqa Dec 18, 2024
96789ab
execute hosts_overview tests first to check if that avoids issues
vicenteqa Dec 18, 2024
42d88c6
use specific selector for all cluster statuses
vicenteqa Dec 18, 2024
dbfcb09
modify test execution order in hosts overview
vicenteqa Dec 18, 2024
4f14c66
try running only this test in the CI
vicenteqa Dec 18, 2024
e1d2864
run test isolated to check if issue persists
vicenteqa Dec 18, 2024
9bd31ad
run test isolated to check if issue persists
vicenteqa Dec 18, 2024
c7b3290
try one thread only
vicenteqa Dec 18, 2024
441e1d9
try one thread only
vicenteqa Dec 18, 2024
14ad1c9
modifications on pipeline matrix
vicenteqa Dec 18, 2024
f432f7e
modifications on pipeline matrix
vicenteqa Dec 18, 2024
ce9e2b9
modifications on pipeline matrix
vicenteqa Dec 18, 2024
a9f3c36
redo cypress and check sequential run
vicenteqa Dec 18, 2024
7288119
modify yaml title
vicenteqa Dec 18, 2024
0c50871
run only hosts overview test
vicenteqa Dec 18, 2024
73b76c9
add matrix strategy
vicenteqa Dec 18, 2024
8383884
add split env variables
vicenteqa Dec 18, 2024
7034908
run whole hosts_overview file
vicenteqa Dec 18, 2024
15b9b64
try with all tests and 4 containers
vicenteqa Dec 18, 2024
53c173e
apply changes in CI pipeline and try 6 cores in POC pipeline
vicenteqa Dec 18, 2024
796bb36
add have.text instead of contains for total critical after stopping h…
vicenteqa Dec 18, 2024
530fed5
remove video attachment for tests
vicenteqa Dec 19, 2024
a5993d4
prepare test scenario with photofinish in pipeline to check if it imp…
vicenteqa Dec 19, 2024
7b45b21
try with 6 cores after recent changes
vicenteqa Dec 19, 2024
c472819
try 8 cores
vicenteqa Dec 19, 2024
0ebcfac
remove unnecessary load scenario
vicenteqa Dec 19, 2024
fd242bd
apply changes to main CI pipeline
vicenteqa Dec 19, 2024
a281e3d
align with master
vicenteqa Dec 20, 2024
bc92f77
bring back load scenario lines and remove it from ci to compare execu…
vicenteqa Dec 20, 2024
55bd49b
run photofinish prior to launch cypress tests
vicenteqa Dec 20, 2024
77166ea
add missing awaits
vicenteqa Dec 20, 2024
ca3bfae
revert change in deregister db instance test
vicenteqa Dec 20, 2024
43f967c
revert change critical 29 hosts health
vicenteqa Dec 20, 2024
09a331d
revert have.text vs contain
vicenteqa Dec 20, 2024
72c817d
remove sleep for agent heartbeat
vicenteqa Dec 20, 2024
1075ea7
add delay for start agent heart beat to reduces flakiness in hosts ov…
vicenteqa Dec 20, 2024
4473d68
signing this commit
vicenteqa Dec 20, 2024
7e8446a
run prettier
vicenteqa Dec 20, 2024
40b91b0
fix merge conflicts and adapt photofinish in before test
vicenteqa Dec 24, 2024
fb6973d
remove load photofinish from index.js and implement logic as a comman…
vicenteqa Dec 24, 2024
acd7891
fix eslint
vicenteqa Dec 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ jobs:
name: End to end tests
needs: [elixir-deps, npm-deps, npm-e2e-deps]
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
containers: [1,2,3,4,5,6,7,8]
env:
MIX_ENV: dev
steps:
Expand Down Expand Up @@ -427,6 +431,8 @@ jobs:
- name: Cypress run
uses: cypress-io/github-action@v6
env:
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
cypress_video: false
cypress_db_host: postgres
cypress_db_port: 5432
Expand Down
1 change: 0 additions & 1 deletion test/e2e/cypress/e2e/about.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { getValue } from '../support/common';

describe('User account page', () => {
before(() => {
cy.loadScenario('healthy-29-node-SAP-cluster');
cy.visit('/about');
cy.url().should('include', '/about');
});
Expand Down
4 changes: 0 additions & 4 deletions test/e2e/cypress/e2e/activity_log.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ const FIRST = '[aria-label="first-page"]';
const LAST = '[aria-label="last-page"]';

context('Activity Log page', () => {
before(() => {
cy.loadScenario('healthy-29-node-SAP-cluster');
});

describe('Navigation', () => {
it('should navigate to Activity Log page', () => {
cy.visit('/');
Expand Down
1 change: 0 additions & 1 deletion test/e2e/cypress/e2e/clusters_overview.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const clusterTags = {

context('Clusters Overview', () => {
before(() => {
cy.loadScenario('healthy-29-node-SAP-cluster');
cy.visit('/clusters');
cy.url().should('include', '/clusters');
});
Expand Down
1 change: 0 additions & 1 deletion test/e2e/cypress/e2e/hana_cluster_details.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ context('HANA cluster details', () => {
const catalog = catalogCheckFactory.buildList(5);

before(() => {
cy.loadScenario('healthy-29-node-SAP-cluster');
cy.intercept(lastExecutionURL, {
body: lastExecution,
}).as('lastExecution');
Expand Down
1 change: 0 additions & 1 deletion test/e2e/cypress/e2e/hana_database_details.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {

context('HANA database details', () => {
before(() => {
cy.loadScenario('healthy-29-node-SAP-cluster');
cy.visit(`/databases/${selectedDatabase.Id}`);
cy.url().should('include', `/databases/${selectedDatabase.Id}`);
});
Expand Down
4 changes: 0 additions & 4 deletions test/e2e/cypress/e2e/suse_manager_overviews.cy.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
context('SUSE Manager overviews', () => {
before(() => {
cy.loadScenario('healthy-29-node-SAP-cluster');
});

describe('navigates and display SUSE Manager based infos', () => {
it('host is found on SUSE Manager and has vulnerabilities', () => {
cy.clearSUMASettings();
Expand Down
49 changes: 41 additions & 8 deletions test/e2e/cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,26 @@
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars

const cypressSplit = require('cypress-split');
const { exec } = require('child_process');
const http = require('http');
const webpack = require('@cypress/webpack-preprocessor');
let heartbeatsIntervals = [];

module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on('before:run', async () => {
const photofinishBinary =
await getPhotofinishBinaryAndGiveExecutablePermissions();
await runPhotofinishMainScenario(photofinishBinary);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: ‏This means the scenario is loaded once per process, right?
So, given the target application is the same, the CI will be executed 8 times while on local execution just once.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's it, once per process, so if you execute the whole test suite locally (sequential) this will be executed just once at the very beginning.

cypressSplit(on, config);
on('task', {
startAgentHeartbeat(agents) {
const { web_api_host, web_api_port, heartbeat_interval } = config.env;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const heartbeat = (agentId) =>
http
.request({
Expand All @@ -37,13 +45,15 @@ module.exports = (on, config) => {
})
.end();

agents.forEach((agentId) => {
heartbeat(agentId);
let interval = setInterval(
() => heartbeat(agentId),
heartbeat_interval
);
heartbeatsIntervals.push(interval);
sleep(500).then(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: ‏Do you think we can better understand why it is needed, to remove it?
Sleeps on arbitrary time spans are often cause of flakiness, as they may depend on the running machine

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of arbitrary waits either and I know they should be avoided as a good practice, for the moment I don't have a conclusive answer tbh but I noticed that with a bit of delay the hosts_overview test flakiness is reduced a lot so I added it as a contingency measure, we can remove it if you want or even we can try the test flakiness tool designed by @gagandeepb then try with and without the arbitrary sleep and compare results.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have an alternative so I guess I must live with it 🤷‍♂️

agents.forEach((agentId) => {
heartbeat(agentId);
let interval = setInterval(
() => heartbeat(agentId),
heartbeat_interval
);
heartbeatsIntervals.push(interval);
});
});
return null;
},
Expand All @@ -66,3 +76,26 @@ module.exports = (on, config) => {

return config;
};

function runCommand(command) {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) reject(new Error(`Error: ${stderr || error.message}`));
else resolve(stdout.trim());
});
});
}

async function getPhotofinishBinaryAndGiveExecutablePermissions() {
const photofinishBinary = await runCommand(
'whereis photofinish | cut -d" " -f2'
);
await runCommand(`chmod +x ${photofinishBinary}`);
return photofinishBinary;
}

async function runPhotofinishMainScenario(photofinishBinary) {
return runCommand(
`cd ../.. && ${photofinishBinary} run --url "http://localhost:4000/api/collect" healthy-29-node-SAP-cluster`
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: ‏Why can't we use the loadScenario helper here?

Also, why the need to rewrite how we configure the photofinish command? See

`cd ${projectRoot} && ${photofinishBinary} run --url "http://${webAPIHost}:${webAPIPort}/api/collect" ${scenario}`

Copy link
Author

@vicenteqa vicenteqa Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because when this piece of code is executed, cy commands are still not available, cypress env parameters are not available either at that point of execution. Maybe we could use regular node env variables with process.env 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process.env

Maybe it's better, we keep the same structure.

Also, if we don't use the loadScenario command anymore, should we remove it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, actually it is still used in some tests, specially to restore scenarios that previous test modified, and to load some other different scenarios.

Loading
Loading