What Is End-To-End Testing? E2E Testing Tutorial With Examples and Best Practices
A comprehensive end-to-end Testing tutorial that covers what E2E Testing is, its importance, its benefits, and how to perform it with real-time examples.
Join the DZone community and get the full member experience.Join For Free
End-to-end testing, or E2E testing, as the name suggests, is the testing methodology that validates a software workflow from start to end. The primary goal of E2E testing is to simulate an end user's application journey and ensure that all integrated components, dependencies, and other integrated pieces work as expected.
While this looks obvious that the testing has to be done with all components attached, end-to-end testing is the last stage of testing and is usually done infrequently. This is especially so if the application under test is extensive, i.e., it has hundreds of components and thousands of dependencies.
What Is End-To-End Testing?
End-to-end testing involves testing all aspects of an application from start to finish. It ensures that an application's flow works or behaves as expected. By simulating a real-world scenario as close as possible to what real end users do, E2E testing helps you improve your team's software.
This execution of complete user workflows is more comprehensive than unit testing or integration testing methodologies. Usually, it involves executing the program along with all possible dependencies, including the database, outside services, metrics, logging, etc. Again, the aim is to be as close as possible to real-world scenarios.
Therefore, in ideal E2E tests, all components and dependencies are usually validated rather than just a selected set of features, like in integration testing. End-to-end testing can be done both manually or via automation scripts.
Why Is E2E Testing Important?
Modern applications are built using hundreds of components and thousands of dependencies, all deployed on an ecosystem of infrastructure layers composed of multiple parts working together. All this complexity creates massive avenues of unpredictable failures. A single isolated system could be working smoothly and perfectly. However, a collection of such systems may create conflicts with each other and create issues.
Therefore to ensure final quality assurance of all moving parts, it is essential to simulate how the end user will interact with the final application composed of all components and dependencies. This calls for running end-to-end testing of all workflows ranging from simple steps to complex workflow scenarios.
End-to-end tests rely on user behavior, which can be seen during usability testing and recorded in tickets. Before delivering the product to end-users, end-to-end tests make it easier to find issues. End-to-end tests assist managers in setting priorities for activities in the development backlog by determining the significance of a process to users in real life.
End-to-end testing can also enhance the user experience. User expectations form the basis for test cases, particularly for applications that require a lot of user engagement, like web and desktop apps.
End-To-End Testing Is Prevalent Since It:
- Enables release teams to automate crucial user pathways, reducing the time to market.
- Decreases the time needed to test software, lowering the overall cost of producing and maintaining software.
- Runs the test cases depending on the end user's behavior to ensure the application functions properly.
- Adds more specific test cases than other testing techniques like unit and functional testing, which helps teams increase their test coverage.
- End-to-end tests are the best indicator of application health.
- Writing end-to-end testing test cases is relatively simple and intuitive as it mimics real-world scenarios. It’s also easier for a tester to start writing E2E tests as it’s easier to write black box E2E tests.
- End-to-end testing has a broader range of test case coverage, and you can easily expand coverage of new components by adding steps in test scenarios.
Each software is connected to and integrated with various external databases and systems. It should go without saying that this makes the app's workflow more complex. E2E testing verifies that an application's many dependencies are operating correctly. It also checks whether precise data is being communicated between different system components.
- Backend: E2E testing looks at an app's backend code and database. Backend functionality is necessary since it is essential to the program's primary functions.
- Multi-tier Architecture: When an application has a complex architecture with a multi-tier workflow, E2E testing is necessary to verify the system's overall operation and the interactions between its many levels.
- Distributed Environment: Applications created in cloud or SOA (service-oriented architecture) environments must undergo E2E testing. Furthermore, multi-part apps must work smoothly for them to function.
- Consistent User Experience: Because E2E testing covers the front, it also ensures that the app's user experience is adaptable to various hardware, software, and environment configurations. Cross-browser testing, for instance, is essential.
Testing Pyramid is a software development framework that can foster high-quality code by minimizing the time required for developers to determine if changes affect the existing code. It also aids in developing a more robust test suite.
The testing pyramid is a model that provides a structure for the types of tests to be performed in automation testing suites. It also defines the order and frequency of such assessments. The purpose is to provide rapid feedback to ensure that code changes do not impact existing functionality.
The test automation pyramid consists of three levels:
- Unit Tests
- Integration Tests
- End-to-end Tests
Unit tests serve as the foundation of the test pyramid. The team executes pre- and post-commit tests in this pyramid layer, which are developer triggered. Tests have a limited scope and ensure that isolated code units function as expected without depending on external dependencies.
Integration tests are a crucial part of the software testing life cycle. Unit tests check small portions of a codebase, while integration tests ensure that the software communicates efficiently and retrieves accurate data to perform as expected. Integration tests ensure that your software interacts with external components, such as APIs and databases. Integration tests can ensure that data is retrieved on time and that your software communicates efficiently with these external components.
Integration tests are slower and more complex than unit tests because they require interaction with external sources. They also need a pre-production environment to run. Having the right balance of virtual and real devices is critical for running integration tests.
End-to-end testing checks all of the code that was written for an application and is the most expensive to maintain. It uses a test environment and data to simulate real-world functionality and has the slowest operating pace. Because it checks assembled applications, it is also the most difficult to identify issues with.
End-to-end tests are the most expansive form of automated testing and can be the most time-consuming part of a testing cycle. They often have unreliable external dependencies like integration tests and can take a long time to set up and run.
Key Benefits of End-to-End Testing
Some of the key benefits of end-to-end testing that can help you on your testing journey are listed below:
- Ensuring Correctness and Health of the Application:
End-to-end testing validates an application at all layers – data, business rules, integration, and presentation. Doing so helps ensure the application's correctness and health.
- Increases Confidence:
End-to-end testing not only ensures that the application functions correctly but also increases confidence in its performance because it is tested across multiple devices and platforms.
- Reduces Risks:
The end-to-end testing process allows for rigorous testing of the application at the end of each sprint and iteration, which reduces the risk of failure in the future.
- Less Repetitive Efforts:
End-to-end testing allows for more thorough testing, which reduces the chances of frequent breakdowns and ultimately reduces repetitive testing efforts.
- Reduces Cost and Time:
By automating your end-to-end tests, you can reduce the number of times you need to test an application, which in turn reduces the amount of time and money it takes to maintain and improve that application.
E2E Testing Example
Let's imagine that testers need to confirm that a Gmail account is operational. The following attributes need to be examined:
- To open the Gmail login page, enter the URL into the address box.
- Enter your account using legitimate credentials.
- Access Inbox. Examine your read and unread emails.
- Create a fresh email.
- Respond to and forwarded an email.
- Open the Sent Items folder. Verify your emails there.
- Go to the Spam folder. Verify your emails there.
- To exit Gmail, click the "Logout" button.
End-to-End Testing Lifecycle
- Test Preparation: This phase outlines the primary duties, timetable, and resources involved.
- Test Plan: The second phase consists of the creation of test specifications, test cases, usage, and risk analysis, and the scheduling of tests.
- Testing: Carries out test scenarios and records testing outcomes.
- Results Analysis: Analyze test results, evaluate testing, and perform additional testing if necessary.
Types of End-to-End Tests
E2E testing is divided into two categories:
- Manual end-to-end testing
- Automated end-to-end testing
Manual End-to-End Testing
Manual testing is a common software testing performed directly by a human tester. This helps testers identify test cases and uncover hidden user interaction paths in the system, which provide the required information to start automating these tests in the future. Tests that were built manually can also become automated tests.
Manual end-to-end testing can be conducted in two ways:
- Horizontal End-to-End Testing
Horizontal end-to-end testing looks at an application from a broad perspective. It requires software development teams to have well-defined workflows and established test environments. In this type of testing, a single test workflow can span multiple subsystems. A plan for simultaneously testing UI, a database, and email integration is an example of a horizontal end-to-end test.
- Vertical End-to-End Testing
Vertical end-to-end testing is a way of testing an application by breaking it down into layers, which can then be tested individually. It is often used before horizontal testing because of its granularity. For example, if you are testing user interface subsystems, you can easily identify and fix bugs.
Automated End-to-End Testing
As your project continues to grow, performing all end-to-end testing manually will become impractical. Automated user-interaction testing is essential for projects with large user interfaces because of the complexity involved in a single action; many actions can be taken depending on the user's inputs. Manual tests are time-consuming and challenging to manage as a project grows in size and complexity.
Once you’ve decided on the test cases, write them as code and integrate them with an automated testing tool. For example, you can use a CI/CD pipeline to automate the end-to-end testing of software. As new features are added to software at increasingly faster rates, you can catch bugs quicker as automation has the entire code base automatically checked against the test cases each time you add new code.
Layers Involved In E2E Testing
In end-to-end testing, you test all layers or components of an application - from the user interface (UI) to the database. The following are some of the layers involved in E2E testing:
- Presentation Layer:
The presentation layer is the user interface of an application, including elements such as buttons, forms, and menus. E2E testing of the presentation layer involves testing these UI elements' functionality, performance, and usability.
- Application Layer:
The application layer is part of an application that deals with processing data and coordinating the different parts of the application. E2E testing of this layer will help ensure that your application logic functions correctly, is secure, and performs well
- Integration Layer:
The integration layer is the connection point between various parts of an application. This layer may comprise APIs, web services, or other interfaces. E2E testing of the integration layer involves testing the functionality and compatibility of these interfaces as well as their performance.
- Data Layer:
The data layer includes the application's database and data storage components. To test these components, you must test the database and data storage components' functionality, performance, and security.
E2E Testing Checklist
E2E is not just about testing the user interface because a user interface is made of numerous distinct components.
The content for a blog site may be fetched from a database via an API. Therefore, the frontend design, the database, and the API must be tested independently and in conjunction in this situation.
Here Is a List To Use as a Guide for E2E Tests:
- Database: It would be necessary to test the database that is used by your system. You might perform tests to ensure that data is correctly organized, stored, read, and updated.
- Performance: A website may navigate properly, but user experience depends on speed. Therefore, testing a page's or feature's usability is crucial.
- Security: The degree of an application's user and organizational security is determined by its web application security. In this situation, vulnerability testing techniques are very crucial. The primary driver for testing in the first place is functionality. Every feature must work as intended. Unit tests may also be helpful in this situation.
- Usability: Given their intended purpose, components must be helpful. Tests must cover events (such as clicks on components), proper navigation, and other issues because users are just as vital as the technology.
End-to-End Testing Process
End-to-end testing is a complex process requiring significant planning and coordination between the development and testing teams.
Follow these steps to ensure your system meets the requirements and functions correctly.
- Requirement Gathering: The first step in end-to-end testing is to gather requirements. This involves understanding the scope of the system and its features and functionality, as well as how they'll be tested.
- Test Planning: The next step in testing a system is to plan the test cases that will be used to evaluate its performance. This includes defining the test scenarios, identifying the test data, and creating the test cases.
- Test Environment: To ensure that your end-to-end tests are effective, you need to set up a test environment that mimics the production environment. Setting up a test environment for end-to-end testing requires installing and configuring hardware, software, and network infrastructure.
- Test Execution: Once the test environment is set up, you can run the test cases to simulate real-world usage scenarios. Running these test cases helps identify defects or issues that need to be fixed.
- Defect Resolution: After defects are identified, the development team fixes them and re-tests the system to ensure they have been resolved.
- Test Reporting: Test reports are essential to provide transparency and help stakeholders understand the system's overall performance and any issues found during testing.
Metrics To Use In End-to-End Testing
In end-to-end testing, measuring and tracking various metrics is important to ensure the system works correctly. Here are some of the most commonly used metrics in end-to-end testing:
- Test Coverage: It is a metric that indicates how thoroughly your tests have been executed. It's essential to achieve high test coverage to identify defects and ensure that all critical functionalities are thoroughly tested.
- Test Cycle Time: Test cycle time is the amount of time it takes to complete a test cycle, including planning, execution, and reporting. Keeping test cycle time short ensures that the system is tested frequently, enabling any issues to be identified and resolved quickly.
- Defect Density: The defect density metric measures the number of defects found per unit of code or functionality and can help identify areas that need improvement. This information can guide the allocation of resources to fix the issues identified.
- Error Rate: The error rate measures the percentage of test cases that failed during testing. A high error rate can indicate problems with the system and suggest further testing is needed.
- Test Case Effectiveness: Test case effectiveness measures the number of defects found in the system by a test case. This helps evaluate the quality of the test cases and identify areas where additional testing is required.
- Test Environment Stability: This metric measures the stability of the test environment, including the hardware, software, and network infrastructure. Stable testing conditions ensure that your results are accurate.
Using these metrics can help identify potential problems, improve the quality of the end-to-end testing process, and ensure that the system meets requirements.
Creating End-to-End Test Cases
The end-to-end testing design framework is comprised of three parts:-
- Build user functions
- Build Conditions
- Build Test Cases
Here is the detailed view:-
Build User Functions
The actions listed below must be carried out as part of the build user functions:
- List the system's features and the ways they are connected.
- List the input, action, and output data for each feature or function.
- Determine the connections between the functions.
- Ascertain whether the function is standalone or reusable.
For instance, if you logged into your bank account and transferred money to a third-party account at another bank.
Build Conditions Based on User Function
The following tasks are considered as part of the build conditions:
- Establishing a set of requirements for every user function specified.
- Sequence, timing, and data conditions are examples of conditions.
For example, checking of more conditions like:
- Invalid username and/or password.
- Check your username and password.
- Checking password strength.
- Checking of error messages.
- Check if the transfer has been completed within 24 hours.
- If you do not have enough money in your account to complete the transfer, the transaction will fail.
Build a Test Scenario
We will construct a test scenario for the specified user function:
In this instance,
- Enter the system.
- Verify your bank balance.
- Transfer your bank balance.
End-to-End Testing vs. System Testing
Let's look at the detailed difference between end-to-end testing and system testing.
End-to-End Testing vs. Functional Testing
Functional testing is a verification process that compares each software function or feature with an organization's specifications to ensure the software provides the output required by users. Functional testing confirms that applications meet customer requirements since the process tries to reflect the real-world usage of a product closely. If a system passes functional testing, it can be verified for release.
End-to-end tests are similar to functional tests in that they consider the user experience. However, differences include the following:
- Scope: Functional tests verify that each step in a process works as expected, while E2E tests confirm that the entire process from start to finish can be completed.
- Acceptance: Functional tests ensure that software meets established acceptance criteria, while end-to-end tests ensure that a process continues to work after software changes.
- Types of tests: E2E testing can take a horizontal or vertical approach. However, there are numerous types of functional testing, including smoke testing, sanity testing, blackbox testing, integration testing, and user acceptance testing.
Tools Used for End-to-End Testing
Here are the top tools that are used for end-to-end testing:
LambdaTest is an intelligent unified digital experience testing cloud that helps businesses drastically reduce time to market through faster test execution and quality releases. The platform allows you to perform both real-time and automation testing across 3000+ environments and real mobile devices, making it a top choice among other cloud testing platforms.
Over 10,000+ enterprise customers and 2+ million users across 130+ countries rely on LambdaTest for their testing needs.
Selenium is a powerful and widely used open-source automation testing tool that has become the standard for end-to-end testing of web applications. Selenium can simulate user interactions with a web application, allowing testers to create automated test scripts that check your application's functionality.
Selenium's cross-browser compatibility is one of its most significant benefits. This feature allows web applications to be tested on multiple browsers such as Chrome, Firefox, Safari, and Internet Explorer.
The tool supports various testing frameworks such as TestNG, JUnit, and NUnit. These frameworks help create test suites and manage test cases while generating reports that testers can use to create and manage their tests in a structured manner.
Selenium consists of various tools such as Selenium WebDriver, Selenium Grid, and Selenium IDE. WebDriver is one component of the Selenium framework, which allows programs to interact with browsers and control the behavior of User Agents. WebDriver is a remote control interface that allows programs to manipulate DOM elements in a web document and perform actions such as clicking links or submitting forms.
The Selenium framework uses the WebDriver's language-neutral protocols to automate testing steps. In other words, the WebDriver is the bridge between the Selenium framework and the end browser over which the test is being executed.
It is a new testing platform that aims to overcome the challenges of automated front-end testing for applications built with React and AngularJS. It's quicker, easier, and more reliable than Selenium for running tests on real browser instances. Since Cypress executes tests on a browser instance, you wouldn't need to download browser drivers.
End-to-end testing with Cypress is the go-to choice for testing the integration between two or more systems. Doing so can ensure that various dependencies of an application are working accurately and that accurate information is being communicated between multiple system components.
Playwright is a powerful and new tool that helps you build modern web applications and offers you end-to-end testing and cross-browser testing capabilities.
Although Playwright is new to the market, it already has several features that make it a strong competitor. People who want to migrate from Selenium to Playwright can do so quickly since Playwright supports C#, Java, and Python. Programmers aren't limited by the language they use; Playwright's first release was in January 2020, and its popularity has grown steadily since then.
The process of writing, automating, and maintaining E2E tests is tedious and time-consuming. Testers have found that having to write E2E tests is not fun at all. The flakiness of the tests made them difficult to maintain. Playwright takes care of auto-waiting for elements to be ready for execution, like clicks and page navigation.
Playwright for end-to-end testing provides options to capture screenshots while an E2E test is running. Options include taking a screenshot of the entire page or a specific element on the page. In addition to saving the screenshot, you can get a buffer with the image and post-process it. If an E2E test fails, the page screenshot will be handy for determining what went wrong and fixing it.
Playwright is an open-source library to help you write end-to-end tests for your application. Using the codegen feature and taking advantage of its built-in assertions and mocks, you can get started with Playwright's library in just a few minutes.
Puppeteer is a new framework that allows testers to perform headless browser testing of Google Chrome. Puppeteer testing will allow for easier and faster end-to-end test automation of web pages and applications.
Puppeteer is a browser automation tool built on top of Chromium's DevTools Protocol, a protocol for communicating with browsers from user scripts. It lets you run headless Chrome in Node.js to perform a majority of tasks performed by a developer when debugging, such as handling requests and responses, locating elements, network traffic, and so on.
Puppeteer can help you automate your end-to-end testing. With Puppeteer, it’s as easy as writing a few lines of code. No special configuration is needed to get started. When you download Puppeteer, it installs its version of Chrome. But if you prefer to use a browser you already have installed, you can install the puppeteer-core package.
There are more frameworks that you can leverage for E2E as well like:
Running End-to-End Tests With LambdaTest
If you lack the required testing tools, testing can always be arduous. LambdaTest offers a cross-browser testing platform that can help developers and testers get beyond the current testing difficulties involving various devices and supported platforms.
Manual End-to-End Testing Using LambdaTest
LambdaTest offers manual end-to-end testing of both web and mobile apps through its Real-Time Testing feature, which requires you to follow the steps below-given to function.
- Register for free and login to your LambdaTest account.
- A modal box will pop up. Click the Realtime Testing card.
It will guide you to the Real Time Browser Test Console.
- Enter the test URL, and select browser VERSION, OS, and RESOLUTION. Then click START.
It will launch a cloud-based machine based on your selected test configurations.
Automated End-to-End Testing Using LambdaTest
LambdaTest gives access to 3000+ desktop and mobile environments to execute automated end-to-end tests using Selenium, Cypress, Playwright, Appium, and Puppeteer frameworks. Here are the simple steps for automation testing:
- Follow the same login process as explained above.
- Choose the Automation tab on the left panel.
- To get started, either try out the Demo Project or Configure Test Suite.
- To run the test, select Configure Test Suite and choose your preferred automation testing framework.
- Now configure your tests and start testing.
Challenges With End-to-End Testing
End-to-end testing has several advantages but also some disadvantages as a method of software testing. End-to-end testing presents difficulties because:
The end-to-end testing approach has earned a reputation for flaky tests that fail unexpectedly. Frustratingly, this means that your test suite can pass one day, even though it’s broken, and then fail the next day for no reason.
Because end-to-end tests have so many moving parts, it’s hard to figure out what’s causing a problem. This inconsistency leads to lost productivity when diagnosing the root cause of flakiness since it’s nearly impossible to replicate failing scenarios. As a result, teams end up accepting flaky tests and ignoring potential issues.
Slow Test Execution
In addition to the flakiness issues mentioned above, end-to-end tests take too long to run. While it’s unfair to compare the speed of these tests to unit or functional tests, which are much faster and only test a portion of your application, slow tests hinder developer productivity and cause unnecessary frustration.
Slow test suites can hamper the ability of software development and testing teams to work efficiently. For instance, many teams nowadays rely on successful test runs in their continuous integration system before merging code modifications or deploying new features.
End-to-end tests are longer than other tests because they cover longer flows and have more steps and assertions. For example, when testing an e-commerce website, an end-to-end test might go through searching for a product, viewing its details page, adding it to a cart, and finalizing the order. These actions represent a wide range of functionality within the application, making the test extensive.
As your end-to-end test suite grows, it becomes harder and harder to add new tests without interfering with existing ones. Over time, minor changes to the application can bring down your entire test suite. That’s why you should plan your end-to-end tests with long-term maintenance in mind.
Gathering Actionable Items
You’ll notice the benefits of test automation once you have a few end-to-end tests working. Your team will have more time to focus on other high-value work, and you’ll likely notice a few spots to improve in the underlying application. While test automation can provide some peace of mind, your team still needs to address any potential issues that stem from its usage.
When an application's automated end-to-end tests are integrated into the development workflow, they can help teams more readily identify when changes break existing functionality. Not only do robust test suites help to alert a team when something violates, but they can also be used to verify new features are contributing to the application's overall success.
Automating end-to-end tests takes time and effort for any project. While there have been advances in testing tools, there’s still a non-trivial amount of work required to create an automated test suite. The key is to plan your testing strategy, prioritize resources and find time to get started.
Because it can be difficult to immediately demonstrate the usefulness of end-to-end testing at the start of a project, teams can abandon their efforts too quickly without anything to show for them.
End-to-End Testing Best Practices
End-to-end testing is the type of testing that mimics the experience of a real user using the application. Here are a few best practices to get the best out of end-to-end testing:
Test Repeated User Scenarios
You may be unable to cover every possible use case and path through the application. Avoid testing the edge cases and focus on the most common scenarios. Integration or low-level unit testing may better fit the exception cases.
Prioritize the Right Aspects
When testing an app, start by testing the features that will impact your business the most, whether it’s customer experience or ensuring a failure does not affect your revenue stream. It’s better to address those aspects that have a significant impact on your business first.
Make Testing Realistic
The way most people use a website is not by clicking a few buttons and moving on. They read, look at images, or pause between actions. End-to-end testing should mirror real-life interaction as much as possible.
End-to-end testing environments can be complex because they encompass the whole application. However, by resolving as many errors as possible before doing end-to-end testing, you can reduce the number of problems to investigate.
When coupled with API tests, end-to-end tests can help developers determine whether a front-end failure is caused by a functional error or an API call error.
Optimize Testing Environments
You can facilitate the testing process by creating an optimum test environment. This allows for minimal setup when it’s time to test and a fast way to clear data so your test environment is ready for the next test.
End-to-end testing is essential for assessing how a user will interact with your program. Evaluating the user experience from beginning to end provides more assurance regarding the quality of your application than simply testing if a button function or a model appears.
End-to-end testing implementation methods such as horizontal testing, vertical testing, and the distinction between manual and automatic testing were all covered.
Through this extensive end-to-end testing tutorial, we hope to answer every question you have regarding end-to-end testing.
You can also use LambdaTest's cloud platform to run your first end-to-end test.
Published at DZone with permission of Kavita Joshi. See the original article here.
Opinions expressed by DZone contributors are their own.