10 Reasons for Flaky Tests
Tags: testing, test, webdev, devops
Published: 2024-05-29 17:41:28


Testing is one of the important aspects of software development. It helps to ensure that your codes are high quality and reliable. However, we sometimes run into issues, one of which is flaky tests. They can be very frustrating, which is why knowing why they can occur is a big step to solving them. In this article, we'll look at the ten reasons for flaky tests and provide some solutions to get your testing back on track.

## What are Flaky Tests
[Flaky tests](https://semaphoreci.com/community/tutorials/how-to-deal-with-and-eliminate-flaky-tests) is a test that both passes and fails at the same time periodically without any code change and by code change, we mean no change in the code that run the tests nor change in the code of the application in the same environment.

Flaky tests can be problematic because they reduce the reliability and effectiveness of automated testing. Let's say, for instance, that you're testing out a feature to be included in software that calculates the total price of items for a shopping cart. You write an automated test that adds the items to the cart,  checks them, and calculates the total price. However, the test fails. Sometimes, this test runs, and the total price is calculated correctly, but other times, it fails and gives an incorrect total price. 
![a frustrated developer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awopcp2j55bzibyg1fg3.png)
This behavior is what we call flaky. It causes an uncertainty about the result. The fact that it passes sometimes and fails the next time doesn't bring about this uncertainty as we are not sure if we are breaking something or just some flaky behavior. 

This brings us to why a flaky test can occur during testing.

## Reasons for Flaky Tests
In this section, we'll run through some reasons why flaky tests occur. Note that they are not limited to these but are some of the common ones we encounter 

###  Poor Tests Data
When the data used to test is poor, it can lead to a flaky test. When we talk about data being poor, we mean it can be old, incomplete, incorrect, or even outdated. And using it can lead to tests periodically failing or passing even when we test under the same conditions. 

To reduce the chances of encountering tests due to poor data, we can employ the following strategies:
  
- Use Realistic Test Data
- ValidateTest Data
- Refresh Test Data Regularly
- Monitor test data quality

### Inconsistent Test Environment
A test environment that varies in hardware, software, and configuration can lead to inconsistent test results. 

For instance, a test can pass on a developer's machine since it has all the configurations needed but fail in a [CI/CD](https://semaphoreci.com/cicd) environment due to the environment possessing a different version of the configurations or settings from the local machine. This incompatibility often leads to flakiness.

To minimize the chances of encountering a flaky test due to an inconsistent test environment, You can employ the following strategies:

- Virtualization
- Containerization
- Cloud-based testing
- Automated environment validation

### Poor Test Designs
When it comes to the reliability and consistency of tests, Test designs play a crucial role. A poorly designed test combined with the absence of a sufficient setup, teardown procedure, and inadequate error handling can lead to a flaky test.

To address issues due to poor test designs, we must have the following:

- Proper setup and teardown
- Robust error handling
- Specific assertions 

### Resource Constraints
Resource constraints refer to the limitations in resources that are available for testing. These limitations can be related to hardware, software, or infrastructure and can impact the execution of tests, leading to flakiness.

For instance, a test that has a specific memory or  CPU limit is bound to be flaky if the available memory fails to meet the required memory for execution.

To prevent issues due to environmental constraints, consider the following:

- Upgrading Hardware
- Optimizing Test Scripts
- Distributing Tests Across Multiple Machines
- Using Cloud Resources
- Implementing Resource Monitoring

### Timing Issues
Timing issues can be encountered when tests depend on certain timing conditions, such as network latency or UI elements. These conditions are sensitive and can cause tests to pass or fail.

To address timing issues, we can implement [synchronization techniques](https://medium.com/@gokulganapathy9500/what-is-synchronization-6f0cf3386f26) like explicit wait and timeouts. These techniques ensure that the test waits for the necessary conditions before proceeding. Doing this will reduce the likelihood of flakiness due to timing issues.

### External Factors
When we talk about external actors, we refer to issues ranging from network connectivity to outages in third-party services. When a test depends on an external service, they are prone to failure, and if such dependencies become unavailable for one reason or another.

To minimize interference from external factors and improve the reliability of tests, consider the following solutions:

- Use Isolated Test Environments
- Implement Retry Mechanisms
- Monitor External Factors Before Test Execution
- Mock External Services

### Test Dependencies
Test dependencies refer to a situation where one test relies on another test's outcome. This usually occurs when tests share resources, and the order in which the tests are executed influences their outcomes.

For instance, if a test modifies a shared resource and another test relies on the resource's original state, the dependent test may fail if it runs before the modifying test has finished.

To reduce the impact of test dependencies, we can:
- Ensure test isolation
- Clear test dependency
- Mock external dependency

### Using Hard-Coded Test Data
Hard-coded test data refers to embedding specific values into test values instead of generating dynamic or dummy data. Even an automation engineer will tell you this is a bad practice that can lead to flaky tests. Using hardcoded test data can lead to issues like difficulty in debugging, data duplication, obsolete data, etc.

A better way is to use dynamic test data, mock external dependencies, or parameterize tests.

### Poorly Written Tests
Poorly written tests are those that are not well structured. They do not define what they are testing, and sometimes, they are overly complex, which makes them difficult to understand. 

One of the numerous ways to cause flaky tests is having a test written poorly. To address the issue of poorly written tests, here are some solutions:

- Refactor and Simplify Tests
- Ensure Proper Cleanup
- Use descriptive test names
- Avoid redundant tests
- Use mocking and stubbing

### Lack of Proper Framework
A proper framework establishes a structured environment for writing, performing, and maintaining tests. This ensures that tests are reliable, efficient, and easy to understand. Not having a proper framework can make a test fail. This is because they lack the necessary tools, libraries, and configurations to run consistently. Having a proper framework includes the process of running the tests, what is needed, and also how to do it.

To address improper framework issues, we can:

- Use Robust and Reliable Test Automation Frameworks and Tools
- Properly Manage Test Environments and Configurations
- Regularly Maintain and Update Tests

## Conclusion
In this article, we've identified ten key reasons contributing to flaky tests, each with its own implications. Understanding these reasons is crucial for addressing flaky tests effectively and ensuring the reliability and accuracy of tests.