O que é teste de unidade de caixa preta?

11

Recentemente, fiz meu exame final para um curso de engenharia de software para o meu programa de mestrado e uma das perguntas do exame foi a seguinte:

Unit Testing is considered:
a. White-box Testing
b. Black-box Testing
c. Either

Nos meus 7 anos de experiência em desenvolvimento de software, o teste de unidade sempre adotou uma abordagem de caixa branca. O testador sempre teve pleno conhecimento da implementação da unidade enquanto escrevia os testes. O teste da caixa preta sempre vinha mais tarde nas formas de integração, sistema e teste de aceitação.

No entanto, a resposta correta para o exame (de acordo com o professor) é que o teste de unidade pode ser um teste de caixa branca ou preta.

Eu fiz algumas pesquisas e parece que muitos casos "teste de unidade de caixa preta" são usados ​​para descrever uma abordagem de teste em que os testes de unidade são escritos antes do código. No entanto, na minha opinião, isso ainda é teste de caixa branca. Embora a implementação ainda não exista, quem está escrevendo o teste geralmente tem uma boa idéia de como o código-fonte será implementado.

Alguém pode me explicar como o teste de unidade de caixa preta funciona (se é realmente uma coisa) e como ele difere do teste de unidade de caixa branca?

backcab
fonte
4
como o professor esclareceu isso quando você perguntou sobre isso? (ver também Por que perguntas da entrevista fazem pobres perguntas Software Engineering.SE? )
mosquito
"quem está escrevendo o teste geralmente tem uma boa idéia de como o teste será implementado" - não se trata de saber como o teste é implementado, mas se você sabe (em branco) ou não (em preto) como a coisa você está testando está implementado.
Jesper
@Jesper desculpe. Eu quis dizer "como o código fonte será implementado". Eu o corrigi na pergunta.
backcab
2
While the implementation does not yet exist, whoever is writing the test generally has a pretty good idea about how the source code is going to be implemented.- Sim, mas o teste em si não. Teste de caixa branca significa testar algo interno ao método ou classe, como o valor de uma variável. Isso não significa que o criador do teste sabe como é o código em teste.
Robert Harvey
11
Relacionado, pode ser visto como uma duplicata: O TDD usa formalmente o teste de caixa preta para suplementar os testes de unidade?
Doc Brown

Respostas:

20

Seu professor está certo: o teste de unidade pode ser uma caixa preta ou uma caixa branca. A diferença é menos sobre o que o testador sabe, mas mais sobre como você gera casos de teste.

Com o teste da caixa preta, você olha apenas para a interface e (se houver) a especificação para um componente. Quando uma função tem uma assinatura int foo(int a, int b), eu posso gerar imediatamente alguns casos de teste apenas testando números inteiros interessantes: zero, um, menos um, números de vários dígitos, INT_MAX, INT_MAX - 1 e assim por diante. Os testes de caixa preta são ótimos porque são independentes da implementação. Mas eles também podem perder casos importantes.

Com um teste de caixa branca, olho para a implementação, ou seja, o código fonte e gero casos de teste a partir disso. Por exemplo, talvez eu queira obter 100% de cobertura de caminho para uma função. Depois, escolho os valores de entrada para que todos os caminhos sejam percorridos. Os testes de caixa branca são ótimos porque eles podem exercitar exaustivamente um pedaço de código, com muito mais confiança do que os testes de caixa preta. Mas eles podem estar apenas testando detalhes da implementação, não um comportamento realmente importante. Em alguns casos, eles são claramente uma perda de tempo.

Como um teste de caixa branca é derivado da implementação, ele só pode ser gravado posteriormente. Um teste de caixa preta é derivado do design / interface / especificação e, portanto, pode ser escrito antes ou depois da implementação. TDD não é claramente uma caixa preta ou uma caixa branca. Como todo comportamento é expresso primeiro por um teste e, em seguida, o código mínimo para esse comportamento é implementado, o TDD resulta em casos de teste semelhantes a um teste de caixa branca. Mas quando analisamos o fluxo de informações, os testes TDD não são derivados do código-fonte, mas de requisitos externos. Portanto, o TDD é mais parecido com uma caixa preta.

amon
fonte
3
"Como um teste de caixa branca é derivado da implementação, ele só pode ser gravado posteriormente" - bem, se eu for escrever um teste com falha no estilo TDD para o próximo novo recurso que eu gostaria de adicionar à minha função ou classe existente , Analiso a implementação atual primeiro para saber o que não é suportado até agora, para que eu possa projetar um teste mais significativo - inicialmente com falha -. Eu chamo isso de abordagem de teste de caixa branca, e não um teste escrito posteriormente. (No entanto, +1 de mim).
Doc Brown
4

Se você está desenvolvendo um desenvolvimento orientado a testes, em teoria, todos os seus testes de unidade devem ser uma caixa preta. Essa é a sua "abordagem do primeiro teste". Você escreve o contrato (interface), escreve os testes para esse contrato e, em seguida, o contrato é cumprido pela implementação. Portanto, o teste não sabe nada e não deve saber nada sobre a implementação.

Afinal, quando você escreve um teste, o que está testando? Métodos / funções públicas.

Se você escrever a interface para uma classe e depois escrever os testes e for atropelado por um ônibus, o cara que escrever a classe enquanto estiver no hospital poderá fazê-lo a partir da sua interface, certo? Ele não deveria ter que jogá-lo fora e escrever sua própria interface e testes.

Onde isso se desfaz um pouco é quando você precisa zombar de algo que a implementação depende, mas se você se encontra na situação em que está zombando de algo que nunca é exposto publicamente, cometeu um erro e precisa veja Dependency Injection et al . Portanto, eu argumentaria que o teste unitário da caixa branca, e não o preto, deveria ser a exceção.

Considere 'Teste no banheiro - comportamento do teste não implementação' , em que a implementação de uma classe é alterada, mas os testes ainda devem ser válidos.

No entanto, se você precisar garantir que sua cobertura de código esteja em alta (por exemplo, verifique se todos os caminhos condicionais são testados na implementação), será absolutamente necessário testar a unidade de caixa branca, porque a única maneira de saber qual é a sua caminhos são é olhando os caminhos na implementação.

AdamJS
fonte
2
If you were to write the interface for a class, and then write the tests, and then you get hit by a bus, the guy who writes the class while you're in hospital should be able to do so from your interface, right?-- Não exatamente. A maioria dos contratos de API realmente especifica apenas assinaturas de método, não semântica ou comportamento.
Robert Harvey
Você está certo; Entendi que sua interface incluiria as especificações a partir das quais foi escrita, não literalmente apenas o texto de MyClassInterface.
AdamJS
@RobertHarvey É verdade que a maioria das interfaces não descreve explicitamente semântica ou comportamento, mas acho que geralmente existe implicitamente. Se não estivesse lá, o código que requer certa semântica não seria capaz de depender da abstração. E não há nada para interromper interfaces, incluindo detalhes de semântica e comportamento como comentários / docblocs. Por exemplo, consulte github.com/php-fig/http-message/blob/master/src/…
bdsl
3

Eu argumentaria que todos os testes de unidade bem escritos são inerentemente "caixa preta". Claro que posso ter uma implementação em mente ao escrever o teste, mas essa implementação pode mudar quando refatorar. Portanto, o teste deve usar APIs públicas apenas durante o teste para testar a funcionalidade, não a implementação. Ele não se importa com os detalhes da implementação, portanto, com o teste da caixa preta.

Se eu escrever testes que acessam aspectos internos ou privados da unidade em teste, testarei os detalhes da implementação: Estou testando caixa branca. Mas também estou escrevendo testes frágeis que podem quebrar facilmente quando a implementação é alterada. Portanto, esses testes de caixa branca são uma má ideia e devem ser evitados.

Conclusão: se você testar caixa branca com testes unitários, terá testes mal construídos. Somente teste de back box com esses testes de unidade. Seu professor está correto: pode ser também. Mas somente se for mal feito.

David Arno
fonte
1

Eu estava no processo de escrever testes de unidade que realizam testes de caixa preta. Ou seja, estou testando métodos públicos em uma classe e por implicação da lógica de teste de resultados nos métodos particulares que eles chamam.

Eu faço isso alterando entradas para o método público que está sendo testado por unidade e testando as saídas esperadas que são determinadas ou alteradas pela lógica nos métodos privados de suporte, cuja implementação meus "testes de unidade" não precisam saber nada.

Portanto, não há nada que o impeça de executar testes de caixa preta em testes de unidade e os testes serão interrompidos se alguém mexer com a implementação da lógica de suporte oculta. De fato, essa parece ser uma abordagem superior, mais eficiente, do que a unidade de caixa branca testando tudo em uma classe por causa disso. Eu estou com o professor.

Shooresh
fonte