How to upload Cypress screenshots to Azure

How to upload Cypress screenshots to Azure

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!

The picture show as the Azure tests page, where we can select a test run, see its scenarios, and in attachments, visualize the screenshot we uploaded


Marcos Henrique

?? Cloud Engineer | AWS Community Builder | 2x AWS Certified

3 个月

Interesting, thanks for sharing it ??

要查看或添加评论,请登录

Willian Drygla Cardoso的更多文章

社区洞察

其他会员也浏览了