Selenium has been my go-to tool for UI test automation for a while, and for good reason. It was the front-runner, proving its worth time and time again. I’ve used it extensively but lately, I’ve leaned towards Cypress. I made a course on Cypress (all of the exercises can be found in my GH), I’ve become thoroughly convinced that it presents a more efficient and reliable alternative.
When it comes to analysing the differences between Selenium and Cypress, a few key factors stand out. Selenium supports multiple languages including Java, Python, C#, and others while Cypress is purely JavaScript. This could initially seem limiting but considering most web applications are now JavaScript-based, Cypress becomes a natural choice. Selenium tests run outside the browser while Cypress runs directly inside the browser. This lets Cypress take control of the entire automation process including network traffic, timers, and even the loading of JavaScript code. It’s this inner control that promises stability – a promise Selenium often can’t keep due to its reliance on numerous third-party factors. The possibility to test your automation with debugger options in the browser is game-changer, I spend a lot of time understanding my scripts using the console, styles and network tabs, I am sure FE developers are all very familiar with them.
Cypress provides a simple and comprehensive API to interact directly with the DOM, allowing you to write simple, effective tests, take a look:
describe('DOM Interactions Test', function() {
it('Fills and submits a form', function() {
cy.visit('https://www.example.com/form') // Cypress loads the webpage
cy.get('input[name="firstName"]').type('John') // Cypress finds the input field firstName and types 'John' into it
cy.get('input[name="lastName"]').type('Doe') // Cypress finds the input field lastName and types 'Doe' into it
cy.get('button[type="submit"]').click() // Cypress clicks the submit button
})
})
Compare this with Selenium
WebDriver driver = new ChromeDriver();
driver.get("https://www.example.com/form"); // Open URL
WebElement firstName = driver.findElement(By.name("firstName"));
firstName.sendKeys("John"); // Fill the firstName input
WebElement lastName = driver.findElement(By.name("lastName"));
lastName.sendKeys("Doe"); // Fill the lastName input
WebElement submitButton = driver.findElement(By.tagName("button"));
submitButton.submit(); // Submit the form
Cypress let you interact with CSS selectors!
Another key advantage of Cypress is its ability to handle asynchronous operations very easily.
describe('Asynchronous Handling Test', function() {
it('Waits for an element to be visible', function() {
cy.visit('https://www.example.com') // Cypress loads the webpage
cy.get('#asyncButton', { timeout: 10000 }) // Cypress waits for the element with id 'asyncButton' to become visible for up to 10 seconds
.should('be.visible') // Asserts that the element should be visible
.click() // Clicks the button once it's visible
})
})
Dealing with API’s is also a breeze:
describe("Todo List API Interaction", () => {
// Define the base URL of your API
const apiUrl = "https://example-api.com";
beforeEach(() => {
// Intercept the API call and load a JSON payload for the response
cy.intercept("GET", `${apiUrl}/todos`, { fixture: "todos.json" }).as("getTodos");
// Visit the application or a specific page where the API call is made
cy.visit("/todo-list");
});
it("should fetch todos from the API and display them", () => {
// Perform any actions that trigger the API call (e.g., click a button to fetch todos)
cy.get("#fetch-todos-btn").click();
// Wait for the API call to complete and the response to be displayed
cy.wait("@getTodos");
// Assert that the correct API endpoint was called and the response was handled properly
cy.get(".todo-item").should("have.length", 3); // Assuming the response contains 3 todo items
});
});
What to me is the big advantage is my caveat: interacting with CSS selectors demands that you be careful to choose those that are least likely to change and break your tests. Still, I only plan to use Cypress for my UI tests.