<?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: Stelios Gkiokas</title>
    <description>The latest articles on DEV Community by Stelios Gkiokas (@stelios_gkiokas).</description>
    <link>https://dev.to/stelios_gkiokas</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%2F3122143%2Fabc2007d-d2b8-4e0b-bc28-5bce6da28801.jpg</url>
      <title>DEV Community: Stelios Gkiokas</title>
      <link>https://dev.to/stelios_gkiokas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stelios_gkiokas"/>
    <language>en</language>
    <item>
      <title>Flaky Tests: Causes, Examples, and Best Practices</title>
      <dc:creator>Stelios Gkiokas</dc:creator>
      <pubDate>Wed, 21 May 2025 17:23:22 +0000</pubDate>
      <link>https://dev.to/agileactors/flaky-tests-causes-examples-and-best-practices-2fml</link>
      <guid>https://dev.to/agileactors/flaky-tests-causes-examples-and-best-practices-2fml</guid>
      <description>&lt;h2&gt;
  
  
  Why Flaky Tests Are Worse Than You Think
&lt;/h2&gt;

&lt;p&gt;Flaky tests aren’t just annoying. They’re destructive. They break trust in your CI pipeline, slow down engineering teams, and hide real bugs under the noise of random failures.&lt;/p&gt;

&lt;p&gt;The worst part? Developers start ignoring all test failures, assuming they’re “just flaky.” At that point, your test suite is worse than useless — it’s lying to you.&lt;/p&gt;

&lt;p&gt;This guide is about fixing flakiness at the root. Not band-aiding it. Not retrying endlessly. Actually understanding why it happens and how to prevent it — from local dev to cloud CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Causes Flaky Tests (And What to Do About It)
&lt;/h2&gt;

&lt;p&gt;Flakiness sneaks into every layer of testing, but it wears different disguises depending on what you’re testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI Testing
&lt;/h3&gt;

&lt;p&gt;When you test user interfaces, you’re testing against the most asynchronous, unpredictable layer of your stack.&lt;/p&gt;

&lt;p&gt;Imagine this: Your test navigates to a page and clicks “Submit” — but the button’s disabled for 200ms after load to allow animations. Sometimes the click happens too soon, sometimes not. Your test randomly fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Example: Stable Clicking&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import static org.junit.jupiter.api.Assertions.assertEquals;

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.junit.jupiter.api.Test;

public class FormTest {

    @Test
    public void submitButtonShouldBeClickable() {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("https://example.com/form");

            WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
            WebElement submitButton = wait.until(
                ExpectedConditions.elementToBeClickable(By.id("submit-button"))
            );

            submitButton.click();

            wait.until(ExpectedConditions.urlToBe("https://example.com/success"));
            assertEquals("https://example.com/success", driver.getCurrentUrl());
        } finally {
            driver.quit();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notice&lt;/strong&gt;: no fixed sleeps. Only event-based waits. That’s how you remove race conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Testing (REST and GraphQL)
&lt;/h3&gt;

&lt;p&gt;APIs are supposed to be deterministic — but when tests hit real servers, all bets are off.&lt;/p&gt;

&lt;p&gt;Network spikes, caching issues, or asynchronous database replication can cause tests to fail randomly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Example: Mocked REST API Test&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WireMockServer wireMockServer = new WireMockServer(8080);
wireMockServer.start();

WireMock.stubFor(post(urlEqualTo("/users"))
  .willReturn(aResponse()
    .withStatus(201)
    .withBody("{\"id\":\"123\", \"name\":\"Alice\"}")));

Response response = given()
  .baseUri("http://localhost:8080")
  .contentType("application/json")
  .body("{\"name\":\"Alice\"}")
  .post("/users");

response.then().statusCode(201);
assertEquals("Alice", response.jsonPath().getString("name"));

wireMockServer.stop();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, you control every byte of the server response. Zero external dependencies. Zero flakiness.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Performance Testing
&lt;/h3&gt;

&lt;p&gt;Performance is inherently noisy — but that doesn’t mean your tests have to be flaky.&lt;/p&gt;

&lt;p&gt;Imagine your load tests show 1s latency on Monday and 3s latency on Wednesday — but no code has changed. That’s not a flaky test — that’s a flaky environment.&lt;/p&gt;

&lt;p&gt;To fix it, performance tests must run in controlled conditions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Key Tip&lt;/strong&gt;: Always run tests multiple times and use median, 95th percentile — not averages. Averages lie when there’s noise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Testing
&lt;/h3&gt;

&lt;p&gt;Security tests like fuzzing or vulnerability scanning can become flaky if you don’t control randomness.&lt;/p&gt;

&lt;p&gt;If your fuzzing engine seeds randomly every run, you’ll get different results, making failures look random.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Fix random seeds in fuzzers&lt;/li&gt;
&lt;li&gt;Run against snapshots of systems&lt;/li&gt;
&lt;li&gt;Log all input payloads for reproducibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Chaos Engineering
&lt;/h3&gt;

&lt;p&gt;Chaos tests intentionally cause system failures. But without tight control, they make tests untrustworthy instead of resilient.&lt;/p&gt;

&lt;p&gt;The goal is &lt;strong&gt;targeted chaos&lt;/strong&gt;, not blind chaos.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Why Environments Matter More Than Your Test Code
&lt;/h2&gt;

&lt;p&gt;99% of articles about flaky tests focus only on “bad test code.”&lt;/p&gt;

&lt;p&gt;Reality: &lt;strong&gt;environment stability&lt;/strong&gt; is just as important.&lt;/p&gt;

&lt;p&gt;Tests that hit unstable environments are doomed from the start.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Cloud Computing Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use ephemeral test environments spun up per PR (e.g., with Terraform)&lt;/li&gt;
&lt;li&gt;Create immutable infrastructure — never “fix” a test env by hand&lt;/li&gt;
&lt;li&gt;Control resource auto-scaling and instance types for tests&lt;/li&gt;
&lt;li&gt;Snapshot entire DBs or services pre-test to ensure known states&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observability in Testing
&lt;/h3&gt;

&lt;p&gt;Good engineers log and monitor not just their app — but their tests too.&lt;/p&gt;

&lt;p&gt;✅ Track test start/end times&lt;br&gt;
✅ Monitor resource usage during tests&lt;br&gt;
✅ Correlate test failures with infrastructure anomalies&lt;/p&gt;

&lt;p&gt;Tools to Add Observability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grafana dashboards from test results&lt;/li&gt;
&lt;li&gt;Prometheus metrics from CI pipelines&lt;/li&gt;
&lt;li&gt;OpenTelemetry traces through tests&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Stable Testing Pyramid: Best Practice Design
&lt;/h2&gt;

&lt;p&gt;Below you can find a rough distribution of the tests that you have for your applications:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Industry Case Studies
&lt;/h2&gt;

&lt;p&gt;Here as 3 examples of some tech giants in order to showcase how flakiness is tackled:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Quick Pro-Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never Retry Blindly&lt;/strong&gt;: Retrying flaky tests without understanding the cause just masks real problems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Test Observability First&lt;/strong&gt;: Know exactly where your tests fail, not just that they failed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud is Your Friend (if used right)&lt;/strong&gt;: Use cloud ephemeral environments spun up per PR — and teardown after.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer Mocks for External Services Always&lt;/strong&gt;: You don’t control Google’s API. Or AWS failures. Mock them aggressively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize Test Stability as a Feature&lt;/strong&gt;: Test stability is not “extra work.” It’s a product quality feature.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts: Flaky Tests Are a Systemic Issue, Not a “Test Code” Issue
&lt;/h2&gt;

&lt;p&gt;Flaky tests point to flaky systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fragile environments&lt;/li&gt;
&lt;li&gt;Bad assumptions about timing&lt;/li&gt;
&lt;li&gt;Poor infrastructure control&lt;/li&gt;
&lt;li&gt;Missing observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fixing flaky tests makes your product better, your systems more resilient, and your team much faster.&lt;/p&gt;

&lt;p&gt;If you’re passionate about software testing, infrastructure, and creating high-quality solutions in a dynamic, knowledge-sharing environment, we invite you to explore our &lt;a href="https://apply.workable.com/agileactors/" rel="noopener noreferrer"&gt;job opportunities&lt;/a&gt; at Agile Actors. Here, your personal growth is a key part of our collective development, especially as we tackle the ever-evolving challenges in software engineering and testing. Join us and be a part of our journey to shape the future of testing and infrastructure excellence.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
