Skip to content

Commit

Permalink
feat: provide option to overwrite historyId hash with own function, a…
Browse files Browse the repository at this point in the history
…ddress #209
  • Loading branch information
Oleksandr Shevtsov committed Jun 8, 2023
1 parent fdd7d83 commit 8af1143
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 19 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,35 @@ It will be used for:

In lower versions some other heuristics would be used, but they are not as reliable as `after:spec`.

## Test name duplicates

By default Allure calculates hash from test title to identify test and show its' proper previous results.
This may lead to tests having the same name being counted by allure as retries of the same test.
There are several ways to avoid this situation:
- the best way to avoid it is basically using unique test names
- update specific test name
```js
cy.allure().testName('new_test_name')
```
- specify your own function for all tests to not only take test.title, but also concatenate it with some other information in `cypress/support/index` or `cypress/support/e2e.js` file, for example:
- use relative spec file path like "cypress/e2e/results2/test.cy.js" and test title:
```js
Cypress.Allure.reporter.getInterface().defineHistoryId((title) => {
return `${Cypress.spec.relative}${title}`;
});
```
- use browser name and test title:
```js
Cypress.Allure.reporter.getInterface().defineHistoryId((title) => {
return `${Cypress.browser.name}${title}`;
});
```
The rule is that this function should return any string (folder name, project name, platform, browser name, Cypress.spec content, etc.), and if those strings will be different - their test historyId hashes will be different - tests will be recognized as different by allure.
## Suite structuring
Allure support 3 levels of suite structure:
Expand Down
7 changes: 7 additions & 0 deletions reporter/allure-cypress/AllureInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ Allure.prototype.defineSuiteLabels = function (defineSuiteLabelsFn) {
this.reporter.defineSuiteLabelsFn = defineSuiteLabelsFn;
};

Allure.prototype.defineHistoryId = function (defineHistoryId) {
if (!defineHistoryId) {
return;
}
this.reporter.defineHistoryId = defineHistoryId;
};

Allure.prototype.label = function (name, value) {
if (this.reporter.currentTest && !this.reporter.currentHook) {
const labelIndex = (name) =>
Expand Down
3 changes: 2 additions & 1 deletion reporter/allure-cypress/AllureReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = class AllureReporter {
this.gherkin = new CucumberHandler(this);
this.config = options;
this.defineSuiteLabelsFn = (titles) => titles;
this.defineHistoryId = (testTitle) => testTitle;
}

/**
Expand Down Expand Up @@ -221,7 +222,7 @@ module.exports = class AllureReporter {
}

this.currentTest.info.historyId = crypto
.MD5(test.title)
.MD5(this.defineHistoryId(test.title))
.toString(crypto.enc.Hex);
this.currentTest.info.stage = Stage.RUNNING;
this.addPackageLabel();
Expand Down
5 changes: 5 additions & 0 deletions reporter/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ declare global {
fileInfo: SuiteLabelFunctionFileInfo
) => string[]
): void;

/**
* Specify string which will be used to calculate historyId for test
*/
defineHistoryId(fn: (testTitle: string) => string): void;
}
}
}
3 changes: 2 additions & 1 deletion reporter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ const invokeResultsWriter = (allure, isGlobal) => {
files: allure.reporter.files || [],
mapping: allure.reporter.mochaIdToAllure,
clearSkipped: config.clearSkipped(),
isGlobal
isGlobal,
defineHistoryId: allure.reporter.defineHistoryId
},
{ log: false }
).catch((e) =>
Expand Down
1 change: 1 addition & 0 deletions reporter/stubbedAllure.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ const stubbedAllure = {
testParameter: () => {},
testName: () => {},
defineSuiteLabels: () => {},
defineHistoryId: () => {},
logCommandSteps: () => {}
};
6 changes: 4 additions & 2 deletions writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ function allureWriter(on, config) {
files,
mapping,
clearSkipped,
isGlobal
isGlobal,
defineHistoryId
}) => {
const { resultsDir: relativeResultsDir, writer } = results;

Expand All @@ -76,7 +77,8 @@ function allureWriter(on, config) {
clearSkipped,
writer,
allureMapping,
isGlobal
isGlobal,
defineHistoryId
});

return null;
Expand Down
2 changes: 1 addition & 1 deletion writer/clearEmptyHookSteps.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const logger = require('../reporter/debug');

const clearEmptyHookSteps = (test) => {
if (!test.steps.length) {
if (!test || !test.steps || !test.steps.length) {
return test;
}

Expand Down
8 changes: 6 additions & 2 deletions writer/customTestName.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
const crypto = require('crypto-js');
const logger = require('../reporter/debug');

const overwriteTestNameMaybe = (test) => {
const defaultHistoryId = (title) => title;

const overwriteTestNameMaybe = (test, defineHistoryId) => {
const historyIdFn = defineHistoryId || defaultHistoryId;

const overrideIndex = test.parameters.findIndex(
(p) => p.name === 'OverwriteTestName'
);
Expand All @@ -10,7 +14,7 @@ const overwriteTestNameMaybe = (test) => {
logger.writer('overwriting test "%s" name to "%s"', test.name, name);
test.name = name;
test.fullName = name;
test.historyId = crypto.MD5(name).toString(crypto.enc.Hex);
test.historyId = crypto.MD5(historyIdFn(name)).toString(crypto.enc.Hex);
test.parameters.splice(overrideIndex, 1);
}
return test;
Expand Down
1 change: 1 addition & 0 deletions writer/handleMultiDomain.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const sanitizeSuites = (folder, files = [], isGlobal = false) => {
(file) =>
file.historyId === child.historyId &&
file.uuid !== child.uuid &&
file.steps &&
file.steps.length
);

Expand Down
63 changes: 51 additions & 12 deletions writer/results.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,13 @@ const writeSuites = ({ groups, resultsDir, tests, clearSkipped }) => {
});
};

const writeTests = ({ tests, resultsDir, clearSkipped, allureMapping }) => {
const writeTests = ({
tests,
resultsDir,
clearSkipped,
allureMapping,
defineHistoryId
}) => {
if (!tests || !tests.length) {
return;
}
Expand All @@ -140,7 +146,7 @@ const writeTests = ({ tests, resultsDir, clearSkipped, allureMapping }) => {
const fileName = `${test.uuid}-result.json`;
logger.writer('write test "%s" to file "%s"', test.name, fileName);
const testResultPath = path.join(resultsDir, fileName);
const updatedTest = overwriteTestNameMaybe(test);
const updatedTest = overwriteTestNameMaybe(test, defineHistoryId);
const testResult = clearEmptyHookSteps(updatedTest);
fs.writeFileSync(testResultPath, JSON.stringify(testResult));
});
Expand Down Expand Up @@ -172,7 +178,10 @@ const catchError = (fn, ...args) => {
try {
fn(...args);
} catch (e) {
process.stdout.write(`error while writing allure results: ${e}`);
const entity = args[args.length - 1];
process.stdout.write(
`error while writing allure results for ${entity}: ${e}`
);
logger.writer('failed to write allure results: %O', e);
}
};
Expand All @@ -183,7 +192,8 @@ const writeResultFiles = ({
clearSkipped,
writer,
allureMapping,
isGlobal
isGlobal,
defineHistoryId
}) => {
!fs.existsSync(resultsDir) && fs.mkdirSync(resultsDir, { recursive: true });

Expand All @@ -192,20 +202,49 @@ const writeResultFiles = ({
const { groups, tests, attachments, envInfo, categories, executorInfo } =
writer;

catchError(writeAttachmentFiles, { files, resultsDir, tests });
catchError(writeSuites, { groups, resultsDir, tests, clearSkipped });
catchError(writeTests, { tests, resultsDir, clearSkipped, allureMapping });
catchError(writeAttachments, { attachments, resultsDir });
catchError(handleAfterTestWrites, { resultsDir, isGlobal });
catchError(writeAttachmentFiles, { files, resultsDir, tests }, 'files');
catchError(
writeSuites,
{ groups, resultsDir, tests, clearSkipped },
'suites'
);
catchError(
writeTests,
{
tests,
resultsDir,
clearSkipped,
allureMapping,
defineHistoryId
},
'tests'
);
catchError(writeAttachments, { attachments, resultsDir }, 'attachments');
catchError(
handleAfterTestWrites,
{ resultsDir, isGlobal },
'after test writes'
);

const allureResultsPath = (file) => path.join(resultsDir, file);

catchError(writeInfoFile, allureResultsPath('categories.json'), categories);
catchError(writeInfoFile, allureResultsPath('executor.json'), executorInfo);
catchError(
writeInfoFile,
allureResultsPath('categories.json'),
categories,
'cetegories file'
);
catchError(
writeInfoFile,
allureResultsPath('executor.json'),
executorInfo,
'executor file'
);
catchError(
writeEnvProperties,
allureResultsPath('environment.properties'),
envInfo
envInfo,
'env file'
);
logger.writer('finished writing allure results');
};
Expand Down

0 comments on commit 8af1143

Please sign in to comment.