Easy way to verify the MD5 checksum of a downloaded file in Test Automation

Easy way to verify the MD5 checksum of a downloaded file in Test Automation

There are many instances during test automation when you would download the files and then would want to verify the completeness of your files downloaded. The MD5 checksum verification is to validate the authenticity of the file so we can ensure that the received file is exactly the same as at the source. This blog explains what MD5 checksum is and also, how we can use it in test automation.

Let’s understand the need for MD5 checksum Verification for a file.

Different kinds of files are distributed on the network or any storage media at different destinations. So, there is a chance that the file can be corrupted because of a few missing bits during data transfer due to some different reasons. Below are a few factors that can cause this to happen, such as:

  •    An interruption to the Internet or network connection.
  •    Storage or space problems, including hard drive-related problems.
  •    A corrupted disk or corrupted file.
  •    A third party interfering with the transfer of data.

After receiving the file, we need to check if the file received is correct or incorrect. It also becomes necessary to verify that our copy of the file is authentic and does not contain any error by applying some sort of test.

We basically use the special key string for this file integrity test known as a checksum. Also, we can refer to checksum as a hash sum or a hash value, hash code, or simply a hash. The most famous and widely used checksum technique is nothing but the MD5 checksum.

the digest, MD5, or hash checksum has been extensively used in the software world to provide some assurance that an uploaded file arrived intact from its source

What is MD5?

The message-digest algorithm(MD5) is a cryptographic hash function whose main purpose is to verify that a file has not been altered.

MD5 hashes are 128 bits long and are usually displayed as their 32-digit hexadecimal equivalents. It doesn’t matter how large or small the file or text is.

For Reference:https://www.intel.com/content/www/us/en/support/programmable/articles/000078103.html

What is the MD5 checksum of a file?

As we learn, it is a 32-character hexadecimal number that is computed on a file. Various Checksum programs are used to generate checksum key strings from the files and verify the integrity of the files. Later by using that checksum string with the original ones shared by the file servers. The file servers often provide a pre-computed MD5, so that a user can compare the checksum of the downloaded file to it. There is a high probability that two files with the same MD5 checksum are the same.

How to calculate MD5 checksum for a file:

1. Calculate MD5 checksum for a file for windows:

With a command prompt, PowerShell command, or third-party applications like Hash Generator or MD5 Checksum Utility, you can generate a checksum for a file. 

a. With the command prompt:

Basically, the command line tool is built-in into the Microsoft Windows 10 operating system, as a certificate service, which is “CertUtil”.

This command line offers a switch, “Hashfile”; We can generate a hash string. Here is a specific algorithm that we can use, such as MD5:

certutil -hashfile <file> <algorithm>           

certutil -hashfile Example.txt MD5

It generates an MD5 file checksum in the command prompt on Windows…

b. With PowerShell:

Since there is no coding, this is the most efficient and easiest method. If PowerShell 4.0 is used then a command line, i.e., cmdlet exists in it.

 This cmdlet can also reffer as “Get-FileHash”. Thanks to this command line, because of that command line we can generate hash files easily:

Get-FileHash -Path <file> -Algorithm <name>

Get-FileHash -Path explorer.exe -Algorithm MD5

Use Get-FileHash in Powershell. It returns the hexadecimal string/hash.

2. Calculate MD5 checksum for a file using some Third Party Tools:

Also, you can find out which tools to use in the right-click menu in a file. Following are some tools we generally can use:

·        Hash Generator

·        MD5 & SHA Checksum Utility.

·      HashMyFiles 

3. Calculate MD5 checksum for a file through automation using C# :

Here, you can calculate programmatically using .net, Java, Python, etc.

To calculate it for a file in C#, .net provides an inbuilt functionality for generating these hash functions, For that reason, we need to import the following NuGet package: https://www.nuget.org/packages/Security.Cryptography

System.Security.Cryptography.MD5

Firstly we need to instantiate the Message Digest Object.

The Compute Hash method of the instance returns the computed hash of the file (bypassing the file stream).

Later, we can convert it to hex, the Bit Converter allows you to represent it as a string for conversion.

So, below is an example code showing a method (GetMD5HashFromFile ()).

It accepts the file name along with the path and then returns the calculated checksum. Also, generates the checksum, After that, it converts into a hex string, and removes dashes. This is the typical format.

The hash string for the file returned by this method can be compared with the one provided by the file servers and checked if the file is altered or not.

private string GetMD5HashFromFile(string fileName)
       using (var md5 = MD5.Create())
       {
                using (var stream = File.OpenRead(fileName))
                 {
                       var hash= md5.ComputeHash(stream);
                      return BitConverter.ToString(hash).Replace("-", string.Empty);
              }
         }

You can call the above function wherever you need to get the checksum. For example:

void verifyChecksum()
{
string filePath = "../../../Resources/test.pdf";
string hash = GetMD5HashFromFile (filePath);
Assert.Equal("A152F13B6EE1EA3D047A6AB99D12A1A1", hash);
}

Conclusion:

As I have implemented and tested this in a test case automation, so, I believe this is a most simple and easier way to verify MD5 checksums for a file in automation using C#

Read more blogs here

How to Create Click-up issues on failed tests using Cypress?

How to Create Click-up issues on failed tests using Cypress?

The purpose of this blog is to provide an overview of Create Click-up issues on failed tests using Cypress for reporting bugs during testing or when automated tests are failed. Click-up is a cloud-based collaboration and project management tool suitable for all team sizes to adopt as an Application Lifecycle Management tool. In our context, we will use it to create bug tasks for failed tests.

In this blog, we will have a quick overview of:-
  • What is Click-up?
  • What is Click-up API and how to use them?
  • How to automate the Click API using cypress.
  • How To create a task automatically when a Cypress test fails with Screenshots.
Requirements:-
  • Node.js to be installed.
  • Any IDE recommended is VS Code.
  • Cypress 10 or any version of Cypress installed.
  • Click-up account.
Now let’s start with our agenda

What is Click-up?

It is a project management tool that is easy to customize and use.

What are Click-up API and how do use them?

Click API  is a service provided by Click-up through which you can operate Click-up without UI.

You can find more information about this by visiting this page:-https://clickup.com/api

We can use them through API client tools like the postman or you can use them in any programming language/ technology which supports HTTPS protocols. In this blog, we are using the Cypress testing tool which is Node.js-based technology using JavaScript as a programming language.

How to automate the Click-API using Cypress?

Cypress’s cy.request API module helps you to automate API quickly.

How to create a task automatically when a Cypress test fails with Screenshots.

Requirements.
  • Personal access token for Click-up.
  • Postman or any API client tool.
  • List Id, Folder Id, Space Id, and Team id of Click-up workspace. 
Let’s see how can we get the personal access token for Click-up:-
  1. Navigate to your personal Settings. 

2. Click Apps in the left sidebar.

3. Click Generate to create your API token.

4. Click Copy to copy the key to your clipboard.

Note:- You can use this personal access token in API for authentication. 

 Get the Team Id 

This endpoint is used to view teams: user groups in your workspace. Use the following API request in postman or any other API client tool for getting the team id which needs to pass as a URI parameter to get the Space id.

Request:- https://api.clickup.com/api/v2/team

Method:- GET

Headers: key:- Authorization

Value:-Personal access token 

Response JSON:

{
    "teams": [
        {
            "id": "33131480",
        }
             ]
 }
Now we need to get the Space Id

View the spaces available in a workspace.

Request:-https://api.clickup.com/api/v2/team/<team_id>/space

Method:-GET

Headers: key:- Authorization

               Value:-Personal access token 

Response JSON

{
    "spaces": [
        {
            "id": "1236491",
        }
              ]
}

Till now we have fetched responses of two endpoints

Let’s get the folder id 

View the folders in space.

Request:-https://api.clickup.com/api/v2/space/<space_id>/folder

Method:-GET

Headers: key:- Authorization

               Value:-Personal access token 

Response JSON

{
    "folders": [
        {
            "id": "34231390",
            "name": "Product Roadmap",
            "orderindex": 0,
            "override_statuses": true,
            "hidden": false,
            "space": {
                "id": "3376891",
                "name": "New Space"
                     }
       }
               ]
}
Now The last thing to get is a List of id 

View the lists within a folder.

Request:- https://api.clickup.com/api/v2/folder/<folder>/list

Method:-GET

Headers: key:- Authorization

               Value:-Personal access token 

Response JSON:

{
    "lists": [
        {
            "id": "7623172",
            "name": "Jan",
            "orderindex": 2,
            "status": null,
            "priority": null,
            "assignee": null,
            "task_count": 2,
            "due_date": "1612045800000",
            "start_date": "1609453800000",
            "folder": {
                "id": "3488090",
                "name": "Product Roadmap",
                "hidden": false,
                "access": true
        }
      }
     ]
}

We have fetched all the required Uri parameters for getting the list id now we can use this list id as a Uri parameter for generating tickets through automation using cypress

  •  How to create a task automatically when a cypress test fails with screenshots.

We have successfully extracted the list id which we will be using as a Uri parameter for creating a task. The cypress “command.js” file is a  file where we have to place reusable code inside that we have the “cypress.command.add” method so we can use that code anywhere in cypress tests.

Paste the following code in Cypress/ Supports/ Command.js

Below is create task method name and we are passing the feature name, scenario name, and steps as a parameter which will be added to the ticket in Click-up

Cypress.Commands.add("CreateTask",(featurename,scenarioname,allsteps)=>

Now to call the endpoint with cy.request we will require the endpoint, the request method, and the access token, so we will store everything in a variable and access in the below code.  mention all endpoints, request methods, and access tokens as variables. 

let endpoint = 'https://api.clickup.com/api/v2/list/<listid>/task'
    let req = 'POST'
    let token = Access_Token '
    const headers = {
        'Authorization': token,
        'Content-Type': 'application/json'
                    }

We are passing all the variables to the cy.request which we mentioned above.

Calling API:- This API will create a ticket for us and the response that we yield will give the id of the ticket which we can use to attach a screenshot in the next request.

cy.request({ method: req, url: endpoint, 'headers': headers, body: body }).then((response) => {
        cy.log(JSON.stringify(response))
        id = response.body.id
        Getting the Response 
        cy.log(id)

In this case, we are getting the id of the ticket which we can use in the next request as a Uri parameter. Now we need to get the path of the failed screenshot dynamically and pass it to the API so that screenshot should get attached to the same click-up ticket.

The below code will attach a screenshot to the ticket which we have created through automation.

const screenshotsFolder = Cypress.config("screenshotsFolder");
         
            const screenshotFileName = `${featurename} -- ${scenarioname} (failed).png`;
Attaching ScreenShot
            cy.request("https://clickup.com")
 var data = new FormData();
            data.append("filename", screenshotFileName);
            cy.log(id)

We have to attach a screenshot as multipart form data and pass it as a Blob as a request for the above ticket which we have created. Here we have used XMLHttp request as cy.request does not support multipart form data.

                cy.intercept({
                method: "POST",
                url: "https://api.clickup.com/api/v2/task/"+id+"/attachment?custom_task_ids=false&team_id=3344860"
            }).as('uploadFile')
                .window()
                .then((win) => {
                    cy.wait(3000)

Here we are reading the screenshot file and creating Blob and passing it as a binary.

cy.readFile(`${screenshotsFolder}/${Cypress.spec.name}/${screenshotFileName}`, 'binary')
                        .then((binary) => Cypress.Blob.binaryStringToBlob(binary))
                        .then((blob) => {
                            const xhr = new win.XMLHttpRequest();
                            data.set("attachment", blob, `${screenshotsFolder}/${Cypress.spec.name}/${screenshotFileName}`);
                            xhr.open("POST", "https://api.clickup.com/api/v2/task/"+id+"/attachment?custom_task_ids=false&team_id=3344860");
                            let token = Access_Token

We have used XMLHttp request to process and send multipart form data in the request.

 xhr.setRequestHeader('Access-Control-Allow-Headers', '*')
                            xhr.setRequestHeader("Authorization", token);
                            xhr.send(data);
                        })
                })
            cy.wait('@uploadFile').then((response) => {
                cy.log(response)
            })
})
}) 

Now when the test fails this part of the code will get executed which will call the method mentioned in the command.js file and automatically create the ticket with a failed screenshot and description.

Paste the code in Cypress/Beforeafter.js.
afterEach(() => {

This Code Will Execute after each test
   cy.on("test:after:run", (test, runnable) => {
      setTimeout(() => {
            Cypress.env("ok",test)
      }, 4000);         
        }).then(()=>
        {

Now we have to extract the feature file name, scenario name, and steps so that we can pass it to the Click-up ticket. We have a test state as a window object which yields all the properties related to the test like test name, test status, etc…

cy.wait(6000)
          let chip = Cypress.env("ok")
          let status = chip.state
          let scenario = chip.title
          let allsteps = ""
          let Featurename = testState.gherkinDocument.feature.name
       let current = chip._testConfig.testConfigList[0].overrides.env.__cypress_cucumber_preprocessor_dont_use_this.currentStep.pickleStep.text
         let a = chip._testConfig.testConfigList[0].overrides.env.__cypress_cucumber_preprocessor_dont_use_this.allSteps
          for (let index = 0; index < a.length; index++) {
              const element = a[index]      
              allsteps += element.pickleStep.text
          }

Calling the custom command which will create a ticket every time the test fails. Passing the feature name scenario name and all steps as parameters to be added to the ticket.

This will create a ticket in Click-up. 

cy.CreateTask(Featurename,scenario,allsteps)
        })
                })
  • The task will be created in Click-up as shown below in the screenshot:-
Conclusion:-

We can create tasks with screenshots attachments for failed test cases using click-up APIs and automate them using Cypress automation.

Read more blogs here

How to Skip Authentication in test automation using Playwright

How to Skip Authentication in test automation using Playwright

Every software application identifies, recognizes, and authenticates the user trying to access the system using some type of credentials (i.e Username and password). And once the user is verified/authenticated, that user is granted permission to access authorized resources.

So, while testing the software application for every test case, the first step we perform is the login step.

If the test suite consists of 100+ test cases, then the step of logging in to the application will be performed for each test case. You can imagine the unnecessary time that will consume for logging in to the application each time for all those 100+ test cases.

Can we find a way to reduce the time required for logging in to the application for every test case? or can we skip logging in to the software application altogether?

This is where Playwright comes into the picture.

The playwright is an open-source test automation tool created by Microsoft. It is a cross-platform tool and has a set of features like Test Generator (codegen), Trace viewer, Inspector, etc, and the most important feature of Playwright which will help us to skip authentication in test automation is full isolation with browser context.

In addition, you can refer to the official document on playwright basic authentication.

First Off, we will have to login into the application via UI and reuse the authentication state in different and multiple scenarios using the browser context.

Let’s see how we can do it.

First, we are going to create a GenerateSession.java class where all of our own logical and automated login steps will be implemented,

Code:

import com.microsoft.playwright.*;
import java.nio.file.Paths;
public class GenerateSession {

        Playwright playwright = Playwright.create();
        Browser browser = playwright.chromium().launch(new      BrowserType.LaunchOptions().setHeadless(false));
        BrowserContext browserContext = browser.newContext();

        Page page = browserContext.newPage();
        page.navigate(BASE URL);
        page.fill("//*[@id=\"username\"]",USERNAME);
        page.fill("//*[@id=\"password\"]",PASSWORD);
        page.click("//*[@id=\"Login\"]");

So, what we did here is, launched the browser and created a new page.

In BrowserContext browserContext = browser.newContext();
we have created a browser context. This browserContext will store our authentication state i.e it will store the session, cookies, local storage, etc.

As you can see, we created the browser context browserContext, but the question here is, where will this authentication state (browserContex) will be stored?

The best way to store this browser context in a .json file.

The playwright provides a method called storageState() which will help us store the authentication state.

browserContext.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("appLoginInfo.json")));

The above code snippet will store the authentication state, cookies, local storage, etc in json format in appLoginInfo.json file.

If the appLoginInfo.json file is not created then the playwright will create a new file with the provided name appLoginInfo.json at the provided location in setPath(Paths.get(“appLoginInfo.json”)));

If you have the appLoginInfo.json file already created, each time you execute the above snippet, a new authentication state with cookies and local storage will be overwritten in the appLoginInfo.json file.

Now, we are all set up with our authentication state, cookies, and local storage. Our next question is

How do we use that authentication state and skip login for each scenario?

We can use a Playwright to skip authentication scenarios. As we all know, Web applications use cookies and token-based authentications. These authentications are stored in the form of cookies or local storage. The playwright provides us with methods that can store these authentication state and then create a new browser context with the previously restored session, which in turn help us skip login/authentication for the scenarios.

Here, we will set the stored authentication state using the methods above to the new browser context created for each scenario we run.

The playwright provides us with a method newContext()  which will create a new browser context.

And by using NewContextOptions(), we can add/set the stored authentication state in the appLoginInfo.json file.

Let’s look at how we can do it in the code snippet below.

BrowserContext brContext = browser.newContext(new Browser.NewContextOptions().

setStorageStatePath(Paths.get("appLoginInfo.json")));

Here, setStorageStatePath(Paths.get(“appLoginInfo.json”))will set the authentication state stored in appLoginInfo.json to the new browser context created in the previous step.

So, every time we execute the above code snippet, the browser context that is stored in appLoginInfo.json file will be set to the new browser context and the previous session will be restored.

Please refer to the methods listed below. I used these methods to skip authentication scenarios for one of the Salesforce apps.

        @Test
        public void generateSessionCookies() throws InterruptedException {
        Playwright playwright = Playwright.create();
        Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
        BrowserContext browserContext = browser.newContext();
        Page page = browserContext.newPage();
        page.navigate("BASE URL");
        page.fill("//*[@id=\"username\"]", "USERNAME");
        page.fill("//*[@id=\"password\"]", "PASSWORD");
        page.click("//*[@id=\"Login\"]");
        page.click("//*[@id=\"save\"]");
        browserContext.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("appLoginInfo.json")));
        page.close();
}
         @Test
         public void useSavedSessionCookies() throws InterruptedException {
         Playwright playwright = Playwright.create();
         Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
         BrowserContext browserContext = browser.newContext();
         Page page = browserContext.newPage();
         browserContext.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("appLoginInfo.json")));
         page.close();
}

Conclusion:

In this way, Playwright helps us to store the authentication state, cookies, local storage, etc. And we can use this authentication state and set it to our new browser context and restore the previous session, which will in turn help us skip the login step for the n number of scenarios for a software application.

I hope this article has served you well. 

Read more blogs here

Inspecting Webview App Element using Chrome Extension

Inspecting Webview App Element using Chrome Extension

Inspecting the WebView element using the Chrome browser is the easiest and most efficient way. So in this blog, I am going to explain how to inspect the WebView element using the chrome browser. Let’s first understand what WebView is and why to use it.

What Is A WebView?

It is widely used to display web pages in an application. The web pages and web apps can reuse in an Android application. The content used to display inside a WebView is responsive and mobile-friendly and because of this, it works better towards providing a better user experience.

Now let’s see how to inspect elements on Android WebView

1) The first step is you need to connect your mobile device to your system.

2) The second step is you need to go to your chrome browser and go to chrome://chrome-urls/ then you will see the result like the below screenshot:

3) You need to select “chrome://inspect/” from that list.

4) Click on it and it will open a window like this. There is an option to discover USB devices in it. It will display information about the devices that are currently attached to the system.

5) Now launch the app on your mobile device, and for inspecting the element just click on inspect.

This will open a new chrome window containing all the UI details of that screen.

Now you can inspect the elements for the webview app like you inspect for the website. By following these steps you will get a better understanding of how you can inspect a webview using a chrome browser and how you can locate your desired elements.

Below is the link for your reference to inspect webViews and get locators.

http://www.qaautomationsimplified.com/android/android-automation-how-to-inspect-webviews-and-get-locators/

Conclusion:

According to my experience, this is the most effective and easier way to inspect WebView elements using the chrome browser.

Read more blogs here

How to set an automatic backup of your source code repository?

How to set an automatic backup of your source code repository?

One day my colleague David was working on a task to migrate a repository from one platform to another while he was doing that the server crashed, the platform went down and all the data, code, and documentation available on the repository was lost. Have you ever imagined yourself in David’s Situation, What if this happens to you? Wondering what solution you can use instead of manual efforts?

You’re not alone.

We faced the same problem and found one of the best automation solutions that will work on all the platforms.

Problem:

We want to protect our source code repositories at any cost. It contains all of our code, documentation, and work history.

The real nightmare comes when you don’t have a backup. We all know that taking frequent backups manually is a tedious process.

So how can we do that through automation?

Solution:

There are many solutions to that. We have used this solution because it is based on bash script and works on all the platforms like Azure DevOps, Gitlab, and Bitbucket.

We are copying the Azure DevOps repository to GitHub. But as we said we can use this solution on every platform.

  1. First, log in to your GitHub account and create a GitHub repository. (If you don’t have it already)
  2. You have to generate a Personal access token at GitHub.

Settings -> Developer Settings -> Personal Access tokens

Generate and copy the token value. (refer to the following screenshot)

C:\Users\Uddhav\Desktop\Blogs\A2G\Untitled.png

3. Navigate to your Azure repository. And create a pipeline there.


4. Add the following bash script task to the pipeline.

What will this script do?

This script will override the branch code of GitHub. In simple words, if you want to copy code from the feature branch of Azure to GitHub then:

  1. In GitHub – If the feature branch is present, it will override the code.
  2. In GitHub – if the feature branch is not present, then the branch will be created.
bash: |
git push -- \
Prune //ghp_iYwH9mwvmWVAFCD@github.com/SpurQLabs/SpurQLabsProject \
+refs/remotes/origin/master:refs/heads/master +refs/tags/:refs/tags/
displayName: 'Copy to GitHub'
condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
Note:

If your branch (in Azure) is master then no need to change but if your branch is main then you should replace the “master” with “main”.

Be Careful:

If you already have a repository (With Code)  in GitHub, then instead of main or master use the feature branch in Azure.  And then raised PR to the main branch.

And if you want to update code from the main branch from Azure to the main branch from GitHub then no worries. You are good to go. (It will override main branch code, if not there then will create a new one.).

  • You can trigger your pipeline according to your requirements.
  • If you want to schedule it on a daily, weekly, or monthly basis then you can use the “schedule”&”cron” options in the pipeline.
  • Below is the link for your reference to schedule the pipeline

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/scheduled-triggers?view=azure-devops&tabs=yaml

Run your pipeline.

  And Done and Dusted..!

#Azure-pipeline.yml for reference

#Azure-pipeline.yml for reference
trigger:
- DemoSync #your feature Branch, Run this pipeline from your feature branch.
pool:
  vmImage: ubuntu-latest
steps:
- checkout: self
- bash: |
    git push --prune https://ghp_cbvnn@github.com/SpurQLabs/SpurQLabsProject \
    +refs/remotes/origin/DemoSync:refs/heads/DemoSync +refs/tags/*:refs/tags/*
  displayName: 'Copy to GitHub'
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/DemoSync')

Conclusion

This is how the source code is migrated from azure repositories to GitHub repositories automatically after every check-in/PR merge.

As mentioned above, you can schedule it daily, Weekly, or monthly.

Read more blogs here