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

add consistency, fix display of times, update readme, show final results time #1

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![npm version](https://badge.fury.io/js/cypress-parallel.svg)](https://badge.fury.io/js/cypress-parallel)
# cypress-parallel
Reduce up to 40% your Cypress suite execution time parallelizing the test run on the same machine.

# Run your Cypress test in parallel (locally)

## How it works
Expand All @@ -15,13 +15,13 @@ Reduce up to 40% your Cypress suite execution time parallelizing the test run on

## Install
```
npm i cypress-parallel
npm i sezane/cypress-parallel
```

or
or

```
yarn add cypress-parallel
yarn add sezane/cypress-parallel
```

## Add a new script
Expand All @@ -41,7 +41,7 @@ yarn add cypress-parallel
Sample:

```
-a '\"--config baseUrl=http://localhost:3000\"'
cypress-parallel -s cy:run -t 2 -d cypress -a '\"--config baseUrl=http://localhost:3000\"'
```

## Launch the new script
Expand All @@ -52,16 +52,20 @@ npm run cy:parallel

### Scripts options

| Option | Alias | Description | Type |
| ---------- | ----- | ---------------------------------- | ------ |
| --help | | Show help | |
| --version | | Show version number | |
| --script | -s | Your npm Cypress command | string |
| --args | -a | Your npm Cypress command arguments | string |
| --threads | -t | Number of threads | number |
| --specsDir | -d | Cypress specs directory. | string |
| Option | Alias | Description | Type | Default |
| ----------------- | ----- | ---------------------------------- | ------ | ------------------- |
| --help | | Show help | | |
| --version | | Show version number | | |
| --script | -s | Your npm Cypress command | string | |
| --args | -a | Your npm Cypress command arguments | string | |
| --specsDir | -d | Cypress specs directory. | string | cypress/integration |
| --writeWeightFile | -w | if a weights file should be crated | bool | false |
| --threads | -t | Number of threads; must be even # | number | 4 |

# Contributors
Looking for contributors.
* Original Author: https://github.com/tnicola
* Total Test Time: https://github.com/stepn1k
* Updates and cleanup: https://github.com/sezane
* Few small tweaks: me @ https://github.com/finalcut
# License
MIT
78 changes: 55 additions & 23 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ const argv = yargs
alias: 'a',
type: 'string',
description: 'Your npm Cypress command arguments'
}).option('write_weights_file', {
alias: 'wwf',
})
.option('writeWeightFile', {
alias: 'w',
type: 'boolean',
description: `Write ${WEIGHTS_JSON} file ? `
}).argv;
Expand All @@ -40,9 +41,8 @@ if (!CY_SCRIPT) {
}

let N_THREADS = argv.threads ? argv.threads : 2;
const DAFAULT_WEIGHT = 1;
const SPEC_FILES_PATH = argv.specsDir ? argv.specsDir : 'cypress/integration';
const WRITE_WEIGHTS_FILE = argv.write_weights_file ? argv.write_weights_file : false;
const WRITE_WEIGHTS_FILE = argv.writeWeightFile ? argv.writeWeightFile : false;
const CY_SCRIPT_ARGS = argv.args ? argv.args.split(' ') : [];

const COLORS = [
Expand Down Expand Up @@ -75,18 +75,26 @@ const getRandomInt = function (max) {
return Math.floor(Math.random() * Math.floor(max));
};

const formatTime = function(timeMs) {
const seconds = Math.ceil(timeMs / 1000);
const sec = seconds % 60;
const min = Math.floor(seconds / 60);
let res = '';
// function stolen from: https://stackoverflow.com/a/32180863/7329
const formatTime = function(millisec) {
var seconds = (millisec / 1000).toFixed(1);
var minutes = (millisec / (1000 * 60)).toFixed(1);
var hours = (millisec / (1000 * 60 * 60)).toFixed(1);
var days = (millisec / (1000 * 60 * 60 * 24)).toFixed(1);

if (min) res += `${min}m `;
res += `${sec}s`;
return res;
if (seconds < 60) {
return seconds + " Sec";
} else if (minutes < 60) {
return minutes + " Min";
} else if (hours < 24) {
return hours + " Hrs";
} else {
return days + " Days"
}
};

const start = () => {
const startRunTime = new Date().getTime()
const fileList = getAllFiles(SPEC_FILES_PATH);
let specWeights = {};
try {
Expand All @@ -95,6 +103,8 @@ const start = () => {
console.log(`Weight file not found in path: ${WEIGHTS_JSON}`);
}

console.log(`Preparing to run ${fileList.length} spec files. Please wait, the first result may take a bit of time to appear.`)

let map = new Map();
for (let f of fileList) {
let specWeight = getRandomInt(3);
Expand Down Expand Up @@ -156,14 +166,14 @@ const start = () => {
try {
const test = JSON.parse(data);
if (test[0] === 'pass') {
const testDuration = test[1].duration;
suiteDuration += testDuration;
suiteDuration = test[1].duration;
console.log(
`\x1b[32m✔ \x1b[0m${test[1].title} (${testDuration}ms)`
`\x1b[32m✔ \x1b[0m${test[1].title} (${suiteDuration}ms)`
);
}
if (test[0] === 'fail') {
console.log(`\x1b[31m✖ \x1b[0m${test[1].title} ( - ms)`);
suiteDuration = test[1].duration;
console.log(`\x1b[31m✖ \x1b[0m${test[1].title} (${suiteDuration}ms)`);
console.log(`\x1b[31m${test[1].err}`);
console.log(`\x1b[31m${test[1].stack}`);
}
Expand All @@ -187,28 +197,37 @@ const start = () => {
});

let timeMap = new Map();
let threadTimes = []
Promise.all(children).then(resultMaps => {
resultMaps.forEach((m, t) => {
let totTimeThread = 0;
for (let [name, test] of m) {
totTimeThread += test.duration;
}
console.log(`Thread ${t} time: ${formatTime(totTimeThread)}`);
threadTimes.push(totTimeThread)

timeMap = new Map([...timeMap, ...m]);
});

let table = new Table({
head: ['Spec', 'Time', 'Tests', 'Passing', 'Failing', 'Pending'],
style: { head: ['green'] },
colWidths: [25, 8, 7, 9, 9, 9]
colWidths: [45, 25, 7, 9, 9, 9]
});

let totalTests = 0;
let totalPasses = 0;
let totalDuration = 0;
let totalPending = 0;

let totalWeight = timeMap.size * 10;
let specWeights = {};
for (let [name, test] of timeMap) {
totalDuration += test.duration;
totalTests += test.tests;
totalPasses += test.passes;
totalPending += totalPending;
specWeights[name] = { time: test.duration, weight: 0 };
table.push([
name,
Expand All @@ -220,22 +239,35 @@ const start = () => {
]);
}

console.log(table.toString());

Object.keys(specWeights).forEach(spec => {
if (WRITE_WEIGHTS_FILE) {
Object.keys(specWeights).forEach(spec => {
specWeights[spec].weight = Math.floor(
(specWeights[spec].time / totalDuration) * totalWeight
);
});
});

const weightsJson = JSON.stringify(specWeights);
const weightsJson = JSON.stringify(specWeights);

if (WRITE_WEIGHTS_FILE) {
fs.writeFile(`${WEIGHTS_JSON}`, weightsJson, 'utf8', err => {
if (err) throw err;
console.log('Generated file parallel-weights.json.');
});
}

const endRunTime = new Date().getTime()
const totalRunTime = endRunTime - startRunTime


table.push([
'Total Run Time and Final Results',
`${formatTime(totalRunTime)}`,
totalTests,
totalPasses,
totalTests-totalPasses,
totalPending
]);

console.log(table.toString());
});
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cypress-parallel",
"version": "0.1.8",
"version": "0.1.16",
"description": "Reduce up to 40% your Cypress suite execution time parallelizing the test run on the same machine.",
"main": "cli.js",
"repository": {
Expand Down