How to upload Cypress screenshots to Azure
Willian Drygla Cardoso
QA Engineer | QA Analyst | Test Automation | E2E automated tests | QA | Quality Assurance | AWS | Cypress | Jmeter | K6 | Node | Typescript
I wanna share a solution that I have developed to improve my debugging with Cypress and Azure. Cypress takes screenshots of test failures, which give us a lot of context about the failure, but, I didn’t find a way to visualize these screenshots with Azure. So, I looked over the internet and found some articles, I took this as a base, and developed a custom solution. I will bring here step-by-step how I do it.
Basically: grab all Cypress screenshots and simplify they name; Get all test runs for that release; Then Get all failed tests to that release and for each test find a matching screenshot and upload it, let's see:
1- We need to get all screenshots and save its path on a variable to use later, here, comes our first problem, depending of how the test fails, the screenshot name changes, appears a 'before each', 'after each', to make this work, I made a function to simplify the name, it receives the full path, remove unnecessary data, and save to a pathMap, then, after we use the same function to simplify the test case name and look for a match:
function simplifyName(filename: string): string {
????return filename
????????.replace(/ --/g, '')
????????.replace(/"/g, '')
????????.replace(/ \(failed\)\.png/g, '')
????????.replace(/before each hook/g, '')
????????.replace(/after each hook/g, '')
????????.replace(/for/g, '')
????????.replace(/ /g, '');
}
async function collectPngFiles(directory: string, pathMap: Map<string, string>): Promise<void> {
????const entries = await fs.readdir(directory, { withFileTypes: true });
????for (const entry of entries) {
????????const fullPath = path.join(directory, entry.name);
????????if (entry.isDirectory()) {
????????????await collectPngFiles(fullPath, pathMap);
????????} else if (entry.isFile() && entry.name.endsWith('.png')) {
????????????const simplifiedName = simplifyName(entry.name);
????????????pathMap.set(simplifiedName, fullPath);
????????}
????}
}
These two functions save the simplified name and its corresponding full path to a variable pathMap.
2- New, we need to get all failed tests on the release of Azure. To this, I make a get on Azure, that returns all test runs from that release, with that in hand, for each test run, I make a new get, but this time, only searching for failed tests. Then, for each failed test, I apply the same algorithm to simplify its name, then we need to check if there is a screenshot who matches the test case name on the pathMap .
???const testRunResponse = await axios.get(testRunUrl, {
????????????headers: getHeaders()
????????})
????????const listOfRuns = testRunResponse.data.value
????????for (const testRun of listOfRuns[]) {
领英推荐
????????????const testResultsUrl = ${teamFoundationCollectionUri}${teamProjectId}/_apis/test/runs/${testRun.id}/results?api-version=5.1&outcomes=Failed;
????????????const testResultsResponse = await axios.get(testResultsUrl, { headers: getHeaders() });
????????????for (const testResult of testResultsResponse.data.value) {
????????????????let testCaseName = simplifyName(testResult.testCase.name);
????????????????const testResultId = testResult.id;
????????????????const screenshotPath = pathMap.get(testCaseName);
3- When we find a match, between the screenshots taken by Cypress and failed tests on Azure, we need to upload it to Azure on that test run, to be available to check on azure:
???if (screenshotPath) {
????????????????????const screenshotFilenameWithoutPath = path.basename(screenshotPath);
????????????????????const createTestResultsAttachmentUrl = ${teamFoundationCollectionUri}${teamProjectId}/_apis/test/runs/${testRun.id}/results/${testResultId}/attachments?api-version=5.1-preview.1;
????????????????????const base64string = await fs.readFile(screenshotPath, { encoding: 'base64' });
????????????????????const jsonBody = {
????????????????????????fileName: screenshotFilenameWithoutPath,
????????????????????????comment: 'Attaching screenshot',
????????????????????????attachmentType: 'GeneralAttachment',
????????????????????????stream: base64string
????????????????????};
????????????????????const response = await axios.post(createTestResultsAttachmentUrl, jsonBody, {
????????????????????????headers: {
????????????????????????????Authorization: Basic ${btoa(:${personalAccessToken}`)}`,
????????????????????????????'Content-Type': 'application/json'
????????????????????????}
????????????????????});
Then we only need to deal with Azure response.
This is a Typescript script, that is the same of the tests, it runs after tests on Azure. I made this a few months ago, and this is really helping me debug, since I don’t need to run the test locally again to see what is wrong, the context given by the screenshots really helps the understanding.
?I hope it helps somebody with a similar problem!
Here a screenshot that show how the you can see screenshots on Azure test page!
?? Cloud Engineer | AWS Community Builder | 2x AWS Certified
3 个月Interesting, thanks for sharing it ??