DEV Community

Will Drygla
Will Drygla

Posted on

2 1 1 1

Uploading screenshots to Azure tests

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:

  1. Grab all Cypress screenshots and simplify they name
  2. Get all test runs for that release
  3. Then Get all failed tests to that release
  4. 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- Now, 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!

Screenshot that show how the uploaded screenshot of cypress appears on the Azure test page

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay