<?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: VictorOliveira</title>
    <description>The latest articles on DEV Community by VictorOliveira (@victorholiveira).</description>
    <link>https://dev.to/victorholiveira</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4084794%2F2f581312-3e97-45d3-8f4f-e9bded6afca1.png</url>
      <title>DEV Community: VictorOliveira</title>
      <link>https://dev.to/victorholiveira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/victorholiveira"/>
    <language>en</language>
    <item>
      <title>Flaky Tests: O Problema Não São os Testes, É a Confiança</title>
      <dc:creator>VictorOliveira</dc:creator>
      <pubDate>Wed, 19 Aug 2026 18:09:33 +0000</pubDate>
      <link>https://dev.to/victorholiveira/flaky-tests-o-problema-nao-sao-os-testes-e-a-confianca-b8l</link>
      <guid>https://dev.to/victorholiveira/flaky-tests-o-problema-nao-sao-os-testes-e-a-confianca-b8l</guid>
      <description>&lt;h1&gt;
  
  
  Flaky Tests: O Problema Não São os Testes, É a Confiança
&lt;/h1&gt;

&lt;p&gt;Um desenvolvedor aperta "merge". O pipeline fica vermelho. Ele clica em "re-run". Passa verde. Merge feito. Ninguém investiga.&lt;/p&gt;

&lt;p&gt;Esse cenário se repete milhões de vezes por dia em empresas ao redor do mundo. E é exatamente aí que mora o problema: não são os testes que estão quebrados — é a confiança no pipeline que se destruiu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os Números Que Ninguém Quer Ver
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google&lt;/strong&gt;: 1,5 milhão de reruns de testes flaky por dia no pico&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atlassian&lt;/strong&gt;: 21% das falhas no master branch são causadas por flaky tests — totalizando 150.000 horas de desenvolvedores desperdiçadas por ano&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SAP HANA&lt;/strong&gt;: Análise de 559 reports de flakiness mostrou que 23% são causados por problemas de concorrência&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exact&lt;/strong&gt;: Uma empresa com 2.000 funcionários e 25.000 testes diários tinha taxa de sucesso de pipeline de apenas 27% antes de atacar flakiness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flaky tests não são uma inconveniência técnica. São um &lt;strong&gt;problema de economia de entrega&lt;/strong&gt;. E ele se compõe.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Ciclo da Desconfiança
&lt;/h2&gt;

&lt;p&gt;O ciclo é previsível e acontece em 6-8 semanas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semana 1-2&lt;/strong&gt;: Flaky tests começam a aparecer. Desenvolvedos culpam seu próprio código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semana 3&lt;/strong&gt;: Eles percebem o padrão — mesmos testes, mesmas falhas, nada a ver com suas mudanças.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semana 6&lt;/strong&gt;: Mentalmente, desistiram. Toda a suíte se torna suspeita, inclusive os testes que funcionam perfeitamente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semana 8&lt;/strong&gt;: O pipeline perde toda credibilidade. O que antes era uma barreira de qualidade vira um obstáculo irritante.&lt;/p&gt;

&lt;p&gt;O indicador-chave? &lt;strong&gt;Taxa de re-run&lt;/strong&gt;. Quando desenvolvedores clicam "retry" em mais de 30% dos seus PRs, eles não estão testando — estão apostando. Abaixo de 30%, eles confiam que a falha é deles. Acima de 30%, confiam que a falha é da infraestrutura.&lt;/p&gt;

&lt;h2&gt;
  
  
  As 5 Causas Raiz (Nenhuma É "Azar")
&lt;/h2&gt;

&lt;p&gt;Flakiness quase nunca é aleatório. Há padrões identificáveis:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Corridas de Tempo (Timing Races)
&lt;/h3&gt;

&lt;p&gt;A causa mais comum. Um &lt;code&gt;sleep(5000)&lt;/code&gt; hardcoded que funciona 99% do tempo, mas falha quando o CI está sob carga. Ou uma.assert que verifica o estado antes da UI terminar de renderizar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// RUIM — depende de timing fixo&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sucesso&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// BOM — espera pela condição real&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sucesso&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Playwright resolve isso com auto-wait nativo. Cypress tem retry automático de comandos. Mas a regra universal é: &lt;strong&gt;nunca asserte em um timer, sempre no estado estabelecido&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Estado Compartilhado (Test Interdependence)
&lt;/h3&gt;

&lt;p&gt;O teste A cria um registro no banco. O teste B depende desse registro. O teste C deleta algo que o teste D precisa. Resultado: a ordem de execução determina se o build passa ou falha.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# RUIM — fixture global compartilhada
&lt;/span&gt;&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;db_connection&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# BOM — isolamento por teste
&lt;/span&gt;&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;db_connection&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Limpa tudo após o teste
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Teste de sanidade&lt;/strong&gt;: Se você embaralhar a ordem dos testes e o suite quebrar, existe acoplamento oculto que retries esconderiam pra sempre.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ambiente Instável (Environment Flakiness)
&lt;/h3&gt;

&lt;p&gt;APIs externas com latência variável, containers que demoram para subir, dados de teste compartilhados entre pipelines. Um estudo do Docker descobriu que após um ano tentando consertar testes individualmente, a estabilidade não melhorou — até que investiram na infraestrutura do ambiente de teste.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Dependências de Rede
&lt;/h3&gt;

&lt;p&gt;Chamadas HTTP reais em testes E2E. Timeouts que variam dependendo da carga do servidor. Webhooks que chegam antes ou depois do esperado.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Animações e Transições
&lt;/h3&gt;

&lt;p&gt;Elementos que estão em transição CSS quando o teste tenta interagir. Modais que estão animando abrindo. Toasts que somem após 3 segundos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por Que Retries São o Pior Remédio
&lt;/h2&gt;

&lt;p&gt;A indústria tratou flaky tests como um problema de agendamento. Retry 3 vezes, se passar, tá verde. Mas retries não consertam — escondem.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimensão&lt;/th&gt;
&lt;th&gt;Retries às cegas&lt;/th&gt;
&lt;th&gt;Quarantine + fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sinal de falha&lt;/td&gt;
&lt;td&gt;Oculto, descartado&lt;/td&gt;
&lt;td&gt;Preservado e classificado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tempo/custo de CI&lt;/td&gt;
&lt;td&gt;Cresce silenciosamente&lt;/td&gt;
&lt;td&gt;Diminui com o tempo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confiança no deploy&lt;/td&gt;
&lt;td&gt;Verde falso, bugs passam&lt;/td&gt;
&lt;td&gt;Verde confiável&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Causas raiz&lt;/td&gt;
&lt;td&gt;Se acumulam&lt;/td&gt;
&lt;td&gt;Caminham a zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confiança do dev&lt;/td&gt;
&lt;td&gt;Erosiona&lt;/td&gt;
&lt;td&gt;Se restaura&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O pior cenário: um teste que falha 20% do tempo passa quase sempre com política de 3 retries. Parece estável, mas não é. Quando finalmente deixa passar uma regressão real no retry "sortudo", vocêshipa o bug confiando no checkmark verde.&lt;/p&gt;

&lt;p&gt;Um pipeline com taxa de retry de 15% e pass rate de 98% não é um pipeline saudável. É um pipeline com um problema de confiança escondido.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Estratégia de Quarantine
&lt;/h2&gt;

&lt;p&gt;A alternativa aos retries é o &lt;strong&gt;quarantine&lt;/strong&gt; — isolar testes flaky sem deletá-los, mantendo visibilidade enquanto resolve a causa raiz.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como Implementar
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Detectar automaticamente&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Registre resultados por teste, por commit SHA. Um teste que passa E falha no mesmo SHA é flaky por definição.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Exemplo de detecção via histórico
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_flaky&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;statuses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;test_name&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pass&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;statuses&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fail&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;statuses&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Separar em duas suítes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blocking suite&lt;/strong&gt;: testes estáveis. Falha aqui bloqueia o merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quarantine suite&lt;/strong&gt;: testes flaky conhecidos. Executam, mas não bloqueiam.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Dono e prazo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cada teste em quarantine tem um dono e um ticket. Prazo máximo: 30 dias. Depois disso: consertar ou deletar com justificativa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Monitorar&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tamanho do quarantine ao longo do tempo (crescendo = problema)&lt;/li&gt;
&lt;li&gt;Dias em quarantine por teste (máximo 30)&lt;/li&gt;
&lt;li&gt;Taxa de entrada/saída (fluido = saudável)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resultado Real
&lt;/h3&gt;

&lt;p&gt;A Exact aplicou essas intervenções e elevou a taxa de sucesso do pipeline de &lt;strong&gt;27% para 96%&lt;/strong&gt;. O segredo não foi consertar todos os testes — foi classificar, isolar e atacar as causas raiz: tarefas de banco redundantes (40% das falhas) e dados de teste poluídos (22%).&lt;/p&gt;

&lt;h2&gt;
  
  
  Métricas Que Importam
&lt;/h2&gt;

&lt;p&gt;Esqueça pass rate. Essas métricas contam a verdadeira história:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Como calcular&lt;/th&gt;
&lt;th&gt;Meta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flake rate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Testes com pass/fail misto no mesmo commit / total&lt;/td&gt;
&lt;td&gt;&amp;lt; 2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Taxa de retry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Jobs que passam só no retry / total de jobs&lt;/td&gt;
&lt;td&gt;&amp;lt; 2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Quarantine %&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Testes em quarantine / total de testes&lt;/td&gt;
&lt;td&gt;&amp;lt; 5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custo de retry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minutos de retry / minutos totais de CI&lt;/td&gt;
&lt;td&gt;&amp;lt; 10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tempo para confiança&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tempo até o dev confiar que o merge é seguro&lt;/td&gt;
&lt;td&gt;&amp;lt; 10 min&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  O Que a Pesquisa Diz Sobre IA e Flakiness
&lt;/h2&gt;

&lt;p&gt;Um dado que pega desprevenido: &lt;strong&gt;testes gerados por IA aumentam a taxa de flakiness&lt;/strong&gt;. LLMs são competentes em gerar scaffolding de testes, mas frequentemente criam asserts frágeis — dependência de timing, assumptions hardcoded sobre o ambiente, e mocks excessivamente específicos.&lt;/p&gt;

&lt;p&gt;Antes de jogar um Copilot na suíte de testes, modernize a infraestrutura de teste primeiro. Caso contrário, você vai aumentar a taxa de flakiness com confiança.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aprender com Google, Atlassian e SAP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Google&lt;/strong&gt; descobriu que 84% das transições de pass para fail vêm de flakiness, não de bugs reais. Isso significa que quase toda falha que seu time investiga é fantasma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atlassian&lt;/strong&gt; quantificou o custo: 150.000 horas/ano desperdiçadas. Quando flaky tests causam 21% das falhas no master, o problema não é mais técnico — é financeiro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SAP HANA&lt;/strong&gt; analisou 559 reports de flakiness usando LLMs como anotadores. Concorrência (23%), timeouts (18%), e fragilidade de oráculos (11%) foram as principais causas. Cada tipo de teste enfrenta desafios diferentes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão: Trust Over Green
&lt;/h2&gt;

&lt;p&gt;Um build verde que ninguém acredita é pior que nenhum build. Porque ele fornece confiança falsa no exato momento em que você precisa de confiança real: enviando para produção.&lt;/p&gt;

&lt;p&gt;A regra é simples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pare de medir pass rate.&lt;/strong&gt; Meça taxa de retry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pare de consertar cada flaky test.&lt;/strong&gt; Quarantine os piores 5%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pare de celebrar builds verdes.&lt;/strong&gt; Celebre pipelines confiáveis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nunca faça retry de vermelho para verde.&lt;/strong&gt; Isso é mentira.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Confiança não é binária. Não se perde gradualmente — despenha de um penhasco. E recuperá-la é muito mais difícil do que perdê-la.&lt;/p&gt;

&lt;p&gt;Seu pipeline mente? A resposta define se você pode confiar na sua automação ou se está apenas apertando botões.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Baseado em pesquisas do Google, Atlassian, SAP, Exact, Docker, e artigos de DevOps.com, SD Times, e ContextQA (2026).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>devops</category>
      <category>qualityassurance</category>
      <category>ci</category>
    </item>
    <item>
      <title>Design Patterns para Automação de Testes: Guia Prático com Playwright e Cypress</title>
      <dc:creator>VictorOliveira</dc:creator>
      <pubDate>Wed, 19 Aug 2026 17:48:06 +0000</pubDate>
      <link>https://dev.to/victorholiveira/design-patterns-para-automacao-de-testes-guia-pratico-com-playwright-e-cypress-391b</link>
      <guid>https://dev.to/victorholiveira/design-patterns-para-automacao-de-testes-guia-pratico-com-playwright-e-cypress-391b</guid>
      <description>&lt;h1&gt;
  
  
  Design Patterns para Automação de Testes: Guia Prático
&lt;/h1&gt;

&lt;p&gt;Se você já escreveu automação de testes, provavelmente já enfrentou aquele momento em que os testes ficam tão acoplados que qualquer mudança quebram dezenas de scripts. É aí que os &lt;strong&gt;Design Patterns&lt;/strong&gt; entram.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos ver os padrões mais usados na indústria, com exemplos práticos em &lt;strong&gt;Playwright&lt;/strong&gt; e &lt;strong&gt;Cypress&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Page Object Model (POM)
&lt;/h2&gt;

&lt;p&gt;O mais clássico e amplamente adotado. Separa a lógica de localização dos elementos da lógica dos testes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Playwright - Page Object&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;passwordInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;submitButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[type=submit]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emailInput&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;passwordInput&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submitButton&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vantagens:&lt;/strong&gt; Manutenção centralizada, reutilizabilidade, código limpo nos testes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Screenplay Pattern
&lt;/h2&gt;

&lt;p&gt;Mais avançado, modela testes como &lt;strong&gt;atores realizando ações em um cenário&lt;/strong&gt;. Excelente para testes complexos com múltiplos usuários.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Data-Driven Testing
&lt;/h2&gt;

&lt;p&gt;Separa os dados dos testes da lógica. Ideal para validar múltiplas entradas no mesmo fluxo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testCases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;viewer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Read Only&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;testCases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Login as &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;loginAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Fixture Pattern (Cypress)
&lt;/h2&gt;

&lt;p&gt;No Cypress, fixtures são nativos e permitem setup/teardown elegante:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;storageState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.stats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Não existe um pattern perfeito para todos os casos. O ideal é &lt;strong&gt;combinar&lt;/strong&gt; POM com Data-Driven e ajustar conforme a complexidade do projeto.&lt;/p&gt;

&lt;p&gt;Quer aprender mais? Visite &lt;a href="https://qaoverflow.com" rel="noopener noreferrer"&gt;QA Overflow&lt;/a&gt; para tutoriais completos.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Artigo por Victor Oliveira - QA Senior com 13+ anos de experiência&lt;/em&gt;&lt;/p&gt;

</description>
      <category>qa</category>
      <category>testing</category>
      <category>automation</category>
      <category>playwright</category>
    </item>
  </channel>
</rss>
