Ferramentas & Produtividade

Testes Automatizados: Do Básico ao Avançado

7 min de leitura

Testes Automatizados: Do Básico ao Avançado

Fundamentos de Testes Automatizados Os testes automatizados são a espinha dorsal do desenvolvimento moderno. Enquanto testes manuais consomem tempo e são propensos a erros humanos, os testes automatizados executam verificações repetitivas com precisão, permitindo que você implante código com confiança. A pirâmide de testes apresenta três níveis: testes unitários (base), testes de integração (meio) e testes end-to-end (topo). Comece pelos unitários — são rápidos, isolados e testam uma única unidade de código. Vamos implementar um teste unitário básico em Python usando . Considere uma função que calcula o preço final com desconto: Execute com . Cada teste é isolado, testando um comportamento específico. Isso garante que refatorações futuras não quebrem funcionalidades esperadas. Testes de Integração e Mocks Testes de integração verificam como múltiplos componentes trabalham juntos. Aqui entra em jogo o uso de mocks — objetos simulados que substituem dependências externas como APIs, bancos de dados ou serviços. Isso permite testar lógica sem depender de sistemas externos. Considere uma aplicação

<h2>Fundamentos de Testes Automatizados</h2>

<p>Os testes automatizados são a espinha dorsal do desenvolvimento moderno. Enquanto testes manuais consomem tempo e são propensos a erros humanos, os testes automatizados executam verificações repetitivas com precisão, permitindo que você implante código com confiança. A pirâmide de testes apresenta três níveis: testes unitários (base), testes de integração (meio) e testes end-to-end (topo). Comece pelos unitários — são rápidos, isolados e testam uma única unidade de código.</p>

<p>Vamos implementar um teste unitário básico em Python usando <code>pytest</code>. Considere uma função que calcula o preço final com desconto:</p>

<pre><code class="language-python">def aplicar_desconto(preco, percentual_desconto):

if percentual_desconto &lt; 0 or percentual_desconto &gt; 100:

raise ValueError(&quot;Desconto deve estar entre 0 e 100&quot;)

return preco * (1 - percentual_desconto / 100)

Teste unitário

def test_aplicar_desconto_valido():

assert aplicar_desconto(100, 10) == 90.0

assert aplicar_desconto(50, 50) == 25.0

def test_aplicar_desconto_invalido():

with pytest.raises(ValueError):

aplicar_desconto(100, 150)</code></pre>

<p>Execute com <code>pytest nome_arquivo.py</code>. Cada teste é isolado, testando um comportamento específico. Isso garante que refatorações futuras não quebrem funcionalidades esperadas.</p>

<h2>Testes de Integração e Mocks</h2>

<p>Testes de integração verificam como múltiplos componentes trabalham juntos. Aqui entra em jogo o uso de <strong>mocks</strong> — objetos simulados que substituem dependências externas como APIs, bancos de dados ou serviços. Isso permite testar lógica sem depender de sistemas externos.</p>

<p>Considere uma aplicação que busca dados de um usuário em uma API:</p>

<pre><code class="language-python">from unittest.mock import patch, MagicMock

import requests

def buscar_usuario(user_id):

response = requests.get(f&quot;https://api.example.com/users/{user_id}&quot;)

if response.status_code == 200:

return response.json()

raise Exception(&quot;Usuário não encontrado&quot;)

@patch(&#039;requests.get&#039;)

def test_buscar_usuario_sucesso(mock_get):

mock_get.return_value = MagicMock(status_code=200)

mock_get.return_value.json.return_value = {&quot;id&quot;: 1, &quot;nome&quot;: &quot;João&quot;}

resultado = buscar_usuario(1)

assert resultado[&quot;nome&quot;] == &quot;João&quot;

mock_get.assert_called_once_with(&quot;https://api.example.com/users/1&quot;)

@patch(&#039;requests.get&#039;)

def test_buscar_usuario_erro(mock_get):

mock_get.return_value = MagicMock(status_code=404)

with pytest.raises(Exception):

buscar_usuario(1)</code></pre>

<p>O decorator <code>@patch</code> substitui a função real por um mock. Você controla o comportamento e verifica se as chamadas ocorreram corretamente. Isso torna testes rápidos e confiáveis, sem dependências externas.</p>

<h2>Testes End-to-End e Automação de Interface</h2>

<p>Testes end-to-end (E2E) simulam a jornada real do usuário, testando a aplicação completa do navegador até o banco de dados. <strong>Selenium</strong> e <strong>Playwright</strong> são frameworks populares para essa automação. Eles controlam navegadores reais, clicam em elementos e verificam resultados.</p>

<p>Aqui está um exemplo com Playwright em Python:</p>

<pre><code class="language-python">from playwright.sync_api import sync_playwright

def test_login_usuario():

with sync_playwright() as p:

browser = p.chromium.launch()

page = browser.new_page()

Navegar até a aplicação

page.goto(&quot;https://exemplo.com/login&quot;)

Preencher formulário

page.fill(&quot;input[name=&#039;email&#039;]&quot;, &quot;usuario@example.com&quot;)

page.fill(&quot;input[name=&#039;senha&#039;]&quot;, &quot;senha123&quot;)

page.click(&quot;button:has-text(&#039;Entrar&#039;)&quot;)

Aguardar redirecionamento e verificar

page.wait_for_url(&quot;https://exemplo.com/dashboard&quot;)

assert page.is_visible(&quot;h1:has-text(&#039;Dashboard&#039;)&quot;)

browser.close()</code></pre>

<p>Testes E2E são lentos e frágeis se não bem estruturados — use-os para fluxos críticos. <strong>Dica profissional</strong>: mantenha seletores CSS descritivos e evite esperas fixas (use <code>wait_for_*</code> ao invés de <code>time.sleep()</code>).</p>

<h2>Boas Práticas e Estratégias Avançadas</h2>

<h3>Cobertura de Testes e Métricas</h3>

<p>A cobertura de testes indica qual percentual do código é executado durante testes. Use <code>coverage</code> em Python para medir:</p>

<pre><code class="language-bash">pip install coverage

coverage run -m pytest

coverage report

coverage html # Gera relatório HTML detalhado</code></pre>

<p>Busque <strong>80-90% de cobertura</strong> em código crítico, não 100% — é overkill e caro. Foque em lógica de negócio complexa.</p>

<h3>Estrutura AAA e Nomenclatura Clara</h3>

<p>Organize seus testes com a estrutura <strong>Arrange-Act-Assert</strong>:</p>

<pre><code class="language-python">def test_carrinho_adiciona_produto():

Arrange: preparar dados

carrinho = Carrinho()

produto = Produto(&quot;Notebook&quot;, 3000)

Act: executar ação

carrinho.adicionar(produto)

Assert: verificar resultado

assert len(carrinho.itens) == 1

assert carrinho.total == 3000</code></pre>

<p>Nomeie testes descritivamente: <code>test_[o_que_esta_sendo_testado]_[condicao]_[resultado_esperado]</code>.</p>

<h3>Testes Parametrizados</h3>

<p>Evite repetição usando parametrização:</p>

<pre><code class="language-python">import pytest

@pytest.mark.parametrize(&quot;entrada,esperado&quot;, [

(2, 4),

(3, 9),

(-1, 1),

])

def test_quadrado(entrada, esperado):

assert entrada ** 2 == esperado</code></pre>

<p>Um teste, múltiplos cenários. Isso torna suites de testes mais concisas e eficientes.</p>

<h2>Conclusão</h2>

<p>Testes automatizados são investimento essencial em qualidade e velocidade. <strong>Comece com testes unitários</strong> para lógica isolada, use <strong>mocks para integração</strong> sem dependências externas, e implemente <strong>E2E para fluxos críticos</strong>. Mantenha testes simples, legíveis e rápidos — uma suite lenta é um bloqueio ao desenvolvimento. Com disciplina, seus testes se tornarão documentação viva do comportamento esperado do sistema, permitindo refatorar com segurança e entregar valor continuamente.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://docs.pytest.org/" target="_blank" rel="noopener noreferrer">Pytest Documentation</a> — Documentação oficial do framework pytest</li>

<li><a href="https://docs.python.org/3/library/unittest.mock.html" target="_blank" rel="noopener noreferrer">Unittest Mock — Python Docs</a> — Guia completo de mocks em Python</li>

<li><a href="https://playwright.dev/python/" target="_blank" rel="noopener noreferrer">Playwright Documentation</a> — Framework para automação E2E</li>

<li><a href="https://testing-library.com/docs/" target="_blank" rel="noopener noreferrer">Testing Library Best Practices</a> — Princípios modernos de teste</li>

<li><a href="https://www.amazon.com.br/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627" target="_blank" rel="noopener noreferrer">Growing Object-Oriented Software, Guided by Tests</a> — Livro essencial sobre TDD</li>

</ul>

Comentários

Mais em Ferramentas & Produtividade

Como Usar Docker e Kubernetes em Produção
Como Usar Docker e Kubernetes em Produção

Docker em Produção: Containerização Eficiente Docker é essencial para qualque...

Dominando Segurança em APIs em Projetos Reais
Dominando Segurança em APIs em Projetos Reais

Autenticação e Autorização: O Primeiro Pilar A segurança de uma API começa co...

PowerShell Profile com Nerd Fonts e ANSI — Do Zero ao Terminal que Impressiona
PowerShell Profile com Nerd Fonts e ANSI — Do Zero ao Terminal que Impressiona

Crie um terminal PowerShell com Nerd Fonts, cores ANSI e prompt personalizado...