<?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: Lucas Amaral</title>
    <description>The latest articles on DEV Community by Lucas Amaral (@lopesdoamaral).</description>
    <link>https://dev.to/lopesdoamaral</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%2F3989149%2Fa59dc71a-b2a9-4c70-85c9-1f76bd465d9e.png</url>
      <title>DEV Community: Lucas Amaral</title>
      <link>https://dev.to/lopesdoamaral</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lopesdoamaral"/>
    <language>en</language>
    <item>
      <title>Engenharia de Prompts para Massa de Dados: Escalando Testes com Cobertura e Sem Duplicidade utilizando LLMs</title>
      <dc:creator>Lucas Amaral</dc:creator>
      <pubDate>Wed, 17 Jun 2026 13:10:19 +0000</pubDate>
      <link>https://dev.to/lopesdoamaral/engenharia-de-prompts-para-massa-de-dados-escalando-testes-com-cobertura-e-sem-duplicidade-oba</link>
      <guid>https://dev.to/lopesdoamaral/engenharia-de-prompts-para-massa-de-dados-escalando-testes-com-cobertura-e-sem-duplicidade-oba</guid>
      <description>&lt;p&gt;O uso de LLMs para a geração de dados sintéticos tornou-se uma estratégia atraente para equipes de QA que precisam escalar suas esteiras de testes. A promessa é tentadora: gerar centenas de registros complexos em segundos. No entanto, na prática, a geração automatizada sem direcionamento técnico introduz um risco crítico: &lt;strong&gt;a falsa sensação de cobertura&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quando submetidas a prompts genéricos (como &lt;em&gt;"gere 50 usuários para teste"&lt;/em&gt;), as LLMs tendem a operar dentro de padrões estatísticos previsíveis. O resultado é o &lt;strong&gt;efeito "João da Silva"&lt;/strong&gt;: um volume massivo de dados que testa repetidamente o "caminho feliz" (&lt;em&gt;happy path&lt;/em&gt;), gerando duplicidade de cenários e deixando lacunas profundas em lógica de negócios complexas e cenários de borda (&lt;em&gt;edge cases&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Para mitigar o viés do modelo e garantir a eficácia dos testes, o QA deve transicionar do papel de mero solicitante para o de &lt;strong&gt;orquestrador de cenários&lt;/strong&gt;, aplicando técnicas tradicionais de teste diretamente na engenharia de prompts. A seguir, analisamos três padrões estruturados de prompts para resolver os problemas de cobertura e duplicidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. O Padrão de Particionamento de Equivalência e Valores Limite
&lt;/h2&gt;

&lt;p&gt;Para garantir cobertura sem inflar a base de dados com registros redundantes, o prompt deve forçar a LLM a aplicar técnicas de design de testes &lt;em&gt;antes&lt;/em&gt; da geração do dado final. Esse padrão utiliza a abordagem de cadeia de pensamento (&lt;em&gt;Chain-of-Thought&lt;/em&gt;), obrigando o modelo a mapear as classes de equivalência estruturalmente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo de Prompt Estruturado:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Defina seu papel: Você é um Engenheiro de QA Sênior especializado em testes de API e validação de regras de negócio.

Contexto do Sistema: Estou testando o endpoint de aplicação de cupons de desconto de um e-commerce. As regras de negócio são:
1. Cupons do tipo "FIXO" exigem valor mínimo de compra de R$ 100,00.
2. Cupons do tipo "PERCENTUAL" aplicam-se a qualquer valor, mas têm teto máximo de desconto de R$ 50,00.
3. Cupons com data de validade expirada devem ser rejeitados.

Sua Tarefa:
1. Identifique e liste em uma tabelaMarkdown todas as Classes de Equivalência (Válidas e Inválidas) e os Valores Limite (Boundaries) para as regras acima.
2. Com base nessa tabela, gere exatamente UM payload JSON para cada cenário identificado. Cada cenário deve isolar uma variável de teste para garantir rastreabilidade.

Restrição: Não gere payloads duplicados para a mesma classe de equivalência. Foque na cobertura mínima necessária para testar todas as ramificações do código.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que essa abordagem resolve:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cobertura:&lt;/strong&gt; Garante que os valores exatos de transição de estado do código (ex: R$ 99,99, R$ 100,00 e R$ 100,01) sejam testados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eficiência:&lt;/strong&gt; Elimina dados redundantes dentro da mesma classe de equivalência, mantendo a suite de testes enxuta e performática.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. O Padrão de Matriz de Transição de Estados (Contra a Duplicidade Comportamental)
&lt;/h2&gt;

&lt;p&gt;Em sistemas orientados a eventos ou máquinas de estado (como fluxos de pagamento ou processamento de pedidos), os dados de teste precisam refletir a assincronicidade e o histórico do ciclo de vida da entidade. O erro comum é gerar dados que representam apenas o estado final ou inicial estável.&lt;/p&gt;

&lt;p&gt;O prompt a seguir utiliza restrição de grafo para forçar a IA a cobrir caminhos de exceção e transições inválidas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo de Prompt Estruturado:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Contexto: Sistema de gerenciamento de pedidos com os seguintes estados: [Criado, Pago, Faturado, Enviado, Entregue, Cancelado].

Diretriz de Geração: Gere uma massa de dados de teste em formato CSV que cubra a Matriz de Transição de Estados do sistema. 

A massa deve conter:
1. Cenários de Fluxo Linear (Transições válidas de ponta a ponta).
2. Cenários de Fluxo de Exceção (Transições válidas de desvio, ex: Criado -&amp;gt; Cancelado).
3. Cenários de Violação de Estado (Transições inválidas que o sistema deve rejeitar, ex: Tentar transicionar de 'Entregue' para 'Cancelado', ou de 'Criado' para 'Enviado' sem passar por 'Pago').

Colunas do CSV necessárias: id_pedido, estado_atual, estado_destino, payload_acao, resultado_esperado (Sucesso/Erro).

Regra estrita: Gere apenas uma linha por combinação única de 'estado_atual' -&amp;gt; 'estado_destino'. Proibido duplicar cenários ideais.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que essa abordagem resolve:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prevenção de Duplicidade:&lt;/strong&gt; Ao mapear a transição como uma chave única (&lt;code&gt;estado_atual&lt;/code&gt; + &lt;code&gt;estado_destino&lt;/code&gt;), impede-se que a LLM gere múltiplos registros para fluxos comuns, como pedidos padrão que já foram testados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testes Negativos:&lt;/strong&gt; Força a criação de dados para validação de resiliência e tratamento de erros do sistema.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. O Padrão de Variabilidade Restrita (&lt;em&gt;Negative Prompting&lt;/em&gt;)
&lt;/h2&gt;

&lt;p&gt;A entropia das LLMs pode fazer com que elas gerem dados realistas, porém excessivamente homogêneos em sua distribuição (como utilizar sempre a mesma faixa de CEPs ou a mesma demografia). Para evitar que os testes fiquem tendenciosos, aplicamos restrições explícitas de variância e o conceito de &lt;em&gt;Negative Prompting&lt;/em&gt; (o que o modelo está proibido de fazer).&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo de Prompt Estruturado:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tarefa: Gere um lote de 10 perfis de clientes em formato JSON para homologação de um sistema de análise de crédito.

Requisitos de Variabilidade:
1. Idade: Distribua uniformemente entre as faixas etárias de 18-25, 26-45, 46-60 e acima de 65 anos.
2. Localização: Utilize estados das cinco diferentes regiões do Brasil (Sul, Sudeste, Centro-Oeste, Nordeste, Norte).
3. Renda: Inclua variações de renda formal, informal e desempregados.

PROIBIÇÕES (Negative Prompt):
- NÃO utilize nomes fictícios óbvios ou genéricos (ex: "João da Silva", "Fulano de Tal", "Teste 1").
- NÃO repita a mesma combinação de Região e Faixa Etária em registros diferentes.
- NÃO utilize máscaras de documentos (CPF) idênticas ou sequenciais.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que essa abordagem resolve:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eliminação de Viés Extrinseco:&lt;/strong&gt; Garante que validações de front-end ou regras de backend baseadas em localização, ou limites numéricos amplos, lidem com dados semanticamente diversos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Determinismo Sintático:&lt;/strong&gt; Reduz a necessidade de sanitização manual posterior dos dados gerados.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusão: A Validação Determinística como Próximo Passo
&lt;/h2&gt;

&lt;p&gt;A engenharia de prompts robusta mitiga a maior parte dos problemas de cobertura e duplicidade na geração de dados sintéticos, mas não elimina a necessidade de validação. Para cenários de larga escala em pipelines de CI/CD, a abordagem ideal combina a &lt;strong&gt;geração generativa estruturada&lt;/strong&gt; (via LLM com os prompts acima) com uma &lt;strong&gt;camada de validação determinística&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O ganho de velocidade proporcionado pela IA só se traduz em eficiência real se os dados gerados forem intencionais. O papel do QA, portanto, evolui de escrever dados estáticos para codificar as regras de restrição que governam os modelos gerativos.&lt;/p&gt;

&lt;p&gt;No contexto de testes de aplicações baseadas em IA (como testar um LLM, um classificador de machine learning ou um sistema de recomendação), a resposta curta é: depende do tipo de teste, mas na maioria das vezes, a duplicidade estrita (exata) ainda é indesejada. No entanto, a redundância semântica ou a repetição intencional de inputs assume um papel completamente diferente e legítimo do que em softwares tradicionais.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Artigo escrito auxiliado por Google Gemini&lt;/code&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>llm</category>
      <category>testing</category>
    </item>
    <item>
      <title>Lei de Little e o dimensionamento de Testes de Performance</title>
      <dc:creator>Lucas Amaral</dc:creator>
      <pubDate>Wed, 27 May 2026 13:27:28 +0000</pubDate>
      <link>https://dev.to/lopesdoamaral/lei-de-little-e-o-dimensionamento-de-testes-de-performance-1b6</link>
      <guid>https://dev.to/lopesdoamaral/lei-de-little-e-o-dimensionamento-de-testes-de-performance-1b6</guid>
      <description>&lt;p&gt;Você acabou de implantar uma nova funcionalidade e o seu líder pede para você realizar um &lt;strong&gt;teste de carga&lt;/strong&gt;. O objetivo? Garantir que o sistema aguente 500 requisições por segundo. Você abre uma ferramenta como o JMeter ou o Locust e se depara com a pergunta de um milhão de dólares: &lt;em&gt;“Quantos usuários virtuais eu devo configurar para atingir esse objetivo?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Se você tentar adivinhar, provavelmente vai derrubar o servidor ou criar um teste que não reflete a realidade. É aqui que entra a &lt;strong&gt;Lei de Little&lt;/strong&gt; , uma fórmula matemática simples que vai se auxiliar no dimensionamento para seus testes de performance de software.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos desmistificar esse conceito, entender o comportamento humano nos testes e mostrar como aplicar tudo isso na prática.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é a Lei de Little?
&lt;/h3&gt;

&lt;p&gt;Formulada pelo professor &lt;strong&gt;John Little&lt;/strong&gt; em 1961, essa lei nasceu no contexto da engenharia de produção e teoria das filas (como filas de banco ou supermercados). Ela dita que, em um sistema estável, existe uma relação fixa entre três variáveis:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;O número de itens dentro do sistema&lt;/strong&gt; (Inventário).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A velocidade com que os itens entram e saem&lt;/strong&gt; (Taxa de transferência).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O tempo que cada item passa lá dentro&lt;/strong&gt; (Tempo de permanência).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A fórmula matemática oficial é:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusi18iyb253wyuhfda7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusi18iyb253wyuhfda7s.png" width="213" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traduzindo para o mundo do Software&lt;/p&gt;

&lt;p&gt;Para desenvolvedores, os “itens” são as requisições ou os usuários, e o “sistema” é a nossa aplicação (API, banco de dados, servidor). Reescrevendo os termos para a nossa realidade, temos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;L&lt;/em&gt; (Concorrência / WIP):&lt;/strong&gt; O número médio de requisições sendo processadas simultaneamente no servidor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;λ&lt;/em&gt; (Throughput / Vazão):&lt;/strong&gt; A taxa de sucesso das requisições (ex: requisições por segundo — RPS).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;W&lt;/em&gt; (Response Time / Tempo de Resposta):&lt;/strong&gt; O tempo médio que o sistema leva para responder a uma requisição.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Analogia do Restaurante:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Imagine um restaurante onde entram 2 clientes por minuto (λ = 2) e cada cliente passa, em média, 30 minutos jantando (W = 30). Quantas pessoas estão dentro do restaurante ao mesmo tempo (L)?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;L = 2 x 30 = 60 clientes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Se o restaurante tiver apenas 40 cadeiras, haverá fila na porta! O mesmo acontece com a memória e a CPU do seu servidor.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Expandindo a Fórmula: O Fator Humano e o Think Time
&lt;/h3&gt;

&lt;p&gt;Quando testamos aplicações web, há um detalhe crucial: &lt;strong&gt;seres humanos não se comportam como robôs hiperativos.&lt;/strong&gt; Se você entrar em um e-commerce, você não clica na Home Page e, em 0,001 segundos, clica em um produto. Você entra na página, gasta alguns segundos lendo os destaques, escolhe o produto, lê as especificações e só depois clica em “Adicionar ao carrinho”.&lt;/p&gt;

&lt;p&gt;Esse intervalo de tempo em que o usuário está consumindo a informação na tela, pensando ou digitando, &lt;strong&gt;sem enviar nenhuma requisição para o servidor&lt;/strong&gt; , é chamado de &lt;strong&gt;Think Time&lt;/strong&gt;  (Z).&lt;/p&gt;

&lt;p&gt;Para incluir o comportamento humano no teste de carga, expandimos a Lei de Little para a &lt;strong&gt;Lei do Tempo de Resposta do Sistema Central&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoryfqx4bg1kgw6xl743.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoryfqx4bg1kgw6xl743.png" width="257" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N = Número de Usuários Virtuais ativos (Concorrência).&lt;/li&gt;
&lt;li&gt;X = &lt;em&gt;Throughput&lt;/em&gt; desejado (Requisições por segundo).&lt;/li&gt;
&lt;li&gt;R = Tempo de resposta do servidor.&lt;/li&gt;
&lt;li&gt;Z = &lt;em&gt;Think Time&lt;/em&gt; (Tempo de pensamento do usuário).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Por que o Think Time é o herói anônimo do seu teste?
&lt;/h3&gt;

&lt;p&gt;Negligenciar o &lt;em&gt;Think Time&lt;/em&gt; é o erro número um de quem está começando em performance. Sem ele, seus usuários virtuais agem como uma “metralhadora de requisições”. As consequências disso são graves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Superfaturamento Artificial de Carga:&lt;/strong&gt; Se 100 usuários reais com &lt;em&gt;Think Time&lt;/em&gt; geram &lt;strong&gt;20 RPS&lt;/strong&gt; (visto que passam a maior parte do tempo lendo a tela), esses mesmos 100 usuários virtuais sem &lt;em&gt;Think Time&lt;/em&gt; podem gerar &lt;strong&gt;2.000 RPS&lt;/strong&gt;. Você vai derrubar o servidor e reportar um bug falso, pois esse cenário de estresse não existe no mundo real.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desperdício de Dinheiro em Nuvem:&lt;/strong&gt; Ao ver o servidor travar com poucos usuários virtuais, a liderança pode achar que o sistema é fraco e gastar milhares de dólares escalando máquinas na AWS/Azure desnecessariamente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simulação Fiel de Recursos:&lt;/strong&gt; O servidor lida de forma diferente com “100 conexões abertas e ociosas esperando o clique” (consome memória para manter a sessão aberta, mas não CPU) versus “100 conexões processando dados na velocidade máxima”. O &lt;em&gt;Think Time&lt;/em&gt; equilibra essa balança.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Como aplicar a Lei de Little em seus Testes de Carga
&lt;/h3&gt;

&lt;p&gt;Como um desenvolvedor Júnior pode usar esse conhecimento no dia a dia? Aqui estão os dois principais casos de uso:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Planejando o Cenário de Teste (Sem adivinhação)
&lt;/h3&gt;

&lt;p&gt;Imagine o seguinte cenário passado pelo seu Product Owner (PO): &lt;em&gt;“Precisamos validar se nossa API aguenta&lt;/em&gt; &lt;strong&gt;&lt;em&gt;100 requisições por segundo (X)&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. Sabemos que o tempo de resposta atual dela é de&lt;/em&gt; &lt;strong&gt;&lt;em&gt;500ms (R = 0,5s)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;e estimamos que o usuário espera&lt;/em&gt; &lt;strong&gt;&lt;em&gt;1,5 segundos (Z)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;entre as ações.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Quantos usuários simulados você deve colocar na ferramenta de teste? Vamos aplicar a fórmula expandida:&lt;/p&gt;

&lt;p&gt;N = 100 x (0,5 + 1,5)&lt;/p&gt;

&lt;p&gt;N = 100 x 2 = 200 usuários virtuais&lt;/p&gt;

&lt;p&gt;Pronto! Você descobriu matematicamente que precisa configurar exatamente &lt;strong&gt;200 usuários virtuais&lt;/strong&gt; para atingir o objetivo de negócio de forma realista.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Identificando Mentiras nos Gráficos (Sanity Check)
&lt;/h3&gt;

&lt;p&gt;Ferramentas de teste e painéis de monitoramento (como Grafana) podem falhar ou exibir dados distorcidos se a infraestrutura estiver sobrecarregada. A Lei de Little serve como o seu detector de mentiras.&lt;/p&gt;

&lt;p&gt;Imagine que, durante um teste com &lt;strong&gt;100 usuários fixos (N)&lt;/strong&gt;, o tempo de resposta da API (R) de repente &lt;strong&gt;dobrou&lt;/strong&gt; devido a uma lentidão no banco de dados.&lt;/p&gt;

&lt;p&gt;Pela matemática da Lei de Little, se o tempo de resposta (R) subiu e o número de usuários (N) permaneceu igual, a taxa de transferência (X) &lt;strong&gt;obrigatoriamente precisa cair&lt;/strong&gt;. Se o seu gráfico mostrar que o &lt;em&gt;Throughput&lt;/em&gt; continuou alto, há algo errado com a máquina que está disparando os testes (ela pode estar sem memória e enfileirando os dados localmente).&lt;/p&gt;

&lt;h3&gt;
  
  
  O Ponto de Inflexão: Quando o sistema satura
&lt;/h3&gt;

&lt;p&gt;A Lei de Little funciona perfeitamente enquanto o sistema está estável. Porém, todo software tem um limite físico (limite de conexões com o banco, threads de CPU, etc.).&lt;/p&gt;

&lt;p&gt;Quando esse limite é atingido, o &lt;em&gt;Throughput&lt;/em&gt; (X) para de crescer e se estabiliza em um teto. Se você continuar adicionando usuários (N) além desse ponto, o tempo de resposta (R) começará a subir vertiginosamente, pois as novas requisições ficarão presas em uma fila de espera (&lt;em&gt;backlog&lt;/em&gt;). O &lt;em&gt;Think Time&lt;/em&gt; (Z) funciona aqui como um amortecedor, atrasando o momento em que o sistema atinge esse colapso.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dica de Ouro: Configurando o Think Time nas Ferramentas
&lt;/h3&gt;

&lt;p&gt;Como humanos não gastam exatamente o mesmo tempo em cada página, você deve evitar usar um valor fixo. Use &lt;strong&gt;valores aleatórios ou distribuições estatísticas&lt;/strong&gt; dentro de uma faixa de tempo. Veja como fazer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No Locust (Python):&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Python
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;locust&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HttpUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt;  

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuarioEcommerce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpUser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="c1"&gt;# Simula um think time aleatório entre 1 e 5 segundos entre as ações     
&lt;/span&gt;  &lt;span class="n"&gt;wait_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;between&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@task&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;acessar_home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No JMeter:&lt;/strong&gt; Adicione o componente &lt;strong&gt;Gaussian Random Timer&lt;/strong&gt; ou &lt;strong&gt;Uniform Random Timer&lt;/strong&gt; dentro do seu fluxo de requisições.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Gatling (Java/Kotlin):&lt;/strong&gt; Use o método .pause(min, max) entre as requisições HTTP.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Para quem está começando, testes de performance podem parecer uma caixa preta cheia de dados aleatórios. A Lei de Little e o entendimento do &lt;em&gt;Think Time&lt;/em&gt; trazem clareza e embasamento científico para o seu trabalho, permitindo que você justifique suas configurações de teste para arquitetos e líderes técnicos com segurança.&lt;/p&gt;

&lt;p&gt;Da próxima vez que abrir uma ferramenta de teste, lembre-se: &lt;strong&gt;Performance não é sobre simular ataques de negação de serviço (DDoS) robóticos, é sobre entender e modelar o fluxo real dos seus usuários.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências para se aprofundar:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Little, J. D. C. (1961).&lt;/strong&gt; &lt;em&gt;A Proof for the Queuing Formula: L = λ x W&lt;/em&gt;. Operations Research. (O artigo científico original).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jain, R. (1991).&lt;/strong&gt; &lt;em&gt;The Art of Computer Systems Performance Analysis&lt;/em&gt;. Wiley. (Considerada a bíblia da análise de performance de sistemas).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentação das Ferramentas:&lt;/strong&gt; Os guias oficiais do Gatling, JMeter e Locust possuem seções ricas detalhando o uso de &lt;em&gt;Timers&lt;/em&gt; e &lt;em&gt;Pauses&lt;/em&gt; baseados na modelagem de carga de Little.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Artigo escrito auxiliado por Google Gemini&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Aceleração Logarítmica: Otimizando Esperas Dinâmicas em Testes de Software</title>
      <dc:creator>Lucas Amaral</dc:creator>
      <pubDate>Fri, 08 May 2026 12:57:22 +0000</pubDate>
      <link>https://dev.to/lopesdoamaral/aceleracao-logaritmica-otimizando-esperas-dinamicas-em-testes-de-software-534</link>
      <guid>https://dev.to/lopesdoamaral/aceleracao-logaritmica-otimizando-esperas-dinamicas-em-testes-de-software-534</guid>
      <description>&lt;h3&gt;
  
  
  Introdução: O Dilema do Polling
&lt;/h3&gt;

&lt;p&gt;Em testes de software modernos, especialmente na automação de interfaces de usuário (UI) ou testes de ponta-a-ponta (E2E), raramente os eventos acontecem instantaneamente. Um botão pode demorar 2 segundos para aparecer após um clique, um relatório pode levar 30 segundos para ser gerado, ou uma API pode demorar um tempo variável para responder.&lt;/p&gt;

&lt;p&gt;Como nossos testes não têm “bola de cristal”, eles precisam &lt;strong&gt;esperar&lt;/strong&gt;. No vocabulário técnico, isso é feito através de &lt;strong&gt;Polling&lt;/strong&gt; : o teste verifica se uma condição é verdadeira (ex: “o botão está visível?”), se não for, ele dorme por um tempo, e tenta novamente, repetindo até o sucesso ou até estourar um tempo limite (Timeout).&lt;/p&gt;

&lt;h4&gt;
  
  
  O Problema com as Esperas Tradicionais
&lt;/h4&gt;

&lt;p&gt;As estratégias de polling mais comuns sofrem de um compromisso doloroso entre &lt;strong&gt;velocidade do teste&lt;/strong&gt; e &lt;strong&gt;carga no sistema&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Espera Fixa (Static Wait):&lt;/strong&gt; O teste verifica a cada intervalo exato (ex: a cada 1 segundo): Se o evento acontece 100ms após a última verificação, o teste perde 900ms esperando desnecessariamente. Multiplique isso por centenas de testes e sua pipeline torna-se lenta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aumento Exponencial (Exponential Backoff):&lt;/strong&gt; O teste dobra o tempo de espera a cada tentativa (ex: $1s, 2s, 4s, 8s…$). É ótimo para SRE/Redes para evitar sobrecarga (efeito manada), mas em testes, se o evento demorar um pouco mais, o próximo intervalo de espera pode ser giganticamente maior que o necessário, atrasando o feedback final.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  O Conceito: Espera em Escala Logarítmica
&lt;/h3&gt;

&lt;p&gt;Propomos uma abordagem diferente para cenários onde sabemos que um evento &lt;strong&gt;vai demorar&lt;/strong&gt; , mas queremos capturá-lo &lt;strong&gt;no exato momento em que ele ocorrer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A ideia central é baseada na percepção humana de tempo em processos longos: &lt;strong&gt;quanto mais tempo esperamos, maior é a probabilidade de que o evento esteja prestes a acontecer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Em vez de desacelerar (como na exponencial) ou manter o passo (como na fixa), a &lt;strong&gt;Espera Logarítmica Acelera&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Início:&lt;/strong&gt; Quando a chance de sucesso é quase zero, fazemos pollings bem espaçados (ex: a cada 5 segundos) para economizar recursos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Com o Passar do Tempo:&lt;/strong&gt; À medida que o tempo avança e a chance de sucesso aumenta, diminuímos o intervalo entre as verificações (ex: $4s, 3s, 2s, 1s, 0.5s$), tornando a busca cada vez mais agressiva.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  A Fórmula Explicada (Sem Dor)
&lt;/h4&gt;

&lt;p&gt;A fórmula que define o intervalo de sono é:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrb3j5pc90qzskvgpxqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrb3j5pc90qzskvgpxqh.png" width="438" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Com uma trava de segurança para não ser menor que um valor mínimo, o Floor)&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vamos torná-la didática:
&lt;/h4&gt;

&lt;p&gt;Pense na fórmula como uma &lt;strong&gt;Escada Rolante que Desce&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial:&lt;/strong&gt; É o intervalo mais longo que você quer no começo. Ex: começar esperando 5 segundos entre cada verificação.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tentativa (Os Degraus):&lt;/strong&gt; A cada vez que o teste falha, ele desce um degrau. Quanto maior o número da tentativa ($1, 2, 3…$), mais baixo na escada você está.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tentativa + 1 (O Freio do Logaritmo):&lt;/strong&gt; Usamos o logaritmo porque ele cresce devagar. Isso garante que a aceleração não seja absurda nas primeiras tentativas, dando tempo ao sistema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;k (A Velocidade da Escada):&lt;/strong&gt; É uma constante que calculamos automaticamente baseada em quão rápido você quer chegar ao final (o Floor).&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Visualizando a Diferença
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 5 |*
 4 | *
 3 | *
 2 | *
 1 | *
 0 | *
-1 | **
-2 | ***
-3 | ****
    +--------------------------------
      0 2 4 6 8 10 20

| Tentativa (`x`) | Intervalo (`y`) |
| --------------- | --------------- |
| 0 | 5.00 |
| 1 | 3.27 |
| 2 | 2.25 |
| 3 | 1.53 |
| 5 | 0.52 |
| 6 | 0.14 |
| 7 | -0.20 |
| 10 | -0.99 |
| 20 | -2.61 |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observação importante:&lt;br&gt;&lt;br&gt;
 a função começa a produzir valores negativos após algumas tentativas, porque o logaritmo continua crescendo.&lt;/p&gt;

&lt;p&gt;Para evitar isso em cenários reais (retry/backoff/cooldown), normalmente usa-se um piso mínimo:&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="n"&gt;Intervalo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Minimo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Initial&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tentativa&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exemplo de Uso em Python
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogarithmicWait&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;__init__&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;30.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;initial_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;floor_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;acceleration_point&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Initializes the logarithmic waiter.
        :param timeout: Maximum time to wait in seconds.
        :param initial_interval: Starting delay between polls.
        :param floor_interval: Minimum delay between polls (maximum speed).
        :param acceleration_point: How many attempts until we reach the floor_interval.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial_interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initial_interval&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;floor_interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;floor_interval&lt;/span&gt;

        &lt;span class="c1"&gt;# Calculate the decay constant based on the desired acceleration curve
&lt;/span&gt;        &lt;span class="c1"&gt;# (Initial - Floor) / log(N + 1)
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_interval&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;floor_interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acceleration_point&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[[],&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        Polls the condition function until it returns True.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

            &lt;span class="c1"&gt;# Decay logic: interval decreases as 'attempt' increases
&lt;/span&gt;            &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;floor_interval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial_interval&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusão: Benefícios e Limitações
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Onde ela tem mais sucesso?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Processos Assíncronos Longos:&lt;/strong&gt; Geração de PDFs pesados, processamento de vídeos, backups, ou provisionamento de infraestrutura em nuvem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testes de CI/CD em Escala:&lt;/strong&gt; Em pipelines com milhares de testes parallelism, a economia de recursos nos primeiros segundos de cada teste pode reduzir drasticamente o custo e a carga da infraestrutura de teste.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Benefícios
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feedback Snappy:&lt;/strong&gt; O teste termina quase imediatamente após o sucesso real, eliminando o “tempo morto” do polling fixo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carga Eficiente:&lt;/strong&gt; Não bombardeia o sistema desnecessariamente no início.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Limitações
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eventos Rápidos:&lt;/strong&gt; Para elementos de UI que aparecem em menos de 1 segundo, esta abordagem é desnecessariamente complexa; a espera fixa tradicional do Selenium/Playwright é melhor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexidade de Configuração:&lt;/strong&gt; Requer que o QA entenda a natureza do processo para configurar bem o &lt;em&gt;Initial&lt;/em&gt; e o &lt;em&gt;Floor&lt;/em&gt;. Se o &lt;em&gt;Initial&lt;/em&gt; for muito alto, você pode perder tempo no começo de um evento que poderia ter sido rápido.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Espera Logarítmica não é uma bala de prata, mas é uma ferramenta de engenharia refinada para QAs que buscam otimização de alto nível e precisão em cenários complexos.&lt;/p&gt;

&lt;p&gt;Powered by Claude e Gemini&lt;/p&gt;

</description>
      <category>softwaretesting</category>
      <category>waitstrategies</category>
      <category>python</category>
    </item>
    <item>
      <title>“Me ajude a te ajudar”: Usando o gist</title>
      <dc:creator>Lucas Amaral</dc:creator>
      <pubDate>Wed, 20 May 2020 19:23:37 +0000</pubDate>
      <link>https://dev.to/lopesdoamaral/me-ajude-a-te-ajudar-usando-o-gist-iej</link>
      <guid>https://dev.to/lopesdoamaral/me-ajude-a-te-ajudar-usando-o-gist-iej</guid>
      <description>&lt;p&gt;Para quem está iniciando ou mesmo pessoas experientes em desenvolvimento de software, mais cedo ou mais tarde, você precisará compartilhar trechos do seu código com alguém. Por que? Seja para exemplificar uma solução legal, seja para tirar uma dúvida com a comunidade ou compartilhar uma informação em formato de texto qualquer.&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://help.github.com/pt/github/writing-on-github/editing-and-sharing-content-with-gists" rel="noopener noreferrer"&gt;&lt;strong&gt;gist&lt;/strong&gt;&lt;/a&gt; é uma ferramenta do GitHub feita para esses compartilhamentos ou nas palavras do GitHub: Compartilhar código, notas ou trechos de código instantaneamente. Ainda com as mesmas capacidades de um repositório normal de receber forks, comentários, etc…&lt;/p&gt;

&lt;p&gt;Para acessar seus gists, basta estar logado na sua conta do GitHub e no dropdown onde tem a sua foto de perfil e selecionar “Seus gists” (Your gists)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf676klirc8kdczkm536.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf676klirc8kdczkm536.png" width="797" height="359"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Listando os seus gists&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Não tem nenhum ou nunca usou? Sem problemas. Vamos criar nosso primeiro gist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando um gist
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foe4mf0w3r44rteauqf8p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foe4mf0w3r44rteauqf8p.png" width="800" height="222"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Criando um novo gist&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Um gist é composto de uma descrição, arquivos com nome (e extensão, importante para receber um highlight em palavras reservados) e corpo. E se é público ou secreto (nessa segunda opção, todos que tiverem o link terão acesso).&lt;/p&gt;

&lt;p&gt;Vamos usar um problema de automação de testes usando Ruby, RSpec e Cucumber para exemplificar nosso primeiro gist. Iniciaremos postando nosso arquivo de Steps, para alguém ver o que pode estar dando errado. Ao final, o gist será criado e o link disponível para compartilhamento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7x2ewlzgytu1lg6kysm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7x2ewlzgytu1lg6kysm.png" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Acrescentando arquivos a um mesmo gist
&lt;/h3&gt;

&lt;p&gt;Com frequência, você precisa exibir mais de um trecho de código ou arquivo para compartilhar o cenário completo para a análise de terceiros. No nosso cenário, vamos incluir o arquivo .feature . Basta editar o seu gist selecionando a opção “Adicionar arquivo”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12kbwzybkikkg5ba6prj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12kbwzybkikkg5ba6prj.png" width="798" height="184"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Adicionando arquivo&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Seguindo os mesmos passos anteriores, adicionamos o novo arquivo, o que dará a seguinte cara para nosso gist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3k5r9003ya6ylss2d7tl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3k5r9003ya6ylss2d7tl.png" width="800" height="461"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;gist com um segundo arquivo&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para finalizar o cenário, vamos adicionar ao gist nosso Gemfile assim nossos colegas podem ter uma visão mais apurada de como está rodando nossa aplicação.&lt;/p&gt;

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

&lt;p&gt;Use o gist para ajudar aos outros colegas, instrutores e até o StackOverflow a ajudarem você. &lt;a href="https://gist.github.com/doamaral/ffd7a9cf31e51c56ff67021b30879389" rel="noopener noreferrer"&gt;Acesse esse link&lt;/a&gt; para visualizar como ficou nosso gist no final.&lt;/p&gt;

</description>
      <category>qualityassurance</category>
      <category>gist</category>
      <category>tools</category>
      <category>code</category>
    </item>
    <item>
      <title>Estou cansado de encontrar bugs</title>
      <dc:creator>Lucas Amaral</dc:creator>
      <pubDate>Wed, 30 Oct 2019 19:33:15 +0000</pubDate>
      <link>https://dev.to/lopesdoamaral/estou-cansado-de-encontrar-bugs-1glm</link>
      <guid>https://dev.to/lopesdoamaral/estou-cansado-de-encontrar-bugs-1glm</guid>
      <description>&lt;p&gt;Este texto é uma tradução livre do &lt;a href="https://angryweasel.com/Articles/TiredOfBugs.pdf" rel="noopener noreferrer"&gt;artigo original&lt;/a&gt; “I’m Tired of Finding Bugs” de &lt;a href="https://angryweasel.com/blog/about-alan/" rel="noopener noreferrer"&gt;Alan Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7mrl2y49q159nlmu3tz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7mrl2y49q159nlmu3tz.png" width="569" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Venho atuando na área de testes de software por mais de 13 anos e estou cansado de encontrar bugs. Não é que eu considere que encontrar bugs não tem importância — Eu prefiro muito mais encontrar antes que o cliente o faça. Certamente, também, não estou cansado de testar, no entanto, o objetivo de testar não é encontrar bugs. O testador é responsável por exercitar a aplicação, o produto, reportar informações e muitas outras atividades. Encontrar bugs é um efeito colateral.&lt;/p&gt;

&lt;p&gt;Estou cansado de testadores encontrarem muitos defeitos que deveriam ter sido encontrados muito mais cedo, ou mesmo nem ser introduzidos na aplicação. Nós encontramos muitas &lt;em&gt;issues&lt;/em&gt; muito tarde no ciclo de vida do produto e deixamos com que muitos bugs cheguem até o usuário final. Eu não quero mais encontrar bugs, quero preveni-los de acontecer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Eu não quero mais encontrar bugs, quero preveni-los de acontecer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Leio muito sobre testes de software, mas livros, blogs, artigos e outros materiais parecem focar primordialmente em abordagens para encontrar bugs. Técnicas populares como testes exploratórios ou suposição de erros (error-guessing), podem ser ferramentas efetivas, mas seu foco é em “Encontrar”. Estas e outras abordagens que primariamente pretendem descobrir erros que já estão no código estão tentando alcançar qualidade através de testes. Em outras palavras, tentam “testar a qualidade de um produto.”&lt;/p&gt;

&lt;p&gt;Quase todos os livros de engenharia de software tem um gráfico que demonstra como o custo de corrigir erros aumenta quanto mais tarde o erro demora a ser encontrado no ciclo de desenvolvimento do software. Se todos concordam com isso, por que não estamos fazendo mais para encontrar bugs mais cedo? Muitas equipes de engenharia estão começando a envolver testes (e testers) mais cedo no ciclo de desenvolvimento, e acredito que esse seja um bom movimento. Já ouvi os gritos de “vamos direcionar/empurrar a qualidade para cima” (“Let’s drive quality upstream!”) por anos, mas continuo achando que não estamos próximo o suficiente.&lt;/p&gt;

&lt;p&gt;Como podemos alcançar níveis mais altos de qualidade e encontrar menos bugs nos estágios mais avançados do desenvolvimento? A maioria dos esforços para “direcionar a qualidade para cima” envolvem a revisão de especificações pelos testers a fim de criar casos de testes ou modelos a partir das especificações ou protótipos iniciais. Estas são abordagens, certamente melhores que esperar o código ser “jogado por cima do muro” para o time de testes. No entanto uma solução consideravelmente melhor seria prevenir que os bugs aconteçam. Com o crescimento da complexidade dos softwares, alguns bugs são inevitáveis — mas a maioria é evitável.&lt;/p&gt;

&lt;p&gt;Bugs existem porque alguém cometeu um erro: A pessoa escrevendo os requisitos pode ter esquecido um detalhe, um desenvolvedor pode ter cometido um erro de escrita ou uma chamada errada a uma biblioteca pode ter sido feita. Erros humanos podem ser prevenidos? Certamente sim. Shigeo Shingo, um engenheiro industrial japonês inventou o conceito de Poka-yoke (“evitando erros inadvertidos”). Em uma planta industrial, poka-yoke pode ser implementado introduzindo uma sinalização em uma peça que corresponda unicamente a outra de encaixe, de tal forma que se evite consumo de tempo com posicionamento ou encaixes errados.&lt;/p&gt;

&lt;p&gt;Todos os dias, eu encontre dúzias de sistemas aplicados para prevenir erros humanos. O fusível de um equipamento elétrico previne que haja uma sobrecarga no meu equipamento e se inicie um incêndio. A pia do banheiro possui um pequeno buraco para evitar a água de transbordar. Meu exemplo favorito é o meu novo carro que não tranca se a chave estiver dentro.&lt;/p&gt;

&lt;p&gt;Técnicas de prevenção são, da mesma forma, aplicáveis a software. Certa vez trabalhei em um projeto no qual registrei uma porção de erros em vários componentes que usavam uma função de uma biblioteca incorretamente. O erro era fácil de acontecer e não provocava uma bug trivial, mas causava um &lt;em&gt;memory leak&lt;/em&gt; que ocasionava um erro de performance considerável. Após detectar o problema, escrevi um script para verificar todas as ocorrências do mesmo erro no código fonte. Uma vez que esses bugs foram documentados, adicionei esse script a uma lista de verificações a serem feitas quando um desenvolvedor adiciona código à aplicação. Se não evitei a primeira ocorrência desse bug, por outro lado, com o script, demos um jeito desse bug nunca mais voltar a aparecer na aplicação. Mais adiante, por causa das verificações realizadas, os desenvolvedores aprenderam a usar corretamente a função da biblioteca.&lt;/p&gt;

&lt;p&gt;Após o sucesso dessa iniciativa, sempre que encontrávamos um bug que poderia ser detectado automaticamente através de códigos, escrevíamos uma rotina e transformávamos a detecção em uma prevenção adicionado essa rotina à lista de verificações. Quando o produto foi lançado, existiam dezenas de scripts de verificação prevenindo centenas de bugs.&lt;/p&gt;

&lt;p&gt;Técnicas de prevenção não precisam ser ferramentas. Recentemente estava trabalhando em um projeto no qual havia uma quantidade relevante de erros relacionados a projeto/arquitetura num time de uma área específica. Não conseguiria eliminar os erros através de uma detecção automática, no entanto, estava convencido de que uma revisão de código informal teria percebido estes erros. Mostrei os erros ao gerente da área e ele concordou com minha avaliação. Logo depois ele iniciou a requerer revisão de código para todas as novas alterações de projeto. Após isso, vi pouquíssimos erros de projeto daquele time. Melhor ainda, outros erros que eu não teria encontrado também foram prevenidos.&lt;/p&gt;

&lt;p&gt;Prevenção de defeitos definitivamente exige investigação da causa raiz do bug. Existem muitas formas de determinar a origem de um incidente, no entanto tive um grande sucesso usando uma estratégia muito mais simplificada de análise. A melhor parte da minha técnica é agir como uma criança de 3 anos de idade, perguntando tantos “Porquês” quantos forem necessários para chegar ao ponto no qual posso aplicar a técnica de prevenção: Por que esse bug aconteceu? Por que essa função em particular foi usada? Por que foi possível que essa função fosse usada incorretamente? Por que esse erro não foi pego no Code Review? Posso garantir que essas perguntas irão desvendar uma técnica de prevenção para cada bug, e cada técnica de prevenção que você encontrar e implementar reduzirá significantemente os erros que você irá encontrar em momentos posteriores.&lt;/p&gt;

&lt;p&gt;Software continuará a ter bug nos anos vindouros. Posso aceitar esse fato, mas não posso aceitar o grande número de bugs que permitimos — e esperamos — que os testadores encontrem. Se queremos levar Qualidade a sério, é tempo de nos cansarmos de encontrar bugs e começar a preveni-los de acontecer em primeiro lugar.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>softwarequalityengin</category>
      <category>qualityassurance</category>
      <category>qa</category>
    </item>
  </channel>
</rss>
