Tipos de teste de caixa branca, Teste de caixa preta
Os testes de software são fundamentais para garantir a qualidade, segurança e desempenho das aplicações. Dentre os tipos mais conhecidos, destacam-se os testes de caixa branca e caixa preta, cada um com sua abordagem, objetivos e técnicas específicas. Neste artigo, vamos entender as diferenças entre eles e explorar exemplos práticos com a linguagem Java para facilitar a compreensão.
O que é Teste de Caixa Branca?
O teste de caixa branca (ou teste estrutural) é aquele em que o testador tem acesso ao código-fonte da aplicação. A ideia é verificar o funcionamento interno do sistema, testando estruturas lógicas, caminhos de decisão, laços e fluxos de dados.
🔍 Técnicas comuns:
Cobertura de instrução: verificar se todas as linhas de código foram executadas.
Cobertura de decisão: testar todas as estruturas de decisão (
if
,switch
,while
, etc).Cobertura de caminho: explorar todos os fluxos possíveis de execução.
Exemplo prático em Java:
public class ClassificadorIdade {
public static String classificar(int idade) {
if (idade < 12) {
return "Criança";
} else if (idade < 18) {
return "Adolescente";
} else {
return "Adulto";
}
}
}
No teste de caixa branca, você analisaria o código-fonte diretamente e criaria testes que percorrem todos os caminhos:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ClassificadorIdadeTest {
@Test
public void testCrianca() {
assertEquals("Criança", ClassificadorIdade.classificar(10));
}
@Test
public void testAdolescente() {
assertEquals("Adolescente", ClassificadorIdade.classificar(15));
}
@Test
public void testAdulto() {
assertEquals("Adulto", ClassificadorIdade.classificar(20));
}
}
Esse conjunto garante 100% de cobertura de decisão e instrução para esse método.
O que é Teste de Caixa Preta?
O teste de caixa preta ignora a implementação interna. O foco está nos requisitos funcionais: o sistema retorna as respostas corretas dadas certas entradas?
🔍 Técnicas comuns:
Partição de equivalência
Análise de valor-limite
Tabela de decisão
Casos de uso
✅ Exemplo prático em Java:
Sem conhecer o código, o testador sabe que:
Se a idade for menor que 12 → deve retornar
"Criança"
.Se a idade for entre 12 e 17 →
"Adolescente"
.A partir de 18 →
"Adulto"
.
Cria-se testes com foco nas entradas e saídas esperadas:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CaixaPretaTest {
@Test
public void testLimiteInferior() {
assertEquals("Criança", ClassificadorIdade.classificar(0));
}
@Test
public void testLimiteTransicaoParaAdolescente() {
assertEquals("Adolescente", ClassificadorIdade.classificar(12));
}
@Test
public void testLimiteTransicaoParaAdulto() {
assertEquals("Adulto", ClassificadorIdade.classificar(18));
}
@Test
public void testEntradaInvalida() {
assertThrows(IllegalArgumentException.class, () -> {
ClassificadorIdade.classificar(-5);
});
}
}
Para esse último teste, seria necessário adaptar o método para lançar uma exceção caso a idade seja negativa.
Comparativo entre Caixa Branca e Caixa Preta
Visibilidade do código
Requer acesso ao código-fonte
Não requer acesso ao código
Foco
Lógica e estrutura interna
Funcionalidade e requisitos
Quem realiza?
Desenvolvedores ou testadores técnicos
Testadores, QA ou analistas
Exemplos de ferramenta
JUnit com cobertura de código
JUnit, Selenium, Postman, etc.
Gráficos de Cobertura de Testes
O que é a cobertura de testes?
A cobertura de testes indica quantas partes do código foram realmente testadas. Em Java, ferramentas como JaCoCo, Cobertura ou EclEmma (Eclipse) geram relatórios visuais após a execução dos testes unitários.
Exemplo de cobertura com JaCoCo:
Suponha que temos a seguinte classe:
public class Calculadora {
public int somar(int a, int b) {
return a + b;
}
public int dividir(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Divisão por zero");
}
return a / b;
}
}
E os testes:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CalculadoraTest {
@Test
public void testSoma() {
Calculadora calc = new Calculadora();
assertEquals(5, calc.somar(2, 3));
}
@Test
public void testDivisao() {
Calculadora calc = new Calculadora();
assertEquals(2, calc.dividir(10, 5));
}
}
Cobertura gerada (exemplo visual de um relatório JaCoCo):
EditarMétodo | Cobertura de Instruções | Cobertura de Ramos
---------------------|-------------------------|---------------------
somar(int, int) | 100% | n/a
dividir(int, int) | 85% | 50%
Observação: O método dividir
não teve a exceção testada! Logo, falta testar b == 0
.
Exemplo de Código com Erros Intencionais
A seguir, um exemplo de código com problemas lógicos e estruturais para fins didáticos. A proposta é que os estudantes identifiquem os erros usando teste de caixa branca.
public class VerificadorParidade {
public String verificar(int numero) {
if (numero % 2 == 0) {
return "Ímpar"; // ❌ ERRO: deve retornar "Par"
} else if (numero % 2 == 1) {
return "Ímpar";
} else {
return "Desconhecido"; // ❌ nunca será alcançado
}
}
}
Erros intencionais:
Lógica invertida no
if
(retorna"Ímpar"
quando é par).Condição
else if (numero % 2 == 1)
é redundante — oelse
já cobriria esse caso.O
else final
é morto, nunca será atingido (código morto).
Como testar:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class VerificadorParidadeTest {
@Test
public void testNumeroPar() {
assertEquals("Par", new VerificadorParidade().verificar(4)); // este teste irá falhar
}
@Test
public void testNumeroImpar() {
assertEquals("Ímpar", new VerificadorParidade().verificar(5));
}
}
Esse exercício ajuda a diagnosticar erros de lógica que muitas vezes passam despercebidos em revisões manuais.
Last updated