<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sonikasinghh</title>
    <description>The latest articles on DEV Community by Sonikasinghh (@dawsonn).</description>
    <link>https://dev.to/dawsonn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F974802%2Fdaa3d330-ce09-4165-ad64-8e9ec0d70508.png</url>
      <title>DEV Community: Sonikasinghh</title>
      <link>https://dev.to/dawsonn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dawsonn"/>
    <language>en</language>
    <item>
      <title>Cypress Best Practices For Test Automation</title>
      <dc:creator>Sonikasinghh</dc:creator>
      <pubDate>Tue, 22 Nov 2022 09:27:02 +0000</pubDate>
      <link>https://dev.to/testmuai/cypress-best-practices-for-test-automation-32am</link>
      <guid>https://dev.to/testmuai/cypress-best-practices-for-test-automation-32am</guid>
      <description>&lt;p&gt;Cypress is an amazing framework for testing your frontend applications. However, there are mistakes that you can make which can cause you to slow down your development and testing processes. You could face challenges that are difficult to surpass, like handling authentication and dealing with web servers, or even worse, dealing with third-party authentication providers, etc.&lt;/p&gt;

&lt;p&gt;In this blog on Cypress best practices, I will show you the best practices of &lt;a href="https://www.lambdatest.com/blog/cypress-test-automation-framework/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress automation&lt;/a&gt; and the common mistakes people make when writing the test code while performing &lt;a href="https://www.lambdatest.com/cypress-e2e-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress E2E testing&lt;/a&gt;. I will also show you how to avoid these mistakes to make your development process faster, free from bugs, and constant code refactoring.&lt;/p&gt;

&lt;p&gt;Here are the key learning points from the blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to model your tests based on a real application?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you write effective tests in isolation?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Freeing yourself from page objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choosing an effective testing strategy for logging in to your application&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to leverage direct access to its state?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cypress is amazing overall, but if you don’t do it the right way and don’t follow the Cypress best practices, the performance of your tests will decrease drastically, you will introduce unnecessary errors, and your test code will be unreliable and flaky.&lt;/p&gt;

&lt;p&gt;For example, your code may work today and break tomorrow after a third-party provider adds some changes to their website.&lt;/p&gt;

&lt;p&gt;This blog will teach you the Cypress best practices to never make such mistakes and write reliable, high-quality test codes while performing &lt;a href="https://www.lambdatest.com/cypress-e2e-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress testing&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Cypress?
&lt;/h2&gt;

&lt;p&gt;Cypress is also widely used for E2E (end to end) testing, so you don’t have to separate your tests and write your front-end, back-end, and database tests separately. Instead, you can replicate real user scenarios and use Cypress for &lt;a href="https://www.lambdatest.com/blog/all-you-need-to-know-about-end-to-end-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;end-to-end testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;According to the State of JS 2021 survey, Cypress is the third most popular testing framework, showing that many developers and QA engineers are switching to the &lt;a href="https://www.lambdatest.com/blog/cypress-test-automation-framework/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress test automation framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2476%2F0%2AJ5w3dL0llA0to-2S.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2476%2F0%2AJ5w3dL0llA0to-2S.png" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though Cypress is a relatively new kid on the block; it has quickly established its position as the test automation framework of choice for JavaScript applications, as evident from the number of Forks (2.4K) and Stars (38.9K) on GitHub for the project. Cypress’ popularity can be attributed to some handy features such as a runtime inspector, time travel debugging, an ability to run tests in parallel, and plugins.&lt;/p&gt;

&lt;p&gt;The ever-increasing downloads for Cypress speak a lot about the popularity of this open-source test automation framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3428%2F0%2Aak0NbCIKi_m7aHBn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3428%2F0%2Aak0NbCIKi_m7aHBn.png" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, the Cypress Community is a thriving environment that features plenty of learning opportunities. It is well-moderated and provides you with access to top minds in software testing and web development. Apart from the active Cypress community, there are Cypress Ambassadors that you can use to learn from. Cypress Ambassadors are experienced developers and engineers that have created amazing applications using Cypress.&lt;/p&gt;

&lt;p&gt;As compared to other testing frameworks like &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;, Cypress is picking up pace. If you are coming from a Selenium background and intrigued to know more about the &lt;a href="https://www.lambdatest.com/cypress-automation-tool?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress automation tool&lt;/a&gt;, you can check out the &lt;a href="https://www.lambdatest.com/blog/cypress-vs-selenium-comparison/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium vs Cypress&lt;/a&gt; comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cypress best practices for testing
&lt;/h2&gt;

&lt;p&gt;One thing that is fondly mentioned in &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automation testing&lt;/a&gt; is “&lt;strong&gt;No amount of bad code can be fixed with automation.&lt;/strong&gt;” What this essentially means is that the maximum &lt;a href="https://www.lambdatest.com/blog/how-do-you-calculate-your-roi-on-test-automation-with-selenium/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;ROI from test automation&lt;/a&gt; can be attained if we follow the best practices of the framework that is being used to write automation tests.&lt;/p&gt;

&lt;p&gt;As per my experience with &lt;a href="https://www.lambdatest.com/cypress-ui-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress UI testing&lt;/a&gt;, here are some of the Cypres best practices to &lt;a href="https://www.lambdatest.com/blog/avoid-anti-patterns-in-cypress/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;avoid Anti-patterns in Cypress&lt;/a&gt; that should be leveraged to come up with top-notch automation tests:&lt;/p&gt;

&lt;h2&gt;
  
  
  Login programmatically
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Using the UI to log in&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Programmatically log into the application and widely use the application’s state&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing protected routes", () =&amp;gt; {
 beforeEach(() =&amp;gt; {
   cy.visit("/login")
   cy.get('[data-cy="email"]').type("jon@example.com")
   cy.get('[data-cy="password"]').type("password")
   cy.get('[data-cy="submit"]').click()
 })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This gets your job done. But the problem with this is that this uses your application UI for authentication, and after the authentication is done, it redirects to the page that you want.&lt;br&gt;
This also means the login page must work before any other specific page you want to test. This style of writing tests is not in isolation, which is not among Cypess best practices.&lt;/p&gt;

&lt;p&gt;Let’s say you want to test the settings page. To do that, you log in and introduce the login page, which means you have failed the test in isolation. This will also be extremely time-consuming and counterproductive if you have hundreds of pages. If the process of logging in and redirecting to the desired page takes 1.0 seconds, it will increase the testing time by 100 seconds if you have a hundred pages.&lt;/p&gt;

&lt;p&gt;The better approach for this is to log in programmatically. What does that mean?&lt;/p&gt;

&lt;p&gt;Let’s first see how authentication happens when someone logs in. Most of the time, the user sends an email and password through a POST request to the backend server, and the server will send back the user data and a token to the client.&lt;/p&gt;

&lt;p&gt;The client saves that token in the browser’s local storage and sends it in the authorization header whenever another request is sent to the backend. This way, the backend can identify which user has sent the request.&lt;/p&gt;

&lt;p&gt;To sign in programmatically, we need to use another Cypress command called Cypress request &lt;strong&gt;cy.request()&lt;/strong&gt;. The method makes HTTP requests outside the constraints of the browser. It’s not bound by CORS or any other security restrictions.&lt;/p&gt;

&lt;p&gt;Let me touch base on what is CORS? CORS stands for Cross-Origin Resource Sharing. It is an HTTP header-based mechanism that helps servers indicate the origins in which the browsers send the request. Most servers only allow requests from specific trusted origins.&lt;/p&gt;

&lt;p&gt;Coming back to &lt;strong&gt;cy.request()&lt;/strong&gt;, the awesome thing about &lt;strong&gt;cy.request()&lt;/strong&gt; is that it uses the browser’s user agent and cookie store, so it behaves exactly as the request did come from the browser, but it is not bound by the restrictions.&lt;/p&gt;

&lt;p&gt;In a nutshell, the difference between &lt;strong&gt;cy.request()&lt;/strong&gt; and &lt;strong&gt;cy.visit()&lt;/strong&gt; is that &lt;strong&gt;cy.visit()&lt;/strong&gt; redirects and uses the browser to visit the indicated URL, which means when you visit a URL with &lt;strong&gt;cy.visit()&lt;/strong&gt; it will open up in the browser and downloads all the assets of the page and runs all the JavaScript code.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;cy.request()&lt;/strong&gt; only sends HTTP requests to a URL; you can not see it visually, and it does not download any website assets or run any JavaScript code.&lt;/p&gt;

&lt;p&gt;What we can do now is send a POST request to our backend server with the email and password in the request body using &lt;strong&gt;cy.request()&lt;/strong&gt;, and after we get back the response, we will save the token in our browser’s local storage.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing protected routes", () =&amp;gt; {
  beforeEach(() =&amp;gt; {
    cy.request("http://localhost:3000/api/auth/login", {
      email: "jon@example.com",
      password: "password",
    }).then((r) =&amp;gt; {
      window.localStorage.setItem("token", r.body.token)
    })
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This sends a request every time a particular page is being tested.&lt;/p&gt;

&lt;p&gt;One of Cypress best practices is to build a custom command for our login code.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cypress.Commands.add("login", (email, password) =&amp;gt; {
  cy.request("http://localhost:3000/api/auth/login", {
    email,
    password,
  }).then((r) =&amp;gt; {
    window.localStorage.setItem("token", r.body.token)
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And re-use our custom command in our test codes.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing protected routes", () =&amp;gt; {
  beforeEach(() =&amp;gt; {
    cy.login("jon@example.com", "password")
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now, this is a much better practice and much faster than logging in using the UI. It saves you a lot of time; it’s more maintainable and reliable since we are not relying on selectors that could change during development.&lt;/p&gt;

&lt;p&gt;Watch this video to learn how Cypress can be used to automate accessibility testing.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gRHwcIVDr8U"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing best-suited locators
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Are you using &lt;a href="https://www.lambdatest.com/playwright-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; for automation testing? Run your Playwright test scripts instantly on 50+ browser/OS combinations using the LambdaTest cloud. Sign up for free!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing best-suited locators
&lt;/h2&gt;

&lt;p&gt;One of the most common mistakes in writing tests is using selectors that are too brittle and subject to change. These include selectors coupled with &lt;a href="https://www.lambdatest.com/blog/html-css-tricks/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;CSS styling&lt;/a&gt; and JavaScript event listeners.&lt;/p&gt;

&lt;p&gt;For example, let’s use &lt;a href="https://ecommerce-playground.lambdatest.io/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest’s eCommerce Playground&lt;/a&gt; to run a test using brittle selectors (not recommended)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing home page", () =&amp;gt; {
  it("should go to product page", () =&amp;gt; {
    cy.visit("&amp;lt;https://ecommerce-playground.lambdatest.io/&amp;gt;")
    cy.get("#mz-product-listing-image-97213254-0-1").click()
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example, we want to click the first element of the “Deals of the day” slider, the problem with the code above is that it is using the element id to click it.&lt;/p&gt;

&lt;p&gt;This will work (for now), but more products will be added to the slider in the future. It is not a guarantee that this product will be there, so Cypress can not find an element with the given id, and the test will fail. To learn more about finding elements in Cypress, you can read this blog on &lt;a href="https://www.lambdatest.com/blog/finding-html-elements-using-cypress-locators/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;finding HTML elements using Cypress locators&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can use Cypress best practices, something like data-cy="first-slider-item" as the element attribute and use cy.get('[data-cy="first-slider-item"]') in Cypress to get access to the element.&lt;/p&gt;

&lt;p&gt;Now it is a guarantee that the code will always run no matter if the id changes or the styling of the element changes.&lt;/p&gt;

&lt;p&gt;You should refactor your code to this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing home page", () =&amp;gt; {
  it("should go to product page", () =&amp;gt; {
    cy.visit("https://ecommerce-playground.lambdatest.io/")

    cy.get('[data-cy="first-slider-item"]').click()
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The problem with using too generic selectors is that it might work at first as you don’t have a very complicated UI, but you could easily break your selectors as you expand and add more features in the application.&lt;/p&gt;

&lt;p&gt;This way you might introduce broken selectors and unnecessary failed tests that should actually be considered as passed tests.&lt;/p&gt;

&lt;p&gt;For example, let’s say you want to select an element **button **and click it. Here are some ways that you could do it and why you should use them or not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cy.get(‘button’).click():&lt;/strong&gt; This is too generic, there might be more than one button in the page or you might add more buttons in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cy.get(‘.btn.btn-primary’).click():&lt;/strong&gt; This one is also subject to change. You might want to change the classes to update the styling of the button in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cy.get(‘#main’).click():&lt;/strong&gt; Better but not the best since it is linked to CSS Styling and JavaScript event listeners.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cy.get(‘[name=submission]’).click():&lt;/strong&gt; Coupled to the name attribute, which has HTML semantics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cy.contains(‘Submit’).click():&lt;/strong&gt; This is much better, but this is coupled with the HTML elements content. It depends if you really want the button to contain “Submit”. If you want the test to fail if it doesn’t contain “Submit”, then you should use it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cy.get(‘[data-cy=submit]’).click():&lt;/strong&gt; Best practice, not subjected to any change in any way possible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;th&gt;Not recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;✅ data-cy&lt;/td&gt;
&lt;td&gt;❌ class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅ data-test&lt;/td&gt;
&lt;td&gt;❌ id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅ data-testid&lt;/td&gt;
&lt;td&gt;❌ name&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;strong&gt;data-cy, data-test or data-testid&lt;/strong&gt; makes it clear to everyone that this element is used directly by the test code.&lt;/p&gt;

&lt;p&gt;Code example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// cypress/support/commands.ts
Cypress.Commands.add("getBySelector", (selector, ...args) =&amp;gt; {
 return cy.get(`[data-test=${selector}]`, ...args)
})
Cypress.Commands.add("getBySelectorLike", (selector, ...args) =&amp;gt; {
 return cy.get(`[data-test*=${selector}]`, ...args)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;getBySelector&lt;/strong&gt; yields elements with a data-test attribute that match a specified selector.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;getBySelectorLike&lt;/strong&gt; yields elements with a data-test attribute that contains a specified selector.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing the types for TypeScript:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;declare global {
  namespace Cypress {
    interface Chainable {
      getBySel: (
        selector: string,
        ...args: Partial&amp;lt;Loggable &amp;amp; Timeoutable &amp;amp; Withinable &amp;amp; Shadow&amp;gt;[]
      ) =&amp;gt; Chainable&amp;lt;any&amp;gt;

      getBySelLike: (
        selector: string,
        ...args: Partial&amp;lt;Loggable &amp;amp; Timeoutable &amp;amp; Withinable &amp;amp; Shadow&amp;gt;[]
      ) =&amp;gt; Chainable&amp;lt;any&amp;gt;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Assigning Return Values
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Assigning return values of Cypress commands&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Using closures and aliases&lt;/p&gt;

&lt;p&gt;Cypress does not run synchronously, which means that you can not ever assign the return value of any Cypress command.&lt;/p&gt;

&lt;p&gt;Do not assign or work with return values of any Cypress command; commands are enqueued and run asynchronously. There is no guarantee that the behavior of the tests will be the same if they are dependent on the return values.&lt;/p&gt;

&lt;p&gt;This is a common mistake that people mostly make:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// this won't work 
// do not write your code like this
const button = cy.get('button')
const form = cy.get('form')
button.click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Since commands are enqueued and run asynchronously, this code does not work. Do not ever assign any value to Cypress commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But don’t worry…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don’t panic yet, Cypress has provided us with a few other techniques that we can use to get the values of any selected element.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/jAruMwIrKgs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  How to access the return values of any Cypress command?
&lt;/h3&gt;

&lt;p&gt;There are some ways that you could access the return values of any Cypress command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using Closures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using Variables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using Aliases&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Closures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’ve worked with JavaScript enough, you definitely are quite familiar with JavaScript promises and how to work with them.&lt;/p&gt;

&lt;p&gt;You can access the value that each Cypress command yields using the &lt;strong&gt;.then()&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s use &lt;a href="https://www.lambdatest.com/selenium-playground/simple-form-demo" rel="noopener noreferrer"&gt;this simple form demo&lt;/a&gt; to run a simple test using closures. Basically, we want to grab a text from a random element from the DOM and type that element in an input which will also display the text in a different &lt;strong&gt;div&lt;/strong&gt; element.&lt;/p&gt;

&lt;p&gt;This is just a simple example of using closures in our code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it("should be equal", () =&amp;gt; {
  cy.visit("https://www.lambdatest.com/selenium-playground/simple-form-demo")

  cy.get("h2").then(($h2) =&amp;gt; {
    const text = $h2.text() // gets the text in the p tag

    cy.get("input").first().type(text)

    // click the button that will show the input
    cy.get("#showInput").click()

    // get the div which contains the message
    // using another closure to get the text
    cy.get("#message").then((message) =&amp;gt; {
      expect(message.text()).to.equal(text)
    })
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see we are using &lt;strong&gt;.then()&lt;/strong&gt; after we are getting the element h2 we also use &lt;strong&gt;.text()&lt;/strong&gt; which can only be accessed on the returned element, which is $h2 in this case. This will return the text value that is inside the first h2 element of the DOM.&lt;/p&gt;

&lt;p&gt;After we get the text of the first h2 element, we want to type that text inside the first &lt;strong&gt;input&lt;/strong&gt; element and click the button to show it on the other div. We also assert that the text in the message should be equal to the text in the first h2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2476%2F0%2AuVdmM0uIEJ4NiTX8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2476%2F0%2AuVdmM0uIEJ4NiTX8.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, both texts are equal, that’s why our test passes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AzYAEx6jWMLccYfTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AzYAEx6jWMLccYfTg.png" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;br&gt;
You will not be using variables in most of your code or you will be hardly using them, but variables also have their own use cases and are sometimes important to use.&lt;/p&gt;

&lt;p&gt;If your application’s state changes throughout running the test codes, then you might want to use variables to compare your previous state value to the next state value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s write a simple HTML code that contains a &lt;strong&gt;span&lt;/strong&gt; that holds a state value of a counter and a button that increments the counter.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button&amp;gt;increment&amp;lt;/button&amp;gt;
counter = &amp;lt;span id="num"&amp;gt;0&amp;lt;/span&amp;gt;
&amp;lt;script&amp;gt;
 var counter = 0
 document.getElementById("num").innerHTML = counter
 document
   .getElementsByTagName("button")[0]
   .addEventListener("click", function () {
     counter++
     document.getElementById("num").innerHTML = counter
   })
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We want to compare the previous state and the next state with Cypress and make an assertion to make sure the value is incremented each time the button is clicked.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.get("#num").then(($span) =&amp;gt; {
 // the current number
 const num1 = parseInt($span.text())
 cy.get("button")
   .click()
   .then(() =&amp;gt; {
     // the number after the state updates
     const num2 = parseInt($span.text())
     expect(num2).to.eq(num1 + 1)
 })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;As you can see we first get the value in the span with &lt;strong&gt;.text()&lt;/strong&gt; and click the button to increment it, finally compare the new value to be equal with the old value +1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aliases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you want to re-use the return values of the Cypress commands that you run inside the hooks like &lt;strong&gt;before&lt;/strong&gt; and &lt;strong&gt;beforeEach&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;.then()&lt;/strong&gt; certainly won’t help with that.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;beforeEach(() =&amp;gt; {
  cy.get("button").then(($btn) =&amp;gt; {
    const text = $btn.text()
  })
})

it("does not have access to text", () =&amp;gt; {
  // how do we get access to text ?
  // .then() is not useful in this scenario.
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You can share the context of any value that you want by using the &lt;strong&gt;.as()&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;.as()&lt;/strong&gt; commands lets you assign an alias for later use; it yields the same subject it was given from the previous command.&lt;/p&gt;

&lt;p&gt;You can then access that alias with &lt;strong&gt;this.alias or cy.get(‘&lt;a class="mentioned-user" href="https://dev.to/alias"&gt;@alias&lt;/a&gt;’)&lt;/strong&gt; with a @ in the beginning.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;beforeEach(() =&amp;gt; {
 // alias the $btn.text() as 'text'
 cy.get("button").invoke("text").as("text")
})

it("has access to text", function () {
 expect(this.text).to.equal("Click me")
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Having test isolation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Having tests rely on each-other&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Tests should always be able to be run independently from any other test&lt;/p&gt;

&lt;p&gt;Let’s say you want to test if a particular input exists, fill in the text input, and then submit the form.&lt;/p&gt;

&lt;p&gt;This includes three tests. Here is how most people do it, which is NOT the Cypress best practices and you should avoid doing this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Texts should be equal", () =&amp;gt; {
 it("should visit lambdatest form demo", () =&amp;gt; {
cy.visit("https://www.lambdatest.com/selenium-playground/simple-form-demo")
 })
 it("should find the input", () =&amp;gt; {
   cy.get("#user-message").should("exist")
 })
 it("should type in the input", () =&amp;gt; {
   cy.get("#user-message").type("Hello World")
 })
 it("should click the button", () =&amp;gt; {
   cy.get("#showInput").click()
 })

 it("should show the message", () =&amp;gt; {
   cy.get("#message").should("contain", "Hello World")
 })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;What is wrong with this code? Why is this a bad idea?&lt;/p&gt;

&lt;p&gt;This approach to testing your code is depending on the previous state of the application, for example, the step of .should("contain", "Hello World") depends on the previous step of clicking the button and this also depends on the previous state of typing in the input.&lt;/p&gt;

&lt;p&gt;These steps obviously depend on each other and fail completely in isolation, which is essential in writing your tests.&lt;/p&gt;

&lt;p&gt;Instead, you should combine all of these steps into one test.&lt;/p&gt;

&lt;p&gt;Here is the recommended way to do it:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Texts should be equal", () =&amp;gt; {
  it("should fill in the form and show the message", () =&amp;gt; {
    cy.visit("https://www.lambdatest.com/selenium-playground/simple-form-demo")

    cy.get("#user-message").should("exist")

    cy.get("#user-message").type("Hello World")

    cy.get("#showInput").click()

    cy.get("#message").should("contain", "Hello World")
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you think you need to run some other tests differently, it’s a good idea to share some of the code by using &lt;strong&gt;beforeEach&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The **beforeEach **hook runs the code inside of it before running any tests.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing login page ...", () =&amp;gt; {
  beforeEach(() =&amp;gt; {
    cy.visit("/login")
  })
  it("test 1", () =&amp;gt; {
    // ...
  })

  it("test 2", () =&amp;gt; {
    // ...
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For example in this code, Cypress will visit the login page before running any of the codes inside the &lt;strong&gt;it&lt;/strong&gt; blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A comprehensive &lt;a href="https://www.lambdatest.com/learning-hub/end-to-end-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;end-to-end Testing&lt;/a&gt; tutorial that covers what E2E Testing is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating small tests with a single assertion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Creating different tests with a single assertion for the same element&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Adding multiple assertions in the same test&lt;/p&gt;

&lt;p&gt;Cypress is different and not the same as running unit tests, it runs a series of asynchronous lifecycle events that reset the state between tests.&lt;/p&gt;

&lt;p&gt;This means writing single assertions in one test will make your tests run very slowly and cause really bad performance.&lt;/p&gt;

&lt;p&gt;Adding multiple assertions is much faster than creating different tests; therefore, don’t be afraid to add multiple assertions in one test.&lt;/p&gt;

&lt;p&gt;What if you want to know which tests have failed? Don’t you need to write different titles for each test? The answer is NO. Since you will be able to see “visually” which tests have failed, you don’t need to write every single assertion in a different test, you can easily create multiple assertions in one test.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/jI7hDyLESvg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As per Cypress, they consider &lt;a href="https://docs.cypress.io/guides/references/best-practices#Creating-tiny-tests-with-a-single-assertion?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;30+ commands in Cypress&lt;/a&gt; tests to be pretty common and normal.&lt;/p&gt;

&lt;p&gt;This is a simple example of the correct usage of writing multiple assertions.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("Testing login page", () =&amp;gt; {
  it("should type and validate inputs", () =&amp;gt; {
    cy.visit(
   "https://ecommerce-playground.lambdatest.io/index.php?route=account/login"
    )

    cy.get("#input-email")
      .type("jon@doe.com")
      .should("have.value", "jon@doe.com")
      .and("include.value", "@")
      .and("not.have.value", "jon@doe")
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Unnecessary Waits
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Waiting for an arbitrary time period&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Not using cy.wait() for a large portion of your tests&lt;/p&gt;

&lt;p&gt;In Cypress, you almost never need to use &lt;strong&gt;cy.wait()&lt;/strong&gt; an arbitrary number for anything. Cypress users seem to do this very often, but fortunately, there are better ways to do this.&lt;/p&gt;

&lt;p&gt;You should never use &lt;strong&gt;cy.wait()&lt;/strong&gt; with any of the following commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;cy.request()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cy.visit()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cy.get()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command &lt;strong&gt;cy.request()&lt;/strong&gt; will not resolve until it receives the response from the server, so adding an arbitrary waiting time is not necessary at all.&lt;/p&gt;

&lt;p&gt;This is a great feature of Cypress and one of the Cypress best practices. If you set an arbitrary number of 2 seconds for a request and the request takes 0.1 seconds, you will slow down the testing process by 20 times.&lt;/p&gt;

&lt;p&gt;Also, if you wait for 1 second and the request takes 2 seconds now, you get an error because the request is not resolved yet. So Cypress made this pretty easy, and you can use &lt;strong&gt;cy.request()&lt;/strong&gt; without worrying about waiting for it to resolve.&lt;/p&gt;

&lt;p&gt;The same is true for &lt;strong&gt;cy.visit()&lt;/strong&gt;. It will only resolve when every single asset has been loaded, including JS and CSS files.&lt;/p&gt;
&lt;h2&gt;
  
  
  Web Servers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Starting a web server using Cypress commands cy.exec() and cy.task()&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Start a web server before running Cypress&lt;/p&gt;

&lt;p&gt;Every time you run &lt;strong&gt;cy.exec()&lt;/strong&gt; and &lt;strong&gt;cy.task()&lt;/strong&gt;, the process must eventually exit. If not, Cypress will not continue any other commands.&lt;/p&gt;

&lt;p&gt;If you start a server with Cypress, you will introduce many problems because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You have to background the process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No access via terminal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No valid access to logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Every time your tests run, you’d have to work out the complexity around starting an already running web server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port conflicts&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the &lt;strong&gt;after()&lt;/strong&gt; hook could solve your problem and shut down the server, but the after() hook only runs after the test is completed. Also, it is not guaranteed that the &lt;strong&gt;after()&lt;/strong&gt; hook will run every single time!&lt;/p&gt;

&lt;p&gt;Since you can always restart/refresh in Cypress, then the code in the &lt;strong&gt;after&lt;/strong&gt; hook will not always run.&lt;/p&gt;
&lt;h3&gt;
  
  
  What should you do instead?
&lt;/h3&gt;

&lt;p&gt;You should instead start your server before running the Cypress tests and shut it down whenever it ends.&lt;/p&gt;

&lt;p&gt;We recommend using the wait-on module&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start &amp;amp; wait-on http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQXGz5qUYzBpv6yW7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQXGz5qUYzBpv6yW7.png" width="391" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then run your tests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7tJVi66PMi6noBuI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7tJVi66PMi6noBuI.png" width="721" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a global baseUrl
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Using cy.visit() without a baseUrl&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Set a baseUrl in your cypress.json&lt;/p&gt;

&lt;p&gt;Setting up a global baseUrl saves you from hard-coding the URL every time you use one of the Cypress commands cy.request() and cy.visit().&lt;/p&gt;

&lt;p&gt;Also, if you do not set up a global baseUrl, Cypress will automatically go to &lt;a href="https://localhost" rel="noopener noreferrer"&gt;**https://localhost&lt;/a&gt;** + a random port, which will show an error. By having a baseUrl configured, you save yourself from seeing this error when cypress first opens up.&lt;/p&gt;

&lt;p&gt;If you haven’t configured a baseUrl in your &lt;strong&gt;cypress.json&lt;/strong&gt;, here is how you should re-write your code:&lt;/p&gt;

&lt;p&gt;let’s say you have visited the login page:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.visit("http://localhost:3000/login")
Change it to:
cy.visit("/login")
cypress.json
{
 ...
 "baseUrl": "http://localhost:3000"
 ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Visiting external websites
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Visiting 3rd party websites&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Only testing what you control and using cy.request() with 3rd party APIs&lt;/p&gt;

&lt;p&gt;You should always avoid using &lt;strong&gt;cy.visit()&lt;/strong&gt; to visit any external website and avoid interacting with the UI at all costs.&lt;/p&gt;

&lt;p&gt;Why shouldn’t you ever use &lt;strong&gt;cy.visit()&lt;/strong&gt; and the UI to interact with third-party websites and servers?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It takes a lot of time and slows you down.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The website might change without you knowing about it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Their website could be having issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They might want to block you because of automation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They might be running A/B campaigns.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Testing logging in with OAuth
&lt;/h3&gt;

&lt;p&gt;Instead of using &lt;strong&gt;cy.visit&lt;/strong&gt; here are some ways you can handle logging in to third-party providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use stub&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Using after or afterEach hooks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern&lt;/strong&gt;: Using after or afterEach hooks to clean up the state&lt;br&gt;
&lt;strong&gt;Best Practice&lt;/strong&gt;: Cleaning up the state before running the tests&lt;/p&gt;

&lt;p&gt;We see people write their state clean-ups right after their test ends. This could cause multiple problems, including introducing unnecessary failing tests and slowing down your testing performance.&lt;/p&gt;

&lt;p&gt;Here is an example of how most beginners tend to do it, which is not recommended:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;afterEach(()=&amp;gt; {
  cy.cleanDb()
})

it('should add a new user', ...)
it("should some other stuff", ...)
it('should do something else', ...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;While this code seems to be fine, it is actually not, because it is not a guarantee that any code inside of the afterEach hook will run at all. This could leave you with an unwanted state in your application.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xb7yP_rgbM4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is afterEach not a guarantee to run?
&lt;/h3&gt;

&lt;p&gt;Let’s say you refresh your browser in the middle of the test, this will restart your test instantly without running any code inside the &lt;strong&gt;afterEach&lt;/strong&gt; hook, leaving you with an unwanted state.&lt;/p&gt;

&lt;p&gt;So, the next time you start your testing process, you will encounter many errors and failed tests, because of the old state that the previous test created when you refreshed/closed the test.&lt;/p&gt;

&lt;p&gt;Let’s look at another code example that most people tend to write, which is also not recommended&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;beforeEach(() =&amp;gt; {
 cy.login()
})

afterEach(() =&amp;gt; {
 cy.logout()
})

it('some', ...)
it('more', ...)
it('tests', ...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This code will log in and log out the user for every test, which is sometimes unnecessary.&lt;/p&gt;

&lt;p&gt;Cypress leaves you with the same state that the previous test leaves behind. It’s of the Cypress best practices to always take advantage of this state and write your tests based on this.&lt;/p&gt;

&lt;p&gt;We don’t have to worry about debugging later because debugging in Cypress is unlike any other test library. It has an unmatched debuggability that helps you write your tests in this style.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should you do instead?
&lt;/h3&gt;

&lt;p&gt;Avoid using &lt;strong&gt;afterEach&lt;/strong&gt; and &lt;strong&gt;after&lt;/strong&gt; as much as you can. This way you can leverage the state of the previous tests and run your tests much faster and much more performant.&lt;/p&gt;

&lt;p&gt;If you want to clean the state, do it before starting the test, meaning, put it in the &lt;strong&gt;beforeEach&lt;/strong&gt; block. This way, you will always ensure you are starting your test in a clean and untouched state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Tip: Use Cloud Cypress Grid to test at scale
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check out this &lt;a href="https://www.lambdatest.com/learning-hub/end-to-end-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;e2e testing&lt;/a&gt; comprehensive tutorial that covers what E2E Testing is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Tip: Use Cloud Cypress Grid to test at scale
&lt;/h2&gt;

&lt;p&gt;Cypress cloud grids like LambdaTest allow you to perform &lt;a href="https://www.lambdatest.com/blog/how-to-perform-cypress-testing-at-scale-with-lambdatest/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress testing at scale&lt;/a&gt;. LambdaTest allows you to perform automated &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cross browser testing&lt;/a&gt; on an &lt;a href="https://www.lambdatest.com/online-device-farm?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;online browser farm&lt;/a&gt; of 40+ browsers and operating systems to expedite the test execution in a scalable way. Moreover, it increases the test coverage with better product quality.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SBY669U14Oo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can also Subscribe to the &lt;a href="https://www.youtube.com/channel/UCCymWVaTozpEng_ep0mdUyw?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest YouTube Channel&lt;/a&gt; and stay updated with the latest tutorials around &lt;a href="https://www.lambdatest.com/automated-browser-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automated browser testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium testing&lt;/a&gt;, CI/CD, and more.&lt;/p&gt;

&lt;p&gt;In this example, I will show you how to run parallel Cypress browsers using LambdaTest. We will use &lt;a href="https://ecommerce-playground.lambdatest.io/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest’s eCommerce Playground&lt;/a&gt; to visit the registration page and create an assertion.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// /cypress.json
{
  "baseUrl": "https://ecommerce-playground.lambdatest.io"
}

// /cypress/integration/test.spec.ts
describe("Testing register page", () =&amp;gt; {
  it("should find a text", () =&amp;gt; {
    cy.visit("/index.php?route=account/register")

    cy.contains("Register Account").should("exist")
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To &lt;a href="https://www.lambdatest.com/blog/cypress-cli-on-lambdatest/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;run your Cypress test on LambdaTest&lt;/a&gt;, install the LambdaTest Cypress CLI using the following command:&lt;/p&gt;

&lt;p&gt;npm install -g lambdatest-cypress-cli&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AS8ky9N5x2KR5g3V8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AS8ky9N5x2KR5g3V8.png" width="546" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cypress test on LambdaTest ” width=”546″ height=”211″ class=”aligncenter size-full wp-image-30582″ /&amp;gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup configurations on which you want to run your test&lt;/strong&gt; — Once you have installed the lambdatest-cypress CLI, now you need to set up the configuration. You can do that using the following command:&lt;/p&gt;

&lt;p&gt;lambdatest-cypress init&lt;/p&gt;

&lt;p&gt;This will put the configurations inside &lt;strong&gt;lambdatest-config.json.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are using &lt;strong&gt;TypeScript&lt;/strong&gt;, don’t forget to add typescript with the specified version in the &lt;strong&gt;npm&lt;/strong&gt; dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"npm_dependencies": {
         "cypress": "9.0.0",
         "typescript": "^4.7.2" // don't forget to add this line
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is an example of the LambdaTest configuration file. Don’t forget to update the Username and Access Key with valid credentials. You can find the same in the &lt;a href="https://accounts.lambdatest.com/detail/profile?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest Profile Section&lt;/a&gt; once you log on to LambdaTest.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "lambdatest_auth": {
      "username": "your-lambdatest-username",
      "access_key": "your-lambdatest-token"
   },
   "browsers": [
      {
         "browser": "Chrome",
         "platform": "Windows 10",
         "versions": [
            "latest-1"
         ]
      },
      {
         "browser": "Firefox",
         "platform": "Windows 10",
         "versions": [
            "latest-1"
         ]
      }
   ],
   "run_settings": {
      "cypress_config_file": "cypress.json",
      "build_name": "build-name",
      "parallels": 5,
      "specs": "./**/*.spec.ts",
      "ignore_files": "",
      "feature_file_suppport": false,
      "network": false,
      "headless": false,
      "reporter_config_file": "",
      "npm_dependencies": {
         "cypress": "9.0.0",
         "typescript": "^4.7.2"
      }
   },
   "tunnel_settings": {
      "tunnel": false,
      "tunnel_name": null
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As shown in the browsers array, we have specified two browsers with the specified operating systems.&lt;/p&gt;

&lt;p&gt;And we have also specified the value of the parallel to be 5, which means LambdaTest will automatically run these tests in different browsers with a maximum of 5 parallel tests.&lt;/p&gt;

&lt;p&gt;Now it’s time to run the &lt;a href="https://www.lambdatest.com/cypress-ui-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress UI automation&lt;/a&gt; test in LambdaTest. Use the following command for that:&lt;/p&gt;

&lt;p&gt;lambdatest-cypress run&lt;/p&gt;

&lt;p&gt;This will automatically upload your tests to the secure LambdaTest Cypress Grid and help you perform &lt;a href="https://www.lambdatest.com/cypress-parallel-testing?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress parallel testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Visit the &lt;a href="https://accounts.lambdatest.com/dashboard?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Automation Dashboard&lt;/a&gt; to view the status of the tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3132%2F0%2Abk4qYgv93k6tzfJu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3132%2F0%2Abk4qYgv93k6tzfJu.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be able to see your tests there and see the logs and videos recorded during the tests.&lt;/p&gt;

&lt;p&gt;You can further deepen your knowledge with this &lt;a href="https://www.youtube.com/watch?v=RuW-R6260Qg?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;webinar on Cypress&lt;/a&gt;, which will help you perform &lt;a href="https://www.lambdatest.com/blog/cross-browser-testing-with-cypress-framework/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;scalable and reliable cross browser testing with Cypress&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are a developer or a tester and want to take your Cypress expertise to the next level, you can take this Cypress 101 certification and stay one step ahead.&lt;/p&gt;

&lt;p&gt;Here’s a short glimpse of the Cypress 101 certification from LambdaTest:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qL_rgUEI2s0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Cypress is a great testing framework if appropriately used, followed by the best practices.&lt;/p&gt;

&lt;p&gt;Following some of the Cypress best practices could be irritating or somewhat difficult to implement. But they will definitely pay off in the long run and save you a lot of time while performing Cypress E2E testing. If not, you will introduce errors and failed tests and slow down the process.&lt;/p&gt;

&lt;p&gt;Following these Cypress best practices will make your tests much more performant, giving you a seamless testing experience without introducing errors or failures in the future.&lt;/p&gt;

&lt;p&gt;Do check out the detailed &lt;a href="https://www.lambdatest.com/learning-hub/cypress-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov22_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress tutorial&lt;/a&gt; if you want to explore the immense number of features Cypress offers.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>automation</category>
      <category>testing</category>
    </item>
    <item>
      <title>Podman vs Docker: All You Need To Know!</title>
      <dc:creator>Sonikasinghh</dc:creator>
      <pubDate>Mon, 21 Nov 2022 05:33:35 +0000</pubDate>
      <link>https://dev.to/testmuai/podman-vs-docker-all-you-need-to-know-2j9m</link>
      <guid>https://dev.to/testmuai/podman-vs-docker-all-you-need-to-know-2j9m</guid>
      <description>&lt;p&gt;Docker and Podman are great container management engines and serve the same purpose in building, running, and managing containers.&lt;/p&gt;

&lt;p&gt;Docker has been in the containerization market for quite a while. It has proved its worth and increased its job market demand. It was first developed by Docker Inc. in 2013 and has been used by some of the biggest names in technology, such as Google and Facebook, thus making it the most popular container engine out there.&lt;/p&gt;

&lt;p&gt;Now that containers have become a lot more popular and are being used almost everywhere, other tools like Podman show up to make this even better and solve some specific problems we face with containerization.&lt;/p&gt;

&lt;p&gt;In this Podman vs Docker comparison blog, you will learn about both Podman and Docker.&lt;br&gt;
Moreover, you will get a much better understanding of both container engines. At the end of the blog post, you will be able to decide which container engine suits you the best.&lt;/p&gt;

&lt;p&gt;Chances are you are using Docker currently, so I will also explain how to migrate from Docker to Podman without having any issues in the later section of this blog on Podman vs Docker.&lt;/p&gt;

&lt;p&gt;So, let’s get started.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Containerization?
&lt;/h2&gt;

&lt;p&gt;Containerization is a very efficient method of &lt;a href="https://www.lambdatest.com/blog/happens-use-virtualization-software-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;virtualization&lt;/a&gt; that is available out there. It makes it much easier for developers to test, build and deploy large-scale applications.&lt;/p&gt;

&lt;p&gt;Containers and Virtual machines are similar, but they’re not the same. Since they are so similar, some people tend to confuse them because they do the same thing but differently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xnp55nchjl5rvg9y47x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xnp55nchjl5rvg9y47x.png" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Podman vs Docker?
&lt;/h2&gt;

&lt;p&gt;If we look at Google trends, we see that the search interest for Podman is on the rise and all-time increasing. We will likely see Podman become more popular in the next few years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb6ycgtgm7tj6crbsxuz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb6ycgtgm7tj6crbsxuz.png" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker is still a leading player in the field, and I don’t think it is going anywhere anytime soon, but the charts tell us that the overall interest in Docker is decreasing.&lt;/p&gt;

&lt;p&gt;Either developer are losing interest in Docker, or they have migrated to another software that could do their jobs better than Docker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lpva74hxe11wjw951kq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9lpva74hxe11wjw951kq.png" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before getting into the Podman vs Docker differences, let’s start by understanding what a container is. Some people tend to confuse the two because they both do the same thing (virtualization), but they’re quite different.&lt;/p&gt;
&lt;h2&gt;
  
  
  Containers vs Virtual Machines
&lt;/h2&gt;

&lt;p&gt;In Virtual Machines (VMs), the system’s resources are distributed between multiple virtual machines. The VMs run separately and can have different operating systems in them.&lt;/p&gt;

&lt;p&gt;Containers, on the other hand, only virtualize software layers above the operating system level, which means you can have multiple virtualized environments with only one operating system. To learn more about the differences, you can read through this blog, which discusses &lt;a href="https://www.lambdatest.com/blog/run-selenium-tests-in-docker/#ContainerVsVirtualMachines?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Containers vs Virtual Machines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flq7iklcuszc5iyc6f3b7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flq7iklcuszc5iyc6f3b7.png" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Containerization is the packaging of software code with just the OS libraries and dependencies required to run the code to create a single lightweight executable, called a container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A comprehensive User &lt;a href="https://www.lambdatest.com/learning-hub/user-acceptance-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=" rel="noopener noreferrer"&gt;Acceptance Testing&lt;/a&gt; (UAT) tutorial that covers what User Acceptance Testing is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why are containers important?
&lt;/h2&gt;

&lt;p&gt;Containers play a considerable role in deploying applications, especially &lt;a href="https://www.lambdatest.com/blog/9-fundamentals-to-a-successful-microservice-design/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;microservices&lt;/a&gt;. Microservices are a few little services that communicate, send, and receive data from and to each other.&lt;/p&gt;

&lt;p&gt;As per the report, Netflix uses over 1,000 microservices now. Each deployed application controls a specific aspect of the colossal Netflix operation. For example, a microservice is only responsible for determining your subscription status to provide content relevant to that subscription tier.&lt;/p&gt;

&lt;p&gt;Microservices allow teams to work on different parts of their applications separately without interfering with another team’s work. They are flexible, maintainable, and easily adaptable.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.lambdatest.com/blog/design-patterns-for-micro-service-architecture/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;microservices design patterns&lt;/a&gt; have helped developers to develop, scale, and maintain their projects efficiently. However, when it comes to deployment, they might face a few challenges, especially in large-scale applications.&lt;/p&gt;

&lt;p&gt;If you don’t use containers, you will have to write a bunch of instructions to your DevOps team to run the code on their side. This increases the number of errors that could occur in the application.&lt;/p&gt;

&lt;p&gt;To learn more about microservices, you can refer to this blog on how to &lt;a href="https://www.lambdatest.com/blog/how-to-test-a-microservice-architecture-application/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test a microservice architecture application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges of not using Containers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the DevOps team makes a mistake in following your instructions, they will not be able to run the code on their side. So they will get back to you, and you’ll have to find that little mistake.&lt;/p&gt;

&lt;p&gt;For example: let’s say you are using MongoDB version 4.0, but for production, there was a mistake, and version 4.1 has been installed. One of your microservices is not compatible with that specific version.&lt;/p&gt;

&lt;p&gt;These errors are often introduced in large-scale applications and can be challenging to debug.&lt;/p&gt;

&lt;p&gt;As your application grows, it requires more dependencies and microservices, which will be quite a headache to re-deploy manually every time something new is added.&lt;/p&gt;

&lt;p&gt;Containerization makes this so much easier. You don’t have to give instructions to your DevOps team as the instructions are written in a &lt;strong&gt;Dockerfile&lt;/strong&gt;. The container engine will automatically download and install every dependency that your code requires to run.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:16

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "node", "server.js" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Docker will read the file and instructions and download the dependencies for that specific application, ending with a specific command to run the application. In this case, we are pulling a specific version of the official NodeJs Docker image.&lt;/p&gt;

&lt;p&gt;These image repositories could depend on other repositories and dependencies, and they also can rely on other dependencies on and on. Docker will handle all that hard work in the background when it builds and runs containers.&lt;/p&gt;

&lt;p&gt;Since containers use only high-level software, it makes them lightweight and can be created, modified, and deleted with ease.&lt;/p&gt;

&lt;p&gt;Most container runtime systems also have a robust ecosystem. Many public repositories of container images are ready to be downloaded and executed.&lt;/p&gt;

&lt;p&gt;For example, you can download the latest version of &lt;a href="https://hub.docker.com/r/selenium/standalone-docker?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium from DockerHub&lt;/a&gt; and run it inside a Docker container with just one single command.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull selenium/standalone-docker

docker run selenium/standalone-docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This will download the official Selenium Docker image from DockerHub and all of the required dependencies for it. Then Selenium will run inside of the Docker container.&lt;/p&gt;

&lt;p&gt;Today, almost every large company uses containerization to test, build, and deploy its applications. Containers have proved their importance over the last few years, especially Docker.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Docker?
&lt;/h2&gt;

&lt;p&gt;Docker is a Platform as a Service (PAAS) product that uses operating-system-level virtualization in small, lightweight packages called containers.&lt;/p&gt;

&lt;p&gt;For starters, PaaS is a complete development and cloud-hosted platform in the cloud. It allows businesses and developers to host, build, and deploy applications.&lt;/p&gt;

&lt;p&gt;Docker is also open-source and helps developers to build, deploy, run and manage containerized applications. It uses a REST API running in the background to listen to requests and perform operations accordingly. This process is called the Docker daemon (or dockerd).&lt;/p&gt;

&lt;p&gt;Docker daemon is a background process responsible for managing all containers on a single host. It can handle all Docker images, containers, networks, storage, etc.&lt;/p&gt;

&lt;p&gt;Docker uses the &lt;strong&gt;containerd&lt;/strong&gt; Daemon that listens to REST API requests to manage most of the work that Docker does. For example, managing images, managing containers, volumes, and networks. &lt;strong&gt;Containerd&lt;/strong&gt; listens on a Unix socket and exposes gRPC endpoints. It handles all the low-level container management tasks, storage, image distribution, network attachment, etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  How does Docker work?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;containerd&lt;/strong&gt; daemon will pull the container images from the container registries. Then it turns over the process of creating the container to a low-level runtime named &lt;strong&gt;runc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;runc&lt;/strong&gt; is a CLI tool for running containers on Linux according to the OCI specification.&lt;/p&gt;

&lt;p&gt;OCI is a collaborative project hosted under the Linux Foundation and designed to establish standards for containers. Container engines like Docker, CRI-O, and containerd rely on the OCI compliant to interface with the operating system and create the running containers.&lt;/p&gt;

&lt;p&gt;It is designed to be used by higher-level container software. Hence, the process of running a container goes from running it through the Docker daemon, containerd, and then run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcp9rwwc34h48n93oo3gk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcp9rwwc34h48n93oo3gk.png" width="388" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker Image&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Docker image is like a template that acts as a set of instructions to build a Docker container. A Docker image contains application code, libraries, tools, dependencies, and other files needed to run the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker Volume&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s say you have a Docker container with a MongoDB database inside it. Usually, this container saves every bit of data inside the container itself.&lt;/p&gt;

&lt;p&gt;The problem with this is that if you want to delete the container for whatever reason, you will lose all of the data that you have accumulated.&lt;/p&gt;

&lt;p&gt;With Docker volumes, you can save the necessary information that you need in the host machine. They are preferred where you want the data to persist in docker containers and services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker Network&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Docker network helps attach containers that can communicate with each other. Hence, Docker is not just the software to build and run containers. It is also a cloud platform to upload and download your container images to the cloud.&lt;/p&gt;

&lt;p&gt;With Docker, you can create, build, and run containers compatible with any operating system. In other words, if you have Docker on your system and your code runs on your machine, it is guaranteed that this code will run on another device if they have Docker installed.&lt;/p&gt;

&lt;p&gt;A quick summary about Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Docker uses a daemon which is a background process listening to API requests to manage the containers accordingly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker lets you build and run super lightweight containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker is a PAAS based on multiple software, including a cloud-hosted registry to share and download Docker images called DockerHub.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is Podman?
&lt;/h2&gt;

&lt;p&gt;Podman is a similar container engine to Docker. It is also used for developing, managing, and running OCI containers. Podman can manage the entire container ecosystem like pods, containers, images, and container volumes using a library &lt;strong&gt;libpod&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What are pods?
&lt;/h2&gt;

&lt;p&gt;One of the key features of Podman is that it allows you to create pods. A pod is an organizational unit for containers. Pods are an essential part of the Kubernetes container orchestration framework.&lt;/p&gt;

&lt;p&gt;You can use Podman to create manifest files that describe pods in a declarative format. Kubernetes can consume these manifest files written in YAML.&lt;/p&gt;

&lt;p&gt;Unlike Docker, containers in Podman can be run as root or non-root users. We will discuss this Podman vs Docker difference in more detail in the later section of this blog on Podman vs Docker.&lt;/p&gt;

&lt;p&gt;Podman does not rely on a daemon to develop, manage or run containers. Since Podman does not have a daemon to manage containers, Podman uses another service manager to manage all of the services and support running containers in the background called Systemd.&lt;/p&gt;

&lt;p&gt;Systemd creates control units for existing containers or generates new ones, with Systemd vendors can install, run, and manage their container applications since most are now exclusively packaged and delivered this way.&lt;/p&gt;

&lt;p&gt;Podman, with the help of Buildah, can build images without using a daemon. Buildah is a tool for building OCI-compatible images through a lower-level core utils interface.&lt;/p&gt;

&lt;p&gt;Just like Docker has a CLI since images created by Docker and Podman are compatible with the OCI standard. Podman can push and pull from container registries such as the Docker Hub and Quay.io.&lt;/p&gt;

&lt;p&gt;If you are already familiar with Docker, you can easily &lt;strong&gt;migrate from Docker to Podman&lt;/strong&gt; (more on this later). You can also alias Podman to docker without having any problems alias docker=podman. This means you can use the same commands with Podman as with Docker.&lt;/p&gt;

&lt;p&gt;Podman, just like Docker, relies on an OCI-compliant like RunC to interface with the operating system and create the running containers. Hence it will make Podman very similar to other container engines like Docker.&lt;/p&gt;

&lt;p&gt;Podman also uses REST API that Podman provides to manage containers; this REST API is only available on Linux. To interact with this REST API, Podman has a client which is available on all of the major operating systems Windows, macOS, and Linux.&lt;/p&gt;

&lt;p&gt;If the Podman REST API is only available on Linux, how can we use it in Windows or macOS?&lt;/p&gt;

&lt;p&gt;Even though containers are Linux, Podman also runs on Mac and Windows. It provides a native Podman CLI and embeds a guest Linux system to launch the containers.&lt;/p&gt;

&lt;p&gt;This guest is also called a Podman machine and can be managed by using the podman machine command.&lt;/p&gt;

&lt;p&gt;A quick summary about Podman:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Podman helps you find containers on DockerHub or quay.io or an internal registry server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easily runs containers from pre-built container images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Builds new layers or containers with a few tweaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can easily share your container images anywhere you want with just one command podman push.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Running a Redis server inside a container using Podman
&lt;/h2&gt;

&lt;p&gt;Running containers with Podman is pretty easy and similar to Docker. To do that, run the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;podman run redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Podman will run a Redis server based on the official Redis image inside of a container. The container will be run in detached mode declared by -d and will be named Redis as specified with —-name.&lt;/p&gt;

&lt;p&gt;The container will expose the ports and attach it to the same port on the host machine, which is the default Redis port as specified with -p 6379:6379.&lt;/p&gt;

&lt;p&gt;After you run the command, Podman will check if the Redis image already exists in the local machine. If it does, it will build a container based on that image. If it doesn’t, it will look for that image from DockerHub and download the latest version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A comprehensive &lt;a href="https://www.lambdatest.com/learning-hub/exploratory-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Exploratory Testing&lt;/a&gt; tutorial that covers what Exploratory Testing is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Podman vs Docker Comparison
&lt;/h2&gt;

&lt;p&gt;Generally, Podman and Docker do the same thing. However, there are some differences between the two container engines, Podman vs Docker.&lt;/p&gt;

&lt;p&gt;Here are the main differences between Podman vs Docker:&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture: Podman has a Daemonless architecture
&lt;/h2&gt;

&lt;p&gt;Docker daemon is a background process responsible for managing all containers on a single host. It can handle all Docker images, containers, networks, storage, etc. Docker daemon uses a REST API to listen to requests and perform operations accordingly.&lt;/p&gt;

&lt;p&gt;So, Docker needs this daemon to run in the background to manage, create, run, and build containers. Docker has a client-server logic mediated by the Docker daemon.&lt;/p&gt;

&lt;p&gt;Podman, on the other hand, does not need a daemon. It has a (daemonless architecture), which helps users to start running containers (rootless). In other words, Podman does not require root privileges to manage containers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Root privileges
&lt;/h2&gt;

&lt;p&gt;Since Docker needs a daemon to manage its containers, it will need root permission to run the processes.&lt;/p&gt;

&lt;p&gt;As Podman does not have a daemon, it has a (daemonless architecture). It does not require root privileges for its containers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rootless Execution
&lt;/h2&gt;

&lt;p&gt;At first, when Docker came out, you could not run Docker without root permission. However, the rootless mode was introduced in Docker at v19.03 and graduated from experimental in Docker Engine v20.10.&lt;/p&gt;

&lt;p&gt;However, Docker rootless doesn’t come out right out of the box. Some configurations and third-party packages should first be installed on the host before installing Docker.&lt;/p&gt;

&lt;p&gt;So, yes, you can run Docker and Podman as root. But it is good to know that Podman introduced running containers on rootless, which also comes with a few limitations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Limitations of Docker rootless
&lt;/h3&gt;

&lt;p&gt;Rootless mode on Docker is not perfect, and some issues come with running containers with Docker rootless:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Not being able to run containers on privileged ports, which are all of the ports below 1024. Otherwise, they will fail to run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only the following storage drivers are supported:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;overlay2 (only if running with kernel 5.11 or later or Ubuntu-flavored kernel).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fuse-overlayfs (only if running with kernel 4.18 or later, and fuse-overlayfs is installed).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;btrfs (only if running with kernel 4.18 or later, or ~/.local/share/docker is mounted with user_subvol_rm_allowed mount option).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vfs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cgroup is supported only when running with cgroup v2 and systemd.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The following features are not supported:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AppArmor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checkpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overlay network&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exposing SCTP ports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To use the ping command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IPAddress shown in docker inspect and is namespaced inside RootlessKit’s network namespace. This means the IP address is not reachable from the host without nsenter -ing into the network namespace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Host network ( docker run --net=host ) is also namespaced inside RootlessKit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NFS mounts as the docker “data-root” is not supported. This limitation is not specific to rootless mode.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;Does Podman have higher security than Docker? Earlier, we looked at how Podman can run rootless because it has a (daemonless architecture), and Docker can not run rootless because it requires a daemon to run and manage the containers while comparing Podman vs Docker.&lt;/p&gt;

&lt;p&gt;But why is this important? Why not having a daemon and being able to run containers without root privileges is essential? The answer is that we do not give root privileges to applications that we don’t trust, and we do trust our containers and applications.&lt;/p&gt;

&lt;p&gt;But that’s not the case. Let’s say an attacker has found a way to access one of your containers! Since Docker can only run with root privileges, any malicious actor (i.e., attacker) can take wrong actions on your server with those root privileges.&lt;/p&gt;

&lt;p&gt;With Podman, if an attacker gets access to your container, they will be able to do you harm, but they still won’t be able to do actions that require root privileges. Therefore Podman is considered safer than Docker.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building images
&lt;/h2&gt;

&lt;p&gt;Docker is a self-sufficient platform. It can build images and run containers on its own without the need for any other third-party tool.&lt;/p&gt;

&lt;p&gt;Podman, on the other hand, is only designed to run containers and not build them. That’s where Buildah comes in. Buildah is an open-source tool that makes building Open Container Initiative (OCI) container images.&lt;/p&gt;

&lt;p&gt;Podman, with the help of Buildah, can build its OCI container images.&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker Swarm and docker-compose
&lt;/h2&gt;

&lt;p&gt;Docker Swarm is a container orchestration platform used to manage Docker containers. With the Docker Swarm, you can run a cluster of Docker nodes and deploy scalable applications without other dependencies required.&lt;/p&gt;

&lt;p&gt;Docker Swarm can also manage multiple containers across multiple hosts and connect them all. Docker Swarm obviously can be used with Docker right out of the box without any problem.&lt;/p&gt;

&lt;p&gt;Podman does not support Docker Swarm, but other tools can be used with Podman, such as Nomad, which comes with a Podman driver.&lt;/p&gt;

&lt;p&gt;Docker-compose is a tool to manage applications with multiple containers. The main difference between Docker compose, and Docker swarm is that docker-compose runs only on a single host while Docker swarm connects various hosts.&lt;/p&gt;

&lt;p&gt;Docker automatically is compatible with docker-compose and can work well with it right out of the box.&lt;/p&gt;

&lt;p&gt;In the previous versions of Podman, Podman did not have a way to simulate the Docker daemon necessary for Docker compose to work, so that’s why Podman compose was used.&lt;/p&gt;

&lt;p&gt;Now, in version 3.0, Podman introduced the podman.socket, a UNIX socket that replaces the Docker Daemon.&lt;/p&gt;
&lt;h2&gt;
  
  
  All in one vs modular
&lt;/h2&gt;

&lt;p&gt;Podman has a modular approach, relying on specialized tools for specific tasks, while Docker is a monolithic independent tool. Docker is a monolithic, powerful independent tool. By monolithic, it means that Docker does not rely on any other third-party tool to manage containers, run, build or handle any other task related to the containers.&lt;/p&gt;

&lt;p&gt;This one is a significant difference between Podman vs Docker technologies.&lt;/p&gt;

&lt;p&gt;As we discussed, Podman relies on many additional third-party tools to achieve the same goals as Dockers. For example, it uses Buildah to build container images, while Docker does not need Buildah or any other third-party tool to build images.&lt;/p&gt;

&lt;p&gt;Here’s the summary of the Podman vs Docker comparison.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;DOCKER&lt;/th&gt;
&lt;th&gt;PODMAN&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Uses a Daemon.&lt;/td&gt;
&lt;td&gt;Has a daemon-less architecture.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;It can only run with root privileges.&lt;/td&gt;
&lt;td&gt;Able to run root-less.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Less secure since all containers have root privileges.&lt;/td&gt;
&lt;td&gt;More secure since containers don’t have root privileges.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker is a self-sufficient tool and builds images on its own.&lt;/td&gt;
&lt;td&gt;Podman can not build images by itself. It uses another tool called buildah to build images.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;It supports the Docker swarm, and Docker compose right out of the box.&lt;/td&gt;
&lt;td&gt;It does not support the Docker swarm or Docker compose.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker is a monolithic independent tool.&lt;/td&gt;
&lt;td&gt;Podman relies on other third-party tools.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Since we have learned about Podman vs. Docker comparison, is it safe to consider Podman a replacement for Docker? Let’s check this in the next section of this Podman vs Docker blog.&lt;/p&gt;
&lt;h2&gt;
  
  
  Is Podman a replacement for Docker, or can they work together?
&lt;/h2&gt;

&lt;p&gt;Some developers use Podman for production and Docker for development. Since they’re both OCI compliant, compatibility won’t be a problem. However, it’s better to compare Podman vs Docker before moving ahead.&lt;/p&gt;

&lt;p&gt;You can use Docker for development to make your work easier and use Podman for production to benefit from the added security it provides and make your application more efficient.&lt;/p&gt;

&lt;p&gt;Podman can be a primary containerization technology option if you start a project from scratch. If the project is ongoing and already using Docker, it depends on the specifics, but it might not be worth the effort. As a Linux native application, it demands Linux skills from the developers involved.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to migrate from Docker to Podman?
&lt;/h2&gt;

&lt;p&gt;Migrating from Docker to Podman could be quite easy and simple to implement. The same commands you use to use Docker can also be used for Podman, so you don’t have to worry about memorizing new commands, which makes migrating really easy.&lt;/p&gt;

&lt;p&gt;Some developers just alias Docker to Podman, and everything works quite the same, but the processes are handled by Podman instead of Docker.&lt;/p&gt;
&lt;h2&gt;
  
  
  Running a Node.js container with Podman
&lt;/h2&gt;

&lt;p&gt;First, you must have Podman installed on your computer. If you want to follow along with this short tutorial, you can download the sample node.js application from this GitHub repository.&lt;/p&gt;

&lt;p&gt;Since both Podman and Docker comply with the OCI container standard, Podman can also build containers from a &lt;strong&gt;Dockerfile&lt;/strong&gt;, so if you can build and run a container from a **Dockerfile **with Docker, then you can run it with Podman as well.&lt;/p&gt;

&lt;p&gt;Let’s build the container on this &lt;strong&gt;Dockerfile&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:16

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 3000
CMD [ "node", "server.js" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;To build the container, run the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      podman build -t my-node-app .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxclzm2ncqctrrr3ka2t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxclzm2ncqctrrr3ka2t.png" width="800" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you run the command, Podman will execute the Dockerfile and build the image in your local machine.&lt;/p&gt;

&lt;p&gt;You can show the container images available on your local device by running podman images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70a85nsnyqoxbzwxhokb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70a85nsnyqoxbzwxhokb.png" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We only created one image called my-node-app, but if you notice, we have another additional image since the container that we are trying to run relies on node:16. Podman will automatically download that image to run the container that we want to run.&lt;/p&gt;

&lt;p&gt;After you have built the image, you can then run an instance of this by running a container using the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;podman run --name my-node-js-container -p 3000:3000 localhost/my-node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The --name tag will specify the name of the container, -p will map the port inside of the container to the port on the host machine -p host:container.&lt;/p&gt;

&lt;p&gt;Finally, add the localhost/my-node-app at the end to specify the container image we want our new container to run on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9m25y81dvkgxiw9xnku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9m25y81dvkgxiw9xnku.png" width="800" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, your server is now running on port 3000 inside a container run by Podman. You can access it from your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnb38y9i7d5mbp2lli6iq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnb38y9i7d5mbp2lli6iq.png" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the commands we used in this tutorial were the same as Docker commands. That’s why migrating from docker to Podman is easy, and developers get used to it effortlessly.&lt;/p&gt;

&lt;p&gt;Another cool feature about Podman is that you can stop or remove all containers using the —-all flag. With Docker, you could not have used that.&lt;/p&gt;

&lt;p&gt;For example, if you want to stop all containers with Podman, you can run podman stop —-all. If you’re going to do the same thing with Docker, you have to run docker stop $(docker ps -a -q), which is a bit difficult to memorize.&lt;/p&gt;

&lt;p&gt;Integrating Docker or Podman with Selenium Grid is easy and helps you perform &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium automation testing&lt;/a&gt;. However, the capabilities offered by the Selenium Grid with Docker or Podman can be further enhanced by integrating an &lt;a href="https://www.lambdatest.com/selenium-grid-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;online Selenium Grid&lt;/a&gt; like LambdaTest.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/WZlsHlReRww"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can also Subscribe to the &lt;a href="https://www.youtube.com/channel/UCCymWVaTozpEng_ep0mdUyw?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest YouTube Channel&lt;/a&gt; and stay updated with the latest tutorials around &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/cypress-e2e-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress E2E testing&lt;/a&gt;, CI/CD, and more.&lt;/p&gt;

&lt;p&gt;LambdaTest is a &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cross browser testing&lt;/a&gt; platform that allows you to perform manual and &lt;a href="https://www.lambdatest.com/automated-browser-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automated browser testing&lt;/a&gt; of websites and web apps on an &lt;a href="https://www.lambdatest.com/online-browser-farm?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;online browser farm&lt;/a&gt; of 3000+ browsers and operating systems combinations.&lt;/p&gt;

&lt;p&gt;LambdaTest’s reliable, scalable, secure, and high-performing test execution cloud empowers development and testing teams to expedite their release cycles. It lets you run parallel tests and cut down test execution by more than 10x.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A comprehensive &lt;a href="https://www.lambdatest.com/learning-hub/ui-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov21_kj&amp;amp;utm_term=kj&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;UI testing&lt;/a&gt; tutorial that covers what UI testing is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this Podman vs Docker blog, we have seen that both Docker and Podman are amazing in running and managing containers. You can build and deploy large-scale applications with both of them.&lt;/p&gt;

&lt;p&gt;If you are more concerned about security in your applications or planning to use Kubernetes to orchestrate your containers, Podman is the better choice for you.&lt;/p&gt;

&lt;p&gt;If you want a well-documented tool with a much larger user base, then Docker is the better option for you.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>How To Get Started With Cypress Debugging</title>
      <dc:creator>Sonikasinghh</dc:creator>
      <pubDate>Fri, 18 Nov 2022 09:41:30 +0000</pubDate>
      <link>https://dev.to/testmuai/how-to-get-started-with-cypress-debugging-154a</link>
      <guid>https://dev.to/testmuai/how-to-get-started-with-cypress-debugging-154a</guid>
      <description>&lt;p&gt;One of the most important tasks of a software developer is not just writing code fast; it is the ability to find what causes errors and bugs whenever you encounter one and the ability to solve them quickly.&lt;/p&gt;

&lt;p&gt;According to The Cost of Poor Software Quality in the US: A 2020 Report by Herb Krasner of CISQ, the cost of bugs is estimated at roughly $607 billion only for the United States.&lt;/p&gt;

&lt;p&gt;This includes all the costs relating to unsuccessful projects and maintaining legacy systems, but it doesn’t include some other aspects like security issues, technical debt, and some other issues that add up to a huge price of $2 trillion.&lt;/p&gt;

&lt;p&gt;Even though we are not building applications with Cypress, we’re only testing them; it is still important to keep our test suites away from bugs as much as possible.&lt;/p&gt;

&lt;p&gt;And if we introduce bugs, we should have the ability to spot them and fix them as fast as possible.&lt;/p&gt;

&lt;p&gt;That is why Cypress does a pretty good job of providing developers with tools and commands that make it easy to debug the test suites easily.&lt;/p&gt;

&lt;p&gt;In this &lt;a href="https://www.lambdatest.com/cypress-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress testing&lt;/a&gt; tutorial on Cypress debugging, I will talk about some of the best ways to debug your Cypress tests and explain each in detail. I will also point out some pitfalls you might get into and explain how Cypress actually works and why some things are not happening very intuitively.&lt;/p&gt;

&lt;p&gt;So, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using debugger in Cypress
&lt;/h2&gt;

&lt;p&gt;Sometimes, when running tests, especially large and complicated ones, it could be very difficult for you to know what exactly went wrong and which part of the code failed to do as expected.&lt;/p&gt;

&lt;p&gt;The debugger is very helpful in these kinds of situations. You can stop the &lt;a href="https://www.lambdatest.com/learning-hub/test-execution?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test execution&lt;/a&gt; at any time and look up the application’s state to see if everything works as it should.&lt;/p&gt;

&lt;p&gt;If you have been in the development field for quite a while, you might already know how to use the debugger in other parts of your applications.&lt;/p&gt;

&lt;p&gt;However, if you are unfamiliar with Cypress debugging, using the debugger in Cypress might work differently than you think it should.&lt;/p&gt;

&lt;p&gt;Even though using a debugger in Cypress is quite similar to using the debugger in other parts of your application (like your front end), it doesn’t work the same way.&lt;/p&gt;

&lt;p&gt;You can only use the debugger in Cypress inside the.then() function. Otherwise, it does not work the way it is supposed to.&lt;/p&gt;

&lt;p&gt;Let me explain…&lt;/p&gt;

&lt;p&gt;Let’s see what goes wrong if we add the debugger outside a .then() function.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should work as usual', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io')

  cy.get('[data-test="some-selector"]')
  debugger // Doesn't work
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Running the test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpguwnv6ckhe2rqtl26cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpguwnv6ckhe2rqtl26cw.png" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the debugger will pause the test to run before the test even starts.&lt;/p&gt;

&lt;p&gt;If you have used a debugger before, your expectation might be that first, the cy.visit() and cy.get() functions should run and complete, and then the debugger should pause the test, but that’s not the case.&lt;/p&gt;

&lt;p&gt;So, what happened there? Why did the test pause immediately?&lt;/p&gt;

&lt;p&gt;Based on the Cypress documentation, it is said that the commands in Cypress are all &lt;strong&gt;“Asynchronous,”&lt;/strong&gt; so what does that mean?&lt;/p&gt;

&lt;p&gt;In Cypress, when a set of commands are invoked, they get enqueued for later, and after the whole, it() block is finished, Cypress will run all of the commands in order.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('hides the thing when it is clicked', () =&amp;gt; {
  cy.visit('/my/resource/path') // Nothing happens yet

  cy.get('.hides-when-clicked') // Still nothing happening
    .should('be.visible') // Still absolutely nothing
    .click() // Nope, nothing
    .should('not.be.visible') // Definitely nothing happening yet
})

// Ok, the test function has finished executing...
// We've queued all of these commands and now
// Cypress will begin running them in order!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Based on this information, now you should know why the debugger pauses the test immediately instead of pausing the test after the other two commands have finished running.&lt;/p&gt;

&lt;p&gt;The two commands that come before the debugger are only being enqueued to run later, but the debugger, which is not a Cypress command, will not be enqueued and will be invoked immediately.&lt;/p&gt;

&lt;p&gt;Causing the test to pause immediately before the other commands can be executed in the queue.&lt;/p&gt;

&lt;p&gt;That’s why you should always use the debugger inside the .then() function. This will ensure that the Cypress command will run and complete, and then the debugger will pause the execution of the tests.&lt;/p&gt;

&lt;p&gt;Now, let’s re-write the test again, but this time using the debugger inside of the .then() function&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should only pause when the cy.get() function finishes executing', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  cy.get('h2')
    .should('exist')
    .then($h2 =&amp;gt; {
      debugger
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this section of this tutorial on Cypress debugging, the debugger will only pause the test if the h2 element exists in the DOM since we are saying that the debugger should only pause the test only if the h2 element exists in the DOM.&lt;/p&gt;

&lt;p&gt;Now, let’s run the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2glnl0va7xxkdbhr32g6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2glnl0va7xxkdbhr32g6.png" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, now the debugger only pauses the test after it gets the element and makes sure that the element does exist in the DOM; otherwise, it will throw an error.&lt;/p&gt;

&lt;p&gt;Let’s fail the assertion on purpose and see if the .then() function runs or not&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should only pause when the cy.get() function finishes executing', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  cy.get('[data-cy="some-selector-which-does-not-exist"]')
    .should('exist')
    .then($h1 =&amp;gt; {
      debugger
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Running the test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxy23bdm5c030y5i9iuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxy23bdm5c030y5i9iuv.png" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the screenshot above, the debugger will never pause the test since the assertion has failed and the .then() block did not have a chance to be executed.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/jX3v3N6oN5M"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Run your &lt;a href="https://www.lambdatest.com/jest?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Jest testing&lt;/a&gt; in massive parallel across multiple browser and OS combinations with LambdaTest, Read more!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the .debug() method for Cypress debugging
&lt;/h2&gt;

&lt;p&gt;The .debug() method is a shortcut for Cypress debugging, which you can chain to every other Cypress command wherever in your tests.&lt;/p&gt;

&lt;p&gt;It will expose some details in the browser’s console when the .debug() function triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command Name&lt;/strong&gt;: the name of the last command invoked before the .debug() triggered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command Args&lt;/strong&gt;: the list of arguments passed to the last method before the .debug() invocation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Current Subject&lt;/strong&gt;: a new variable will be created inside the browser with the name subject, which you can interact with using the browser’s console.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subject variable is the return value of the Cypress command and can be interacted with by using the browser’s console.&lt;/p&gt;

&lt;p&gt;Let’s try it out. In this example, I will get the first h2 element on the page.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should pause the test by using the .debug() command', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  cy.get('h2')
    .should('exist')
    .debug() // debugger
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvh5pbpgpm6ie6qma5yl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvh5pbpgpm6ie6qma5yl.png" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, the subject variable represents the return value of the cy.get('h2') command, which means the subject variable is an h2 element.&lt;/p&gt;

&lt;p&gt;When we run the subject.text(), this will give us the text content inside the h2 element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using stack trace for Cypress debugging
&lt;/h2&gt;

&lt;p&gt;A stack trace shows a list of method calls that lead to the exception being thrown, together with the filenames and line numbers where the calls happened.&lt;/p&gt;

&lt;p&gt;Cypress also translates the stack trace so that the actual source file is shown along with its line numbers instead of the file loaded by the browser.&lt;/p&gt;

&lt;p&gt;The Cypress console could be very useful whenever you face an error, luckily, most of the Cypress errors are well explained, and you can easily understand what is going on by simply reading the stack trace.&lt;/p&gt;

&lt;p&gt;You can also integrate it with the VSCode IDE to jump right to where the error was thrown and shown in the stack trace.&lt;/p&gt;

&lt;p&gt;For example, let’s introduce an error by trying to get an element that doesn’t exist in the DOM&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it("should throw an error", () =&amp;gt; {
  cy.visit("https://ecommerce-playground.lambdatest.io/")

  cy.get("some-selector-which-does-not-exist").click()
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Running the test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4znqk90gjbsbofuxe2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4znqk90gjbsbofuxe2a.png" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, Cypress does a great job explaining why and where the error happened.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AssertionError: Timed out retrying after 4000ms: Expected to find element: some-selector-which-does-not-exist, but never found it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you click the “View stack trace” button, you can see the file name in which the error was thrown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8r4ajj41ziurkfg4hcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8r4ajj41ziurkfg4hcw.png" width="791" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click on it, it will ask you to select your IDE to open it. You can choose VSCode from there. If you can not open it, go to the &lt;strong&gt;Settings tab&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Device Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;External Editor&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Visual Studio Code&lt;/strong&gt; or your preferred IDE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgy2gpc0uqyqiyzrfvci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgy2gpc0uqyqiyzrfvci.png" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if you click on the link on the stack trace dropdown, it will automatically open that file and navigate to that specific line where the error was introduced.&lt;/p&gt;

&lt;p&gt;This is a very good feature of &lt;a href="https://www.lambdatest.com/cypress-ui-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress UI automation&lt;/a&gt; tool, helps you easily spot errors and locate where the error happened.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test your &lt;a href="https://www.lambdatest.com/puppeteer-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Puppeteer test&lt;/a&gt; scripts online. Deploy a quality build faster by running automated checks across over 3000+ browsers and OS combinations with the LambdaTest cloud. Try for free!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using logs for Cypress debugging
&lt;/h2&gt;

&lt;p&gt;Using logs or console logs is another way to debug your code and get an understanding of what is going on when executing tests.&lt;/p&gt;

&lt;p&gt;There are two different commands that you can use for logging outputs inside of your browser’s console, which is the cy.log() and the conventional JavaScript console.log() function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Console log
&lt;/h2&gt;

&lt;p&gt;Since all Cypress commands are asynchronous and will be enqueued for later use, you should never assign returning values of any Cypress command.&lt;/p&gt;

&lt;p&gt;If you want to console.log() a returning value of any Cypress command, you should do so inside the .then() function.&lt;/p&gt;

&lt;p&gt;If you log a returned value from a Cypress command, it will be logged in the browser’s console, but the value will be just a Cypress Chainer Object.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should not return the h2 element', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  const h2 = cy.get('h2')

  // do not do this, the value will not be the actual "h2" element
  console.log(h2)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is the result that you’ll get, which is not very useful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focxmdh8d8hnjqj622sjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focxmdh8d8hnjqj622sjz.png" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to log the return value of any Cypress command, the right way to do it is by logging the value inside of a .then() function. This way, you will get the actual element after you log it.&lt;br&gt;
This is the right way to do it.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;('should return the actual h2 element', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  cy.get('h2').then($h2 =&amp;gt; {
    // this will log the actual value of the "h2" element
    console.log($h2)
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you want to log the text of the element:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should return the text of h2 element', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  cy.get('h2').then($h2 =&amp;gt; {
    // gets back the text inside the "h2" element
    console.log($h2.text())
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The result in the browser’s console is the text inside of the h2 element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs45176gemfioe6nqcyfc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs45176gemfioe6nqcyfc.png" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using the Cypress log command
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.lambdatest.com/cypress-automation-tool?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress automation tool&lt;/a&gt; provides us with another useful command that will help us log outputs inside of Cypress’s dashboard logger.&lt;/p&gt;

&lt;p&gt;You can use the command by running cy.log() anywhere in your code.&lt;/p&gt;

&lt;p&gt;If you want to log the output of a Cypress command, just make sure you do it inside the .then() function since Cypress commands are being enqueued and not instantly executed.&lt;/p&gt;

&lt;p&gt;The difference between the regular console.log() function and the Cypress log() function is that the Cypress log() function will log the output inside of the Cypress console, but the console.log() command will log it inside of the browser’s console.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should log the return value inside of the Cypress console', () =&amp;gt; {
  cy.visit('https://ecommerce-playground.lambdatest.io/')

  cy.get('h2').then($h2 =&amp;gt; {
    cy.log($h2.text())
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The result in the Cypress console:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22xroi037t7dnfepyx0k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22xroi037t7dnfepyx0k.png" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using .pause() command for Cypress debugging
&lt;/h2&gt;

&lt;p&gt;Cypress exposes another command which helps in pausing the test execution and making it easily debuggable, you can then manually start the test again and resume executing Cypress commands.&lt;/p&gt;

&lt;p&gt;The .pause() command is also a Cypress chainable and can be chained with any other Cypress command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cypress.pause() example of use&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it("should pause the test", () =&amp;gt; {
  cy.visit("https://ecommerce-playground.lambdatest.io/")

  cy.get("input[name='search']")
    .first()
    .should("exist")
    .and("be.visible")
    // pauses the command execution
    .pause()
    .type("Iphone 12")
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In this section of this tutorial on Cypress debugging we are getting the input elements in the DOM, which has a “name” attribute of “search,” and we are selecting the first one by running the .first() command.&lt;/p&gt;

&lt;p&gt;And we are asserting two assertions on them; after that, we are typing something inside of the input, but just before typing the input, we have run the .pause() method.&lt;/p&gt;

&lt;p&gt;The code will run the first three commands and pause before running the fourth and final commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running the test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh00c3ayd9hlcv7a3jskt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh00c3ayd9hlcv7a3jskt.png" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, a new button has appeared on the top of the Cypress console, and also, we can see in the final output of the logs it is written - pause, which is caused by our pause command.&lt;/p&gt;

&lt;p&gt;Now, if we press the play button, the test will resume, and the commands will resume executing again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resuming the test execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lc1keylhgwdib3z6oyt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lc1keylhgwdib3z6oyt.png" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test will resume, and the last command will then be executed. Finally, the text will be typed inside of the search input.&lt;/p&gt;
&lt;h2&gt;
  
  
  [Bonus Tip] How to reduce type errors in Cypress?
&lt;/h2&gt;

&lt;p&gt;I will give you a bonus, this one is not for Cypress debugging but for reducing and spotting errors inside of your application before running the tests, and it will provide you with a faster development pace.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use TypeScript
&lt;/h2&gt;

&lt;p&gt;TypeScript is a programming language that enables developers to write code in a type-safe way. Since Cypress ships with the official type declarations and is strongly typed, it will be easier for developers to spot and find type errors before running the tests.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install TypeScript
&lt;/h2&gt;

&lt;p&gt;Install typescript by running the following command.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: TypeScript 3.4+ is required to be used with Cypress.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Create a tsconfig.json file inside of the cypress folder with the following configurations.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "target": "es5",
    "lib": ["es5", "dom"],
    "types": ["cypress", "node"]
  },
  "include": ["**/*.ts"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Adding types for your custom commands
&lt;/h2&gt;

&lt;p&gt;It is also important for you to add types for the custom commands that you will create and use throughout your tests and Cypress allows you to do that.&lt;/p&gt;

&lt;p&gt;Let’s say you have the following command.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cypress.Commands.add("login", (email, password) =&amp;gt; {
  /**
   * Login to the application
   * With Cypress
   * ...
   */

  return "{ ... }"
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you don’t declare the types for the login custom command, you will get a TypeScript error instantly, so let’s go ahead and create the types for it.&lt;/p&gt;

&lt;p&gt;Inside your support folder, create a file with the name index.ts and add the following code.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// cypress/support/index.ts
declare global {
  namespace Cypress {
    interface Chainable {
      login(email: string, password: string): string
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now your Cypress tests should be able to work with TypeScript perfectly. If you are still getting errors, restart the TypeScript server by pressing the Ctrl+Shift+P on Windows or CMD+Shift+P on macOS and type &amp;gt; in the beginning and search for &amp;gt;TypeScript: Restart the TS server and press it. This will restart your TS server and load the new configurations.&lt;/p&gt;

&lt;p&gt;Now you will see an autocomplete option for all of the Cypress commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsgtky2ix288ksjvdxlz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsgtky2ix288ksjvdxlz.png" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will also see an autocomplete option for your custom commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftaci0su0wl1acor5xh8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftaci0su0wl1acor5xh8e.png" width="579" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get accurate results, you must run Cypress tests on real browsers and OS. The best way to do this is by using LambdaTest’s cloud-based &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automation testing&lt;/a&gt; platform. Accelerate your go-to-market delivery by performing &lt;a href="https://www.lambdatest.com/cypress-parallel-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress parallel testing&lt;/a&gt; on 40+ versions on the latest across Windows and macOS without compromising accuracy.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/jrgx_3gfWVA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Subscribe to the &lt;a href="https://www.youtube.com/c/LambdaTest?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest YouTube channel&lt;/a&gt; for tutorials around &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/blog/playwright-framework/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Playwright browser testing&lt;/a&gt;,&lt;a href="https://www.lambdatest.com/appium-mobile-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt; Appium&lt;/a&gt;, and more.&lt;/p&gt;

&lt;p&gt;If you’re a developer who needs to perform &lt;a href="https://www.lambdatest.com/cypress-e2e-testing" rel="noopener noreferrer"&gt;Cypress end-to-end testing&lt;/a&gt; for your app and you’d like to get an overview of everything Cypress has to offer, the Cypress 101 certification is for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test your website or web app online for iOS browser compatibility. Perform seamless cross browser testing on the latest &lt;a href="https://www.lambdatest.com/test-on-iphone-simulator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;iPhone tester&lt;/a&gt; Simulator. Try for free!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this Cypress debugging tutorial, we have discussed the best ways to debug Cypress tests easily. &lt;a href="https://www.lambdatest.com/cypress-ui-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Cypress UI testing&lt;/a&gt; is an excellent framework for validating your front-end applications. It provides us with many great features to debug our &lt;a href="https://www.lambdatest.com/learning-hub/test-suite?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov18_kj&amp;amp;utm_term=kj&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test suites&lt;/a&gt; easily.&lt;/p&gt;

&lt;p&gt;Here are the different ways to debug your Cypress tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using a debugger.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using .debug() Cypress command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the stack trace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using logs console.log() and cy.log().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the Cypress .pause() command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using TypeScript to reduce type errors.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
    </item>
  </channel>
</rss>
