A diferença cabe em uma frase: o teste de caixa preta olha para o software de fora, sem ver o código, e verifica o que ele faz; o teste de caixa branca olha de dentro, com o código à vista, e verifica como ele faz. O primeiro pergunta se o resultado está correto. O segundo pergunta se cada caminho do programa foi executado. Não são rivais nem etapas: são dois ângulos do mesmo objeto, e quem usa apenas um fica com metade do mapa de risco.
O nome vem de uma imagem simples. Uma caixa preta é opaca: você coloca uma entrada, sai uma saída, e não vê o que acontece dentro. Uma caixa branca (ou de vidro) é transparente: você vê os fios, os ramos, os laços. Essa metáfora decide que informação o testador usa para desenhar seus casos, e por isso cada abordagem captura falhas que a outra deixa passar. Este artigo separa as duas, mostra as técnicas concretas de cada uma e explica por que um plano de testes sério as combina de propósito.
01 · de foraCaixa preta: testar o que faz, sem ver o código
Em um teste de caixa preta o testador trata o sistema como uma caixa opaca. Ele só conhece a especificação: o que deveria receber e o que deveria devolver. Desenha seus casos a partir dos requisitos, não do código, e por isso podem ser escritos por alguém que não sabe programar, ou antes mesmo de o código existir. A norma ISO/IEC/IEEE 29119-4, dedicada a técnicas de teste, agrupa estas como técnicas baseadas na especificação [2].
Seu valor é que verifica o comportamento tal como o usuário o vive, sem se enviesar por como está construído por dentro. Seu limite é o espelho do mesmo fato: como não vê o código, não sabe quais partes ficaram sem executar. Pode passar em todos os seus casos e ainda deixar ramos inteiros do programa sem tocar.
A caixa preta não sabe como o software foi feito. E é justamente por isso que encontra o que o programador deu por óbvio.
As técnicas clássicas de caixa preta, todas descritas no programa do ISTQB [1], são estas:
- Particionamento de equivalência: agrupar as entradas em classes que o sistema deveria tratar do mesmo modo, e testar um representante de cada classe em vez de todos os valores. Se um campo aceita idades de 18 a 65, testar "um valor válido", "um abaixo" e "um acima" cobre as três classes sem testar os cem números.
- Análise de valores limite: os erros se escondem nas bordas. Se a faixa válida é 18 a 65, testam-se 17, 18, 65 e 66, porque é ali que um "menor que" escrito por engano no lugar de "menor ou igual" se denuncia.
- Tabela de decisão: quando o resultado depende de várias condições combinadas (por exemplo cliente novo, com cupom e valor acima de certo limiar), listam-se todas as combinações e sua saída esperada, para não esquecer nenhuma regra de negócio.
- Transição de estados: útil quando o sistema se comporta conforme o estado em que está (um pedido passa de "criado" a "pago" a "enviado"). Testam-se as transições válidas e, sobretudo, as proibidas.
02 · de dentroCaixa branca: testar como faz, com o código à vista
Em um teste de caixa branca o testador de fato conhece o código. Desenha os casos para percorrer sua estrutura interna: cada instrução, cada ramo de um "se/então", cada condição dentro desses ramos. O objetivo não é apenas que o resultado esteja correto, mas que nenhuma parte do programa fique sem executar durante os testes. O ISTQB as chama de técnicas baseadas na estrutura [1], e a ISO/IEC/IEEE 29119-4 as cataloga como técnicas de teste estruturais [2].
A medida que sai daqui é a cobertura: que porcentagem da estrutura seus testes tocaram. Há vários níveis, e são mais exigentes à medida que você desce:
- Cobertura de instruções: que cada linha de código tenha sido executada ao menos uma vez. É o nível mais básico e o mais enganoso, porque uma linha executada não significa que se testou cada decisão ao redor dela.
- Cobertura de ramos (ou decisões): que cada bifurcação tenha sido tomada nos dois sentidos, o verdadeiro e o falso. Um "se o saldo é suficiente" só está coberto quando você testou tanto o caso em que é quanto o caso em que não é.
- Cobertura de condições e de rotas: níveis mais finos que exigem exercitar cada condição booleana individual, ou cada caminho completo do começo ao fim. São potentes e custosos: o número de rotas cresce rápido a cada laço e a cada condição aninhada.
Alcançar cobertura total de instruções só garante que cada linha rodou, não que fez o certo. Um teste pode executar uma linha e não verificar nada do seu resultado. A cobertura mede quanto código você tocou, não quanto você verificou. É um indicador de lacuna (o que não está coberto é risco certo), não um certificado de ausência de erros.
A caixa branca não pergunta se o software serve ao usuário. Pergunta se seus testes de fato percorreram o programa.
Por isso a caixa branca vive sobretudo nos testes unitários, onde o programador testa seu próprio código com a estrutura à frente. Ali uma ferramenta de cobertura lhe diz, linha por linha, quais ramos ficaram sem executar, e esses ramos órfãos costumam ser justamente onde se esconde a falha que ninguém pensou em testar.
03 · juntasPor que se complementam e não se escolhem
A tentação é perguntar qual é melhor. É a pergunta errada, porque cada abordagem é cega justamente onde a outra enxerga. A caixa preta confirma que o sistema faz o que o usuário espera, mas não lhe diz que código ficou sem testar. A caixa branca confirma que você percorreu o programa, mas não lhe diz se o que ele faz faz sentido para o negócio: você pode ter 100 % de cobertura de um cálculo de imposto que está mal especificado desde o requisito.
O exemplo esclarece. Imagine uma função que aprova um empréstimo. Com a caixa preta você testa combinações de renda, dívida e idade, e verifica que a decisão final seja a correta segundo a política. Com a caixa branca você abre o código e descobre um ramo que só é ativado quando a dívida é exatamente zero, um caso que suas partições de equivalência nunca priorizaram. Nenhuma das duas abordagens, sozinha, cobre as duas lacunas. Juntas, sim.
A forma sadia de combiná-las é por níveis da pirâmide de testes. Nos testes unitários, onde o programador tem o código à frente, domina a caixa branca guiada por cobertura. Nos testes de sistema e de aceitação, onde importa o comportamento visível, domina a caixa preta guiada pelos requisitos. Existe ainda um meio-termo, a caixa cinza, onde o testador conhece algo da estrutura interna (o esquema do banco de dados, uma API) sem chegar ao detalhe do código, e o usa para desenhar melhores casos de caixa preta.
O ISTQB mantém essa classificação justamente para que um plano de testes cubra ambos os ângulos de forma deliberada e não por acidente, e a ISO/IEC/IEEE 29119-4 padroniza as técnicas concretas de cada família para que "testamos bem" deixe de ser uma opinião e passe a ser algo demonstrável [1][2]. A lição prática é uma: não pergunte qual usar, pergunte quanto de cada um este nível de teste precisa. A caixa preta lhe diz se o software serve; a caixa branca, se seus testes de fato o percorreram. O risco vive na lacuna entre as duas.
Fontes
- ISTQB, Certified Tester Foundation Level (CTFL) Syllabus, International Software Testing Qualifications Board. Descreve as técnicas baseadas na especificação (caixa preta: particionamento de equivalência, valores limite, tabela de decisão, transição de estados) e as técnicas baseadas na estrutura (caixa branca: cobertura de instruções e de ramos/decisões).
- ISO/IEC/IEEE 29119-4, Software and systems engineering. Software testing. Part 4: Test techniques. Organização Internacional de Normalização (ISO). Padroniza as técnicas de teste baseadas na especificação, baseadas na estrutura e baseadas na experiência.
- Myers, G. J., Sandler, C. & Badgett, T. (2011). The Art of Software Testing, 3.ª edição. John Wiley & Sons. Obra de referência que introduz os testes de caixa preta e de caixa branca e suas técnicas de desenho de casos.
- ISO/IEC 25010, Systems and software Quality Requirements and Evaluation (SQuaRE). System and software quality models. Organização Internacional de Normalização (ISO). Modelo de qualidade de produto sobre o qual ambas as abordagens de teste fornecem evidência (adequação funcional e demais características).