Skip to content
Dev Discovers

Cypress vs. Selenium: A Comparison for Integration Testing

testing, cypress, selenium7 min read

Integration testing is an essential part of software development that ensures the interoperability of different modules and components of an application. It verifies that the software is working correctly as a whole, instead of just testing individual pieces. To perform integration testing, developers rely on a range of testing frameworks, including Cypress and Selenium.

Cypress is an open-source JavaScript-based testing framework that enables developers to write end-to-end tests and perform integration testing of web applications. It runs directly in the browser and provides an extensive set of APIs and libraries to simulate user interactions and test the functionality of web pages.

Selenium is another widely-used testing framework for performing automated testing of web applications. Selenium supports various programming languages and is compatible with different web browsers, operating systems, and devices. Selenium allows developers to write and execute test scripts in a range of programming languages, including Java, Python, Ruby, and more.

Comparison Table

Before we take a deeper look at these two frameworks, here is a table comparing some of their features at the time of this writing. We will dive into some of these features more later in the article.

Please note that some of these observations are subjective. :)

FeatureCypressSelenium
Browser SupportLimited to Chromium-based browsersSupports most popular browsers
Mobile Web SupportYesYes
Native Mobile SupportNoYes
LanguageJavaScriptMultiple languages (Java, Python, etc.)
Underlying FrameworkMochaNone (can be used with language-specific frameworks)
Execution MethodRuns directly in the browserRequires a separate driver
Locator SupportCSS selectors, custom selectors, XPathCSS selectors, XPath, etc.
Development SupportBuilt-in dev tools, time-travel debuggingThird-party tools, debugging clients
Test ReportingBuilt-in, with video and screenshot supportRequires external plugins or libraries
Screenshot SupportBuilt-inRequires external plugins or libraries
Video SupportBuilt-inRequires external plugins or libraries
Execution SpeedFaster due to direct access to browserSlower due to reliance on a driver
Waiting for ElementsAutomatic waiting, no need to use explicit waitsRequires explicit waits
Debugging SupportExcellent, with helpful error messagesNot as comprehensive as Cypress
Mock API SupportBuilt-inRequires external plugins or libraries
Mock Spies/ClocksBuilt-inRequires external plugins or libraries
Driver DependencyNoneSelenium WebDriver
Retry SupportBuilt-inRequires external plugins or libraries
Headless ExecutionYesYes
SetupEasyMore complicated than Cypress
DocumentationExcellentGood
Learning CurveLowHigh

Benefits and Limitations of Cypress

Cypress has several benefits for integration testing. Firstly, it provides a fast and easy setup process, allowing developers to get started quickly with little effort. Secondly, Cypress comes with a range of built-in testing features and tools, such as the ability to take screenshots, record videos, and debug tests in real-time. Thirdly, Cypress has a unique architecture that allows it to run directly in the browser, providing real-time feedback and faster test execution times.

However, Cypress has some limitations that developers should be aware of. Firstly, Cypress is primarily focused on front-end testing, making it less suitable for testing back-end functionalities. Secondly, Cypress has limited cross-browser support, only supporting Chrome-based browsers, Firefox, and Electron. Lastly, Cypress's unique architecture means it cannot perform certain types of testing, such as file downloads or handling multiple windows or tabs.

Benefits and Limitations of Selenium

Selenium is another popular testing framework for integration testing. Firstly, Selenium supports multiple programming languages, making it highly flexible and compatible with different development stacks. Secondly, Selenium supports cross-browser and cross-platform testing, enabling developers to test their applications on different web browsers and operating systems. Lastly, Selenium has a large and active community, with many online resources and support available.

However, Selenium also has its limitations. Firstly, setting up Selenium can be more challenging than Cypress, as it requires installing the Selenium WebDriver and configuring it for the specific browser and operating system. Secondly, Selenium tests can be slower compared to Cypress, as it interacts with the browser through the WebDriver, which can cause delays. Finally, Selenium requires a more significant learning curve for beginners due to its complexity.

When to Use Cypress vs. Selenium

Cypress and Selenium have different use cases and should be chosen based on the specific requirements of the project. Developers should consider using Cypress when they want a fast and straightforward testing framework for front-end web applications.

On the other hand, developers should choose Selenium when they need to perform complex testing scenarios, such as cross-browser testing or testing back-end functionalities.

Code Examples

Let's take a look at some code examples using both Cypress and Selenium to highlight their differences in syntax and functionality.

Waiting for Elements

Here's a simple example of a Cypress test case that navigates to a web page, performs a login, and verifies the presence of a success message:

describe('Login form', () => {
it('Should login successfully', () => {
cy.visit('/login');
cy.get('[data-cy=email-input]').type('user@example.com');
cy.get('[data-cy=password-input]').type('password');
cy.get('[data-cy=login-button]').click();
cy.get('[data-cy=success-message]').should('be.visible');
});
});

In the Cypress example, the test automatically waits for the elements to appear on the page before attempting to interact with them. The cy.get() command will automatically retry until the element is found or the specified timeout is reached. The cy.get().should() command will also automatically retry until the specified condition is met or the timeout is reached.

Here's an equivalent Selenium test case that achieves the same thing:

@Test
public void loginTest() {
driver.get("https://example.com/login");
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement emailInput = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("[data-cy=email-input]")));
WebElement passwordInput = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("[data-cy=password-input]")));
WebElement loginButton = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-cy=login-button]")));
emailInput.sendKeys("user@example.com");
passwordInput.sendKeys("password");
loginButton.click();
WebElement successMessage = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("[data-cy=success-message]")));
assertTrue(successMessage.isDisplayed());
}

In the Java Selenium example, explicit waits are used to wait for the elements to become available. The WebDriverWait object is used to wait for specific conditions to be met, such as the element to be present, clickable, or visible. Once the conditions are met, the test will proceed to interact with the elements.

Mocking Support

Cypress provides mocking support for APIs, spies, and clocks out-of-the-box since it runs directly in the browser. This is tricky, and even impossible at times, for Selenium-based frameworks since they run through a web driver.

Here are some example Cypress tests showcasing its mocking features:

describe('Mocking APIs, Spies, and Clocks in Cypress', () => {
it('Mocks an API call and verifies the response', () => {
cy.intercept('GET', 'https://jsonplaceholder.typicode.com/posts/1', { fixture: 'post.json' })
.as('getPost')
cy.visit('https://example.com')
cy.wait('@getPost').its('response.body').should('have.property', 'title', 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit')
})
it('Spies on a function call and verifies it was called', () => {
cy.visit('https://example.com')
cy.window().then(win => {
cy.spy(win.console, 'log').as('consoleSpy')
win.console.log('Hello, world!')
cy.get('@consoleSpy').should('have.been.calledWith', 'Hello, world!')
})
})
it('Mocks the clock and verifies a timeout function is called', () => {
cy.clock()
cy.visit('https://example.com')
cy.window().then(win => {
cy.spy(win, 'setTimeout').as('timeoutSpy')
win.setTimeout(() => {
win.console.log('Hello, world!')
}, 1000)
cy.tick(1000)
cy.get('@timeoutSpy').should('have.been.calledOnce')
})
})
})

Final Thoughts

Integration testing is an important part of any software development process, and choosing the right tool for the job can make a big difference in the effectiveness and efficiency of your testing. Cypress and Selenium are two popular integration testing frameworks with different strengths and weaknesses.

Cypress is a great choice for testing modern web applications that use frameworks like React or Angular. Its declarative syntax and built-in debugging tools make it easy to write and debug complex tests. However, Cypress is limited to testing web applications, and cannot be used to test native or hybrid mobile apps.

Selenium, on the other hand, is a more general-purpose testing tool that can be used to test a wide variety of applications, including web, mobile, and desktop applications. Its imperative API makes it more flexible than Cypress, but also more difficult to use for testing modern web applications that use complex JavaScript frameworks.

In general, if you're testing a modern web application, Cypress is likely the better choice. If you're testing a non-web application or need more flexibility in your testing approach, Selenium may be a better fit.

© 2023 by Dev Discovers. All rights reserved.
Theme by LekoArts