CINXE.COM
Catching Flaky Tests Before It's Too Late - Codecov
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"> <head profile="http://gmpg.org/xfn/11"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="google-site-verification" content="vJJzG_HitBMzWgMMYHRCAa6Y2voMwC9OTHuxgHL2358" /> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" /> <title>Catching Flaky Tests Before It's Too Late - Codecov</title> <!-- WP HEAD --> <meta name='robots' content='index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1' /> <style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style> <!-- This site is optimized with the Yoast SEO plugin v23.6 - https://yoast.com/wordpress/plugins/seo/ --> <link rel="canonical" href="https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/" /> <meta property="og:locale" content="en_US" /> <meta property="og:type" content="article" /> <meta property="og:title" content="Catching Flaky Tests Before It's Too Late - Codecov" /> <meta property="og:description" content="This is a guest post from Artem Zakharchenko, creator of MSWJS, an API mocking library for Javascript. He also writes about testing for EpicWeb and on his personal blog. Test ..." /> <meta property="og:url" content="https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/" /> <meta property="og:site_name" content="Codecov" /> <meta property="article:publisher" content="https://www.facebook.com/Codecov-106795907636673/" /> <meta property="article:published_time" content="2024-12-06T01:15:11+00:00" /> <meta property="article:modified_time" content="2024-12-06T18:14:33+00:00" /> <meta property="og:image" content="https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png" /> <meta property="og:image:width" content="2048" /> <meta property="og:image:height" content="1162" /> <meta property="og:image:type" content="image/png" /> <meta name="author" content="Artem Zakharchenko" /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:creator" content="@codecov" /> <meta name="twitter:site" content="@codecov" /> <meta name="twitter:label1" content="Written by" /> <meta name="twitter:data1" content="Artem Zakharchenko" /> <meta name="twitter:label2" content="Est. reading time" /> <meta name="twitter:data2" content="7 minutes" /> <script type="application/ld+json" class="yoast-schema-graph">{"@context":"https://schema.org","@graph":[{"@type":"Article","@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#article","isPartOf":{"@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/"},"author":{"name":"Artem Zakharchenko","@id":"https://about.codecov.io/#/schema/person/4791f6e49e5e21f7ef536126eb9e83f0"},"headline":"Catching Flaky Tests Before It’s Too Late","datePublished":"2024-12-06T01:15:11+00:00","dateModified":"2024-12-06T18:14:33+00:00","mainEntityOfPage":{"@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/"},"wordCount":1294,"commentCount":0,"publisher":{"@id":"https://about.codecov.io/#organization"},"image":{"@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#primaryimage"},"thumbnailUrl":"https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#respond"]}]},{"@type":"WebPage","@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/","url":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/","name":"Catching Flaky Tests Before It's Too Late - Codecov","isPartOf":{"@id":"https://about.codecov.io/#website"},"primaryImageOfPage":{"@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#primaryimage"},"image":{"@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#primaryimage"},"thumbnailUrl":"https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png","datePublished":"2024-12-06T01:15:11+00:00","dateModified":"2024-12-06T18:14:33+00:00","breadcrumb":{"@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#primaryimage","url":"https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png","contentUrl":"https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png","width":2048,"height":1162,"caption":"Screenshot of Codedov installation prompt on GitHub showing individual and organizational options"},{"@type":"BreadcrumbList","@id":"https://about.codecov.io/blog/catching-flaky-tests-before-its-too-late/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://about.codecov.io/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://about.codecov.io/blog/"},{"@type":"ListItem","position":3,"name":"Catching Flaky Tests Before It’s Too Late"}]},{"@type":"WebSite","@id":"https://about.codecov.io/#website","url":"https://about.codecov.io/","name":"Codecov","description":"Code coverage done right.","publisher":{"@id":"https://about.codecov.io/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://about.codecov.io/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https://about.codecov.io/#organization","name":"Codecov","url":"https://about.codecov.io/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https://about.codecov.io/#/schema/logo/image/","url":"https://about.codecov.io/wp-content/uploads/2020/09/codecov.svg","contentUrl":"https://about.codecov.io/wp-content/uploads/2020/09/codecov.svg","width":1,"height":1,"caption":"Codecov"},"image":{"@id":"https://about.codecov.io/#/schema/logo/image/"},"sameAs":["https://www.facebook.com/Codecov-106795907636673/","https://x.com/codecov","https://www.instagram.com/codecov/","https://www.linkedin.com/company/codecov/","https://www.youtube.com/channel/UCj-fJuvXv-m05HkSNn0OS9g/featured"]},{"@type":"Person","@id":"https://about.codecov.io/#/schema/person/4791f6e49e5e21f7ef536126eb9e83f0","name":"Artem Zakharchenko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https://about.codecov.io/#/schema/person/image/","url":"https://secure.gravatar.com/avatar/34f7c64bde1d2344573673f8455ecde4?s=96&r=g","contentUrl":"https://secure.gravatar.com/avatar/34f7c64bde1d2344573673f8455ecde4?s=96&r=g","caption":"Artem Zakharchenko"},"sameAs":["https://kettanaito.com/blog"]}]}</script> <!-- / Yoast SEO plugin. --> <link rel='stylesheet' id='wp-block-library-css' href='https://about.codecov.io/wp-includes/css/dist/block-library/style.min.css?ver=6.7.2' type='text/css' media='all' /> <style id='classic-theme-styles-inline-css' type='text/css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <style id='global-styles-inline-css' type='text/css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} </style> <link rel='stylesheet' id='likebtn_style-css' href='https://about.codecov.io/wp-content/plugins/likebtn-like-button/public/css/style.css?ver=6.7.2' type='text/css' media='all' /> <link rel='stylesheet' id='wp-pagenavi-css' href='https://about.codecov.io/wp-content/plugins/wp-pagenavi/pagenavi-css.css?ver=2.70' type='text/css' media='all' /> <link rel='stylesheet' id='styles-css' href='https://about.codecov.io/wp-content/themes/codecov/style.css?ver=1742918081' type='text/css' media='all' /> <script type="text/javascript" id="likebtn_frontend-js-extra"> /* <![CDATA[ */ var likebtn_eh_data = {"ajaxurl":"https:\/\/about.codecov.io\/wp-admin\/admin-ajax.php","security":"e91941f658"}; /* ]]> */ </script> <script type="text/javascript" src="https://about.codecov.io/wp-content/plugins/likebtn-like-button/public/js/frontend.js?ver=6.7.2" id="likebtn_frontend-js"></script> <script type="text/javascript" defer data-domain='about.codecov.io' data-api='https://about.codecov.io/wp-json/fb8d43/v1/fef8/87d0ca76' data-cfasync='false' src="//about.codecov.io/wp-content/uploads/0ef4f2a49f/92e3cfb7.js?ver=1719335001" id="plausible"></script> <script type="text/javascript" id="plausible-analytics-js-after"> /* <![CDATA[ */ window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) } /* ]]> */ </script> <script type="text/javascript" src="https://about.codecov.io/wp-content/plugins/jquery-updater/js/jquery-3.7.1.min.js?ver=3.7.1" id="jquery-core-js"></script> <script type="text/javascript" src="https://about.codecov.io/wp-content/plugins/jquery-updater/js/jquery-migrate-3.5.2.min.js?ver=3.5.2" id="jquery-migrate-js"></script> <link rel="https://api.w.org/" href="https://about.codecov.io/wp-json/" /><link rel="alternate" title="JSON" type="application/json" href="https://about.codecov.io/wp-json/wp/v2/posts/11179" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://about.codecov.io/xmlrpc.php?rsd" /> <link rel='shortlink' href='https://about.codecov.io/?p=11179' /> <link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://about.codecov.io/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F" /> <link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://about.codecov.io/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F&format=xml" /> <meta name='plausible-analytics-version' content='2.1.4' /> <!-- FAVICON INFO --> <link rel="apple-touch-icon" sizes="57x57" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-57x57.png"> <link rel="apple-touch-icon" sizes="60x60" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-60x60.png"> <link rel="apple-touch-icon" sizes="72x72" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-72x72.png"> <link rel="apple-touch-icon" sizes="76x76" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-76x76.png"> <link rel="apple-touch-icon" sizes="114x114" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-114x114.png"> <link rel="apple-touch-icon" sizes="120x120" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-120x120.png"> <link rel="apple-touch-icon" sizes="144x144" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-144x144.png"> <link rel="apple-touch-icon" sizes="152x152" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-152x152.png"> <link rel="apple-touch-icon" sizes="180x180" href="/wp-content/themes/codecov/assets/brand/icons/favicons/apple-icon-180x180.png"> <link rel="icon" type="image/png" sizes="192x192" href="/wp-content/themes/codecov/assets/brand/icons/favicons/android-icon-192x192.png"> <link rel="icon" type="image/png" sizes="32x32" href="/wp-content/themes/codecov/assets/brand/icons/favicons/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="96x96" href="/wp-content/themes/codecov/assets/brand/icons/favicons/favicon-96x96.png"> <link rel="icon" type="image/png" sizes="16x16" href="/wp-content/themes/codecov/assets/brand/icons/favicons/favicon-16x16.png"> <!-- <link rel="manifest" href="/wp-content/themes/codecov/assets/brand/icons/favicons/manifest.json">--> <meta name="msapplication-TileColor" content="#ff0077"> <meta name="msapplication-TileImage" content="/wp-content/themes/codecov/assets/brand/icons/favicons/ms-icon-144x144.png"> <meta name="theme-color" content="#ff0077"> <!-- Facebook Verification --> <meta name="facebook-domain-verification" content="d8454acosfhz6aizm750a0qtfm99pn" /> <!-- COMMENT SCRIPTS --> <!-- Google Tag Manager --> <script> (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-KGH2DSG'); window.dataLayer.push({ "codecov": { "page": { "type": "Blog Post" } } }); </script> <!-- End Google Tag Manager --> </head> <body class="post-template-default single single-post postid-11179 single-format-standard fl-builder-2-8-4-1"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KGH2DSG" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --><div id="mega-header"><div class="hero-texture"><div class="texture-left"></div><div class="texture-right"></div></div><header id="header"> <div class="container"> <div class="row"> <div class="col-12"> <div class="header__content"> <!-- LOGO --> <a class="header__logo" href="https://about.codecov.io"> <img src="/wp-content/themes/codecov/assets/brand/sentry-cobranding/logos/codecov-by-sentry-logo.svg" title="Code Coverage by Codecov" alt="Code Coverage by Codecov" /> </a> <!-- MAIN NAVIGATION --> <nav class="header__main-navigation"> <ul> <li> <a href="/product/features/">Product</a> <!-- PRODUCT MENU --> <div class="menu menu--product"> <div class="row"> <div class="col-md-12"> <ul> <li><a href="/product/features/">Features</a></li> <li><a href="/product/integrations/">Integrations</a></li> <li><a href="/product/documentation/">Docs</a></li> <li><a href="/product/api/">API</a></li> <li><a href="/product/status/">Status</a></li> </ul> </div> </div> <!--<div class="row callout"> <div class="col"> <p><a href="https://about.codecov.io/blog/introducing-codecovs-new-uploader/"><span class="badge badge-primary">Product Update</span>Introducing Codecov's New Uploader<i class="fa fa-arrow-right"></i></a></p> </div> </div>--> </div> </li> <li> <a href="/product/documentation/" target="_BLANK">Docs</a> </li> <li> <a href="/customers/">Customers</a> </li> <li> <a href="/resources/">Blog</a> </li> <li><a href="/pricing/">Pricing</a></li> <li> <a href="/contact/">Help</a> <!-- COMPANY --> <div class="menu menu--company"> <div class="row"> <div class="col-md-12"> <ul> <li><a href="https://codecovpro.zendesk.com/">Pro Support</a></li> <li><a href="https://codecoventerprise.zendesk.com/">Enterprise Support</a></li> <li><a href="https://community.codecov.com/">Community</a></li> <li><a href="/contact/">Contact Us</a></li> </ul> </div> </div> <!--<div class="row callout"> <div class="col"> <p><a href="https://angel.co/job-collections/52-best-startup-companies-to-watch-out-for-in-2020" target="_blank" rel="noopener noreferrer"><span class="badge badge-primary">Angel List</span>Company to watch out for in 2020 <i class="fa fa-arrow-right"></i></a></p> </div> </div>--> </div> </li> </ul> </nav> <!-- LOGIN NAVIGATION --> <nav class="header__login-navigation"> <ul> <li class="d-inline-inline-block d-lg-none"> <div class="effect-02"> <div class="menu-icon js-menu_toggle"> <span class="menu-icon_box"> <span class="menu-icon_line menu-icon_line--1"></span> <span class="menu-icon_line menu-icon_line--2"></span> <span class="menu-icon_line menu-icon_line--3"></span> </span> </div> </div> </li> <li class="d-none d-lg-inline-block"> <a class="header--login" href="javascript:;">Login</a> <div class="menu menu--login"> <div class="row"> <div class="col"> <ul> <li><a href="https://codecov.io/login/gh"><img src="/wp-content/themes/codecov/assets/logos/ci/github/github-icon.svg" /> GitHub</a></li> <li><a href="https://codecov.io/login/gl"><img src="/wp-content/themes/codecov/assets/logos/ci/gitlab/gitlab-icon.svg" /> GitLab</a></li> <li><a href="https://codecov.io/login/bb"><img src="/wp-content/themes/codecov/assets/logos/ci/bitbucket/bitbucket-icon.svg" /> Bitbucket</a></li> <li><a href="https://api.codecov.io/login/sentry?to=https%3A%2F%2Fapp.codecov.io%2Fsentry"><img src="/wp-content/themes/codecov/assets/logos/sentry-logo.svg" /> Sentry</a></li> </ul> </div> </div> </div> </li> <li class="d-none d-lg-inline-block"> <!-- <a href="/sign-up/" class="btn btn-md btn-dark-blue btn-signup">Sign Up</a>--> <a href="/demo/" class="btn btn-md btn-dark-blue btn-signup plausible-event-name=Nav+Click+CTA">Get Demo</a> </li> </ul> </nav> <!-- MOBILE NAVIGATION --> <nav class="header__mobile-navigation"> <ul> <li> <a href="/product/" class="has-menu">Product</a> <!-- PRODUCT MENU --> <div class="menu menu--product"> <div class="row"> <div class="col"> <ul> <li><a href="/product/">Overview</a></li> <li><a href="/product/features/">Features</a></li> <li><a href="/product/integrations/">Integrations</a></li> <li><a href="/product/getting-started/" class="d-none">Getting Started</a></li> <li><a href="/product/documentation/">Documentation</a></li> <li><a href="/product/api/">API</a></li> <li><a href="/product/status/">Status</a></li> </ul> </div> </div> </div> </li> <li> <a href="/customers/">Customers</a> </li> <li> <a href="/resources/">Blog</a> </li> <li><a href="https://docs.codecov.io" target="_blank" rel="noopener noreferrer">Docs</a></li> <li><a href="/pricing/">Pricing</a></li> <li><a href="/contact/">Contact</a></li> <li><a href="/sign-up/">Login</a></li> </ul> </nav> </div> </div> </div> </div> </header><section id="hero"><div class="container"><div class="row d-flex"> <div class="col-12"> <div class="title-content"> <h6>Blog Post</h6><h1>Catching Flaky Tests Before It’s Too Late</h1><p><i class="fal fa-calendar mr-1"></i> December 5, 2024 <i class="fal fa-user ml-3 mr-1"></i> Artem Zakharchenko</p> </div> </div> </div> </div></section></div><section id="scrollbar"> <div class="container"> <div class="row d-flex justify-content-between align-items-center"> <!-- LOGO --> <a class="logo" href="https://about.codecov.io"> <img src="/wp-content/themes/codecov/assets/brand/sentry-cobranding/logos/codecov-by-sentry-logo.svg" title="Codecov" alt="Codecov" /> </a> <a class="d-flex d-lg-none btn btn-md btn-primary" href="https://codecov.io/login/">Get Started For Free</a> <ul class="list-inline d-none d-lg-block"> <!--<li class="mr-2"> <h6 class="my-0">Get Started With</h6> </li> <li> <a class="btn btn-sm btn-white btn-github plausible-event-name=Scrollbar+Click+Github" href="https://codecov.io/login/gh"><img src="/wp-content/themes/codecov/assets/logos/ci/github/github-icon.svg"> GitHub</a> </li> <li> <a class="btn btn-sm btn-white btn-gitlab plausible-event-name=Scrollbar+Click+Gitlab" href="https://codecov.io/login/gl"><img src="/wp-content/themes/codecov/assets/logos/ci/gitlab/gitlab-icon.svg"> GitLab</a> </li> <li> <a class="btn btn-sm btn-white btn-bitbucket plausible-event-name=Scrollbar+Click+Bitbucket" href="https://codecov.io/login/bb"><img src="/wp-content/themes/codecov/assets/logos/ci/bitbucket/bitbucket-icon.svg"> Bitbucket</a> </li> <li> <a class="btn btn-sm btn-white btn-sentry plausible-event-name=Scrollbar+Click+Sentry" href="https://api.codecov.io/login/sentry?to=https%3A%2F%2Fapp.codecov.io%2Fsentry"><img src="/wp-content/themes/codecov/assets/logos/sentry-logo.svg" /> Sentry</a> </li> --> <li> <a class="btn btn-sm btn-white plausible-event-name=Scrollbar+Click+Login" href="https://codecov.io/login/">Login</a> </li> <li> <a class="btn btn-sm btn-secondary plausible-event-name=Scrollbar+Click+Signup" href="https://about.codecov.io/codecov-free-trial">Try Codecov for Free</a> </li> </ul> </div> </div> </section> <main id="main"> <div class="container"> <div class="row d-flex justify-content-center"> <div class="col-12 col-md-1"> <div class="share-buttons d-flex-col"><a class="share-button share-button--twitter" href="https://twitter.com/intent/tweet?text=Catching%20Flaky%20Tests%20Before%20It’s%20Too%20Late&url=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F&via=codecov" target="_blank" rel="noopener noreferrer"><i class="fa fa-twitter"></i></a><a class="share-button share-button--linkedin" href="https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F&title=Catching%20Flaky%20Tests%20Before%20It’s%20Too%20Late" target="_blank" rel="noopener noreferrer"><i class="fa fa-linkedin"></i></a><a class="share-button share-button--xing" href="https://www.xing.com/spi/shares/new?url=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F" target="_blank" rel="noopener noreferrer"><i class="fa fa-xing"></i></a><a class="share-button share-button--hackernews" href="https://news.ycombinator.com/submitlink?u=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F&t=Catching%20Flaky%20Tests%20Before%20It’s%20Too%20Late" target="_blank" rel="noopener noreferrer"><i class="fa fa-y-combinator"></i></a><a class="share-button share-button--facebook" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F" target="_blank" rel="noopener noreferrer"><i class="fa fa-facebook"></i></a><a class="share-button share-button--email" href="mailto:?subject=Catching%20Flaky%20Tests%20Before%20It’s%20Too%20Late&body=https%3A%2F%2Fabout.codecov.io%2Fblog%2Fcatching-flaky-tests-before-its-too-late%2F"target="_blank" rel="noopener noreferrer"><i class="fa fa-envelope"></i></a><div class="share-buttons__title">Share</div></div> </div> <div class="col-md-8"> <p>This is a guest post from Artem Zakharchenko, creator of <a href="https://mswjs.io/">MSWJS</a>, an API mocking library for Javascript. He also writes about testing for <a href="https://www.epicweb.dev/contributors/artem-zakharchenko">EpicWeb</a> and on his <a href="https://kettanaito.com/blog">personal blog</a>.</p> <hr /> <p>Test flakiness is a big issue. Not only can it be a colossal time investment to detect and fix, but it hurts perhaps the biggest value you get from your tests—their trustworthiness. A test you cannot trust is a useless test. Time spent maintaining a useless test is time wasted; time that could have been spent building.</p> <p>I’ve already shared with you a <a href="https://www.epicweb.dev/be-smart-about-flaky-tests">practical guide on addressing flaky tests</a>, but today I’d like to talk about what it all starts from. <strong>Detecting flakiness.</strong></p> <h2>The root cause of flaky tests</h2> <p>One thing I learned over the years of testing is that flakiness can hide its roots in every layer of your system. From the way you write the test to the test setup and the tools you’re using. Even in the hardware that runs all of that. And the more layers your test involves, the easier it is for flakiness to slip through.</p> <p>It’s not a coincidence that end-to-end tests are notoriously known to be flaky. There are a lot of things at play between the two ends. Add to that a generally higher cost of maintenance, and you’ve got yourself a problem nobody on the team wants to deal with.</p> <p>The worst thing of all is that the sporadic nature of flakiness makes it compellingly easy to brush off an occasionally failed test. When so many layers are involved, who knows, perhaps it was a hiccup somewhere down the line. Just hit the “Rerun” button, see the test passing, and move on with your day.</p> <p>Sadly, that is how most teams approach flakiness at its early stage. Ignore it once, then twice, and, suddenly, you are gambling on the CI results of your product, pulling those reruns just to see it turn green.</p> <p>I’ve talked with teams that have given up on the whole idea of E2E testing because of how unreliable their test suites eventually became.</p> <p>That’s now how automated tests are supposed to work.</p> <h2>Addressing flaky tests instead of ignoring them</h2> <p>In larger teams, flakiness can easily go unnoticed. <em>You</em> might not be the one experiencing the flaky test to begin with.<em> You</em> might not need to constantly rerun the tests. Your team members who <em>are</em> being affected by flakiness might assume it’s just “the way it is”. But flakiness will eventually affect everyone.</p> <p>It is rather nasty to find yourself in a situation when an important pull request is stalled until you win the rerun game. I’ve been there. That’s why I put a ton of effort into keeping my builds green at all times, eradicating flakiness as soon as it surfaces.</p> <p>It is all the more useful to have tools by your side to help you detect and track flaky tests across your product.</p> <p>Recently, <a href="https://about.codecov.io/blog/find-failing-and-flaky-tests-with-codecov-test-analytics/">Codecov announced Test Analytics</a> and I wanted to try it straight away. And the best way to try is to reproduce one of the common mistakes that leads to flakiness and see how it would help me catch and fix it.</p> <h2>Testing flaky test detection</h2> <p>Here I’ve got a basic in-browser test using Vitest Browser Mode:</p> <pre class="hljs javascript"><span style="font-weight: 400;"><code>import { render } from 'vitest-browser-react' import { screen } from '@testing-library/react' import { worker } from '../src/mocks/browser.js' import App from '../src/App.jsx' beforeAll(() => worker.start()) afterAll(() => worker.stop()) function sleep(duration: number) { return new Promise((resolve) => { setTimeout(resolve, duration) }) } it('renders the list of posts', async () => { render(<App />) await sleep(250) const posts = screen.getAllByRole('listitem') expect(posts).toEqual([ expect.toHaveTextContent('First post'), expect.toHaveTextContent('Second post'), ]) }) </code></span></pre> <p>This one concerns itself with testing the <code><App /></code> component that renders a list of user’s posts. Fairly simple. For those with a sharp eye, you’ve likely already spotted the problem with this test, but let’s imagine I didn’t. I wrote it, ran it, saw it successful, got the changes approved, and now it runs on <code>main</code> for everyone in my team.</p> <p>Let’s see how the experience will look like for me (and my teammates) if I’ve got test analytics set up to track flaky tests.</p> <h2>Getting started with Codecov’s Test Analytics</h2> <p><a href="https://docs.codecov.com/docs/test-analytics">Test Analytics</a> is available as part of Codecov. The flaky test detection features I’m showing here are freely available for any public repo, or with pro and enterprise plans for private repos. You can integrate it in your project in just three steps.</p> <h3>Step 1: Install the Codecov app in GitHub</h3> <p>For starters, make sure you <a href="https://github.com/apps/codecov/installations/select_target">install the Codecov app on GitHub</a> and authorized for the repositories you want to add Test Analytics to.</p> <p><img fetchpriority="high" decoding="async" class="alignnone wp-image-11212 size-full" src="https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png" alt="Screenshot of Codedov installation prompt on GitHub showing individual and organizational options" width="2048" height="1162" srcset="https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app.png 2048w, https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app-300x170.png 300w, https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app-1024x581.png 1024w, https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app-768x436.png 768w, https://about.codecov.io/wp-content/uploads/2024/12/github-codecov-app-1536x872.png 1536w" sizes="(max-width: 2048px) 100vw, 2048px" /></p> <h3>Step 2: Configure Vitest to write the test report in JUnit format</h3> <p>Test Analytics works by parsing the results of your test run in JUnit format (don’t worry, you don’t have to actually use JUnit!). I use <a href="https://vitest.dev/">Vitest</a> in my project, and luckily it supports outputting the test report in that format.</p> <p>Provide <code>junit</code> as a test reporter to Vitest in <code>vitest.config.ts</code>:</p> <pre class="hljs javascript"><span style="font-weight: 400;"><code>// vitest.config.ts import { defineConfig } from 'vitest/config' export default defineConfig({ test: { reporters: ['default', 'junit'], outputFile: './test-report.junit.xml', }, }) </code></span></pre> <p>I’ve also added the default reporter so I can still see the test output in my terminal like I’m used to.</p> <p>And yes, Vitest supports different reporters and code coverage in the Browser Mode too.</p> <h3>Step 3: Upload test reports to Codecov</h3> <p>The only thing left to do is to run automated tests on CI and upload the generated report to Codecov. I will use GitHub Actions for that.</p> <pre class="hljs bash"><span style="font-weight: 400;"><code>name: ci on: push: branches: [main] pull_request: workflow_dispatch: jobs: test: runs-on: ubuntu-latest steps: - name: Checkout use: actions/checkout@v4 - name: Install dependencies run: npm install - name: Install browsers run: npx playwright install chromium - name: Run tests run: vitest - name: Upload test results # Always upload the test results because # we need to analyze failed test runs! if: ${{ !cancelled() }} use: codecov/test-results-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} </code></span></pre> <p><strong>Learn how to create the `CODECOV_TOKEN` <a href="https://docs.codecov.com/docs/codecov-tokens">here</a>.</strong></p> <p>Notice that the upload action is marked to run always <code>(`${{ !cancelled() }}`)</code> so we could analyze the failed test runs as well.</p> <h3>Reading the test analytics by Codecov</h3> <p>Once the setup is done, you will start getting reports in your pull requests highlighting overall test results and also any detected flakiness.</p> <p>Once someone on my team encounters the flakiness coming from the test I added, they will see an immediate report from Codecov right under the pull request:</p> <p><img decoding="async" class="alignnone wp-image-11213 size-full" src="https://about.codecov.io/wp-content/uploads/2024/12/github-comment-example-scaled.jpg" alt="Screenshot of a Codecov pull request comment showing failed and flaky tests" width="2048" height="1379" srcset="https://about.codecov.io/wp-content/uploads/2024/12/github-comment-example-scaled.jpg 2048w, https://about.codecov.io/wp-content/uploads/2024/12/github-comment-example-300x202.jpg 300w, https://about.codecov.io/wp-content/uploads/2024/12/github-comment-example-1024x689.jpg 1024w, https://about.codecov.io/wp-content/uploads/2024/12/github-comment-example-768x517.jpg 768w, https://about.codecov.io/wp-content/uploads/2024/12/github-comment-example-1536x1034.jpg 1536w" sizes="(max-width: 2048px) 100vw, 2048px" /></p> <p>An even more detailed report is available on <a href="https://app.codecov.io/">Codecov</a>. Once you’ve logged into Codecov, you can open the repository and navigate to the “Tests” tab. This tab is where you will find the Test Analytics Dashboard.</p> <p>Here’s how the test analytics report looks for the <code>main</code> branch:</p> <p><img decoding="async" class="alignnone wp-image-11214 size-full" src="https://about.codecov.io/wp-content/uploads/2024/12/codecov-dashboard-example-scaled.jpg" alt="A screenshot of a Codecov test analytics report showing test suite statistics like test run time, failure rate, flake rate, commits failed and last run" width="2048" height="872" srcset="https://about.codecov.io/wp-content/uploads/2024/12/codecov-dashboard-example-scaled.jpg 2048w, https://about.codecov.io/wp-content/uploads/2024/12/codecov-dashboard-example-300x128.jpg 300w, https://about.codecov.io/wp-content/uploads/2024/12/codecov-dashboard-example-1024x436.jpg 1024w, https://about.codecov.io/wp-content/uploads/2024/12/codecov-dashboard-example-768x327.jpg 768w, https://about.codecov.io/wp-content/uploads/2024/12/codecov-dashboard-example-1536x654.jpg 1536w" sizes="(max-width: 2048px) 100vw, 2048px" /></p> <p>I can see straight away that the test I introduced has been flaky on <code>main</code> (“renders the list of posts”). That won’t do!</p> <p>There’s also a lot of other metrics on display here, the most useful criteria for me being:</p> <p><strong>Flaky tests</strong>, the list of unreliable tests I have;</p> <p><strong>Slowest tests</strong>, the list of tests that take most time to run;</p> <p><strong>Average flake rate</strong>, to help me monitor my efforts as I go and fix flaky tests across the entire project.</p> <p>With a way to track that problematic test, it’s time for me to fix it for good.</p> <h2>Fixing flaky tests using insights from Codecov</h2> <p>Normally, I would start by removing the flaky test from the test suite entirely. But when I open the test I can see the root cause right away:</p> <pre class="hljs javascript"><span style="font-weight: 400;"><code>await sleep(250) // ❌ </code></span></pre> <p>Using <code>sleep</code> in a test is a terrible idea. You are almost never waiting for a certain amount of time to pass, but rather you are waiting for a certain state to change.</p> <p>Since I know the root cause, I’m going to propose a fix straight away. In the <code><App /></code> test case, the state I’m waiting for is when the user posts a response and the list of posts renders in the UI. I need to rewrite the test to reflect that:</p> <pre class="hljs javascript"><span style="font-weight: 400;"><code>-const posts = screen.getAllByRole('listitem') -await sleep(250) +const posts = await screen.findAllByRole('listitem') </code></span></pre> <p>By swapping the <code>getAllByRole</code> query with the <code>findAllByRole</code> I am introducing a promise that will resolve once the list items are present on the page. Lastly, I <code>await</code> that promise, making my test resilient to how long it takes to fetch the data.</p> <p>And with that, the flake is gone! 🎉</p> <h2>Resources</h2> <p><a href="https://docs.codecov.com/docs/test-analytics">Test Analytics documentation</a><br /> <a href="https://about.codecov.io/blog/find-failing-and-flaky-tests-with-codecov-test-analytics/">Find failing and flaky tests with Codecov Test Analytics</a><br /> <a href="https://www.epicweb.dev/be-smart-about-flaky-tests">Be S.M.A.R.T. About Flaky Tests</a><br /> <a href="https://github.com/kettanaito/test-analytics-vitest">Full example of using Test Analytics with Vitest on GitHub</a></p> <div class="row my-5 text-center align-items-center d-none"> <div class="col-lg-6 text-left"> <h6>Previous Post</h6> <a href="https://about.codecov.io/blog/beyond-coverage-flaky-test-detection-ai-test-generation-and-more/" rel="prev">Beyond Coverage: Flaky Test Detection, AI Test Generation, and More</a> </div> <div class="col-lg-6 text-right"> <h6>Next Post</h6> <a href="https://about.codecov.io/blog/measuring-the-effectiveness-of-test-suites-beyond-code-coverage-metrics/" rel="next">Measuring the Effectiveness of Test Suites: Beyond Code Coverage Metrics</a> </div> </div> </div> <div class="col-1"> </div> </div> </div> </main> <section id="cta"> <div class="container"> <div class="row d-flex justify-content-center"> <div class="col-8 text-center"> <div class="cta__sign-up"> <div class="row d-flex justify-content-center"> <div class="col-12 col-lg-8"> <h2>Ready to get covered?</h2> <p>Join over a million developers in shipping healthier code today.</p> </div> </div> <div class="row"> <div class="col-12 col-lg-6 py-1"> <a class="btn btn-lg btn-dark-blue w-100 plausible-event-name=Click+Signup" href="https://about.codecov.io/sign-up/">Get Started</a> </div> <div class="col-12 col-lg-6 py-1"> <a class="btn btn-lg btn-primary w-100 plausible-event-name=Click+Demo" href="https://about.codecov.io/demo/">Get Demo</a> </div> </div> </div> </div> </div> </div> </section> <footer id="footer"> <!-- TOP FOOTER --> <div id="footer__top"> <div class="container"> <div class="row d-flex justify-content-center justify-content-lg-start text-center text-lg-left align-items-center"> <div class="col-12 col-lg-1"> <a href="https://about.codecov.io" id="footer__logo" title="codecov"> <img src="/wp-content/themes/codecov/assets/brand/icons/codecov/codecov-circle.svg" loading="lazy" alt="codecov code coverage"> </a> </div> <div class="col-12 col-lg-11 mt-3 mt-lg-0"> <nav id="follow"> <ul> <li> <a href="https://www.linkedin.com/company/codecov/" target="_blank" rel="noopener noreferrer" title="LinkedIn"><i class="fab fa-linkedin"></i></a> </li> <li> <a href="https://twitter.com/codecov" target="_blank" rel="noopener noreferrer" title="Twitter"><i class="fab fa-twitter"></i></a> </li> <li> <a href="https://github.com/codecov" target="_blank" rel="noopener noreferrer" title="Github"><i class="fab fa-github"></i></a> </li> <li> <a href="https://www.youtube.com/channel/UCj-fJuvXv-m05HkSNn0OS9g/featured" target="_blank" rel="noopener noreferrer" title="YouTube"><i class="fab fa-youtube"></i></a> </li> <li> <a href="https://angel.co/company/codecov" target="_blank" rel="noopener noreferrer" title="AngelList"><i class="fab fa-angellist"></i></a> </li> <li> <a href="https://community.codecov.io/" target="_blank" rel="noopener noreferrer" title="Discourse"><i class="fab fa-discourse"></i></a> </li> <li> <a href="https://www.instagram.com/codecov/" target="_blank" rel="noopener noreferrer" title="Instagram"><i class="fab fa-instagram"></i></a> </li> </ul> </nav> </div> </div> </div> </div> <!-- MIDDLE FOOTER --> <div id="footer__middle"> <div class="container"> <div class="row d-flex justify-content-between"> <div class="col-12 col-sm-6 col-lg-2 text-center text-lg-left"> <h3><a href="/product/features/">Product</a></h3> <ul> <li><a href="/product/features/">Features</a></li> <li><a href="/product/integrations/">Integrations</a></li> <!-- <li><a href="/product/getting-started/">Getting Started</a></li>--> <li><a href="/product/documentation/">Documentation</a></li> <li><a href="/product/api/">API</a></li> <li><a href="/product/status/">Status</a></li> </ul> </div> <div class="col-12 col-sm-6 col-lg-2 text-center text-lg-left"> <h3><a href="/solutions/">Solutions</a></h3> <ul> <li><a href="/for/open-source/">Open Source</a></li> <li><a href="/for/enterprises/">Enterprise</a></li> <li><a href="/for/startups/">Startups</a></li> <li><a href="/for/education/">Education</a></li> </ul> </div> <div class="col-12 col-sm-6 col-lg-2 text-center text-lg-left"> <h3><a href="/customers/">Customers</a></h3> <ul> <li><a href="/customers/">Customers</a></li> <li><a href="/resources/?_type=case-study">Case Studies</a></li> <li><a href="/resources/community/">Community</a></li> <!-- <li><a href="/customers/advisory-board/">Customer Advisory Board</a></li>--> <!-- <li><a href="/resources/swag/">Swag</a></li>--> </ul> </div> <div class="col-12 col-sm-6 col-lg-2 text-center text-lg-left"> <h3><a href="/resources/">Resources</a></h3> <ul> <!-- <li><a href="/resources/?_type=case-study">Case Studies</a></li>--> <li><a href="/resources/?_type=webinar%2Con-demand-webinar">Webinars</a></li> <li><a href="/blog/">Blog</a></li> <li><a href="/product/documentation/">Documentation</a></li> </ul> </div> <div class="col-12 col-sm-6 col-lg-2 text-center text-lg-left"> <h3><a href="/">Company</a></h3> <ul> <!-- <li><a href="/company/">About Us</a></li>--> <li><a href="/team/">Team</a></li> <li><a href="/company/press/">Press</a></li> <li><a href="/careers/">Careers</a></li> <!--<li><a href="/write-for-us/">Write for us</a></li> --> <!-- <li><a href="/company/partners/">Partners</a></li>--> </ul> </div> <div class="col-12 col-sm-6 col-lg-2 text-center text-lg-left"> <h3><a href="/contact/">Contact Us</a></h3> <ul> <li><a href="/contact/">Contact</a></li> <li><a href="/demo/">Demo</a></li> <!-- <li><a href="#chat">Live Chat</a></li>--> <li><a href="https://codecovpro.zendesk.com/">Pro Support</a></li> <li><a href="https://codecoventerprise.zendesk.com/">Enterprise Support</a></li> <li><a href="https://community.codecov.com/">Community Board</a></li> </ul> </div> </div> </div> </div> <!-- BOTTOM FOOTER --> <div id="footer__bottom"> <div class="container"> <div class="row d-flex justify-content-center"> <div class="col-12 col-lg-10 d-flex justify-content-center align-items-center text-center mb-3 mb-lg-0"> <nav> <ul> <li><a href="/terms-of-service/">Terms of Service</a></li> <li><a href="/privacy/">Privacy</a></li> <li><a href="/security/">Security</a></li> <li><a href="/gdpr/">GDPR</a></li> <li><a href="/data-processing-addendum/">Data Processing Addendum</a></li> <li><a href="#" class="cky-banner-element">Cookie Preferences</a></li> <li><a href="/privacy/#tabs--california">California Privacy Notice</a></li> </ul> </nav> </div> <div class="col-12 d-flex justify-content-center align-items-center"> <p>© 2025 • SENTRY IS A REGISTERED TRADEMARK OF FUNCTIONAL SOFTWARE, INC.</p> </div> </div> </div> </div> </footer> <!-- LikeBtn.com BEGIN --> <script type="text/javascript">var likebtn_wl = 1; (function(d, e, s) {a = d.createElement(e);m = d.getElementsByTagName(e)[0];a.async = 1;a.src = s;m.parentNode.insertBefore(a, m)})(document, 'script', '//w.likebtn.com/js/w/widget.js'); if (typeof(LikeBtn) != "undefined") { LikeBtn.init(); }</script> <!-- LikeBtn.com END --> <script type="text/javascript" src="https://about.codecov.io/wp-content/themes/codecov/assets/scripts/main-lean.js?version=1742918080&ver=6.7.2" id="script-single-js"></script> <script type="text/javascript" src="https://about.codecov.io/wp-content/plugins/page-links-to/dist/new-tab.js?ver=3.3.7" id="page-links-to-js"></script> <script type="text/javascript" src="https://about.codecov.io/wp-includes/js/comment-reply.min.js?ver=6.7.2" id="comment-reply-js" async="async" data-wp-strategy="async"></script> <div id="github-login-interstitial"> <div class="row"> <div class="col-12"> <div class="alert alert-info"> <h5>Before we redirect you to GitHub...</h5> <small>In order to use Codecov an admin must approve your org.</small> </div> </div> <div class="col-10 mx-auto my-3"> <img src="/wp-content/themes/codecov/assets/temp/request-access.gif" class="img-fluid" loading="lazy" /> </div> <div class="col-12"> <a class="btn-github-private plausible-event-name=Click+Github" id="github-private" class="btn btn-sm btn-pink float-right d-block" href="https://codecov.io/login/gh">Continue to GitHub →</a> </div> <div class="col-12 pt-2"> <a class="btn-github-public plausible-event-name=Click+Github" class="float-right d-block" href="https://codecov.io/login/gh"><small>Continue to GitHub (Public Repos Only) →</small></a> </div> </div> </div> </body> </html>