Como você pode TDD para um bug que só pode ser testado depois de corrigido?

13

Aqui está um exemplo: Meu aplicativo Web contém elementos arrastáveis. Ao arrastar um elemento, o navegador produz uma "imagem fantasma". Quero remover a "imagem fantasma" ao arrastar e escrevo um teste para esse comportamento.

Meu problema é que inicialmente não tenho idéia de como corrigir esse bug e a única maneira de escrever um teste é depois de corrigi-lo.

Em uma função simples como let sum = (a, b) => a - b, você pode escrever um teste para saber por sum(1, 2)que não é igual 3antes de escrever qualquer código.

No caso que estou descrevendo, não posso testar, porque não sei qual é a verificação (não sei qual deve ser a afirmação).

Uma solução para o problema descrito é:

let dataTransfer = e.dataTransfer
let canvas = document.createElement('canvas');
canvas.style.opacity = '0';
canvas.style.position = 'absolute';
canvas.style.top = '-1000px';
dataTransfer.effectAllowed = 'none';

document.body.appendChild(canvas);
dataTransfer.setDragImage(canvas, 0, 0);

Eu não poderia saber que essa era a solução. Eu não poderia nem ter escrito o teste depois de encontrar a solução on-line, porque a única maneira de saber se ela realmente funcionava era adicionar esse código à minha base de código e verificar com o navegador se tinha o efeito desejado. O teste teve que ser escrito após o código, que vai contra o TDD.

Qual seria a abordagem TDD para esse problema? Escrever o teste antes do código é obrigatório ou opcional?

maximedupre
fonte
2
Faça sua pesquisa então. Encontre uma solução ... depois escreva seu teste, corrija e refatore. Os testes não são feitos para (apenas) verificar se o seu código funciona, mas para a prova futura de sua solução completa. Inicialmente, você cria seu teste para falhar, que propriedade estará testando? Essa é uma maneira de começar.
Juan Carlos Eduardo Romaina Ac
@Kilian Foth: Vejo suas boas intenções alterando o título da pergunta, mas sua edição invalidou partes da minha resposta. Além disso, seu novo título IMHO não se encaixava bem no corpo da pergunta. Então fiz uma reversão, sem ofensa.
Doc Brown

Respostas:

26

Quando entendi corretamente, você não pode nem escrever um teste automatizado confiável para o seu exemplo de "imagem fantasma" depois de encontrar uma solução, pois a única maneira de verificar o comportamento correto é olhar para a tela e verificar se não há imagem fantasma não mais. Isso me dá a impressão de que o título original fez a pergunta errada. A verdadeira questão deve ser

  • como testar automaticamente um determinado comportamento de uma interface gráfica do usuário?

E a resposta é: para vários tipos de problemas de interface do usuário, você não . Claro, pode-se tentar automatizar a criação da interface do usuário mostrando o problema de alguma forma e tentar implementar algo como uma comparação de captura de tela, mas isso geralmente é propenso a erros, quebradiço e não é econômico.

Especialmente o design da interface do usuário "test drive" ou aprimoramentos da interface do usuário por testes automatizados escritos com antecedência são literalmente impossíveis. Você "conduz" o design da interface do usuário fazendo uma melhoria, mostra o resultado a um humano (você, alguns testadores ou usuário) e solicita feedback.

Portanto, aceite o fato de que o TDD não é uma bala de prata e, para alguns tipos de problemas, o teste manual ainda faz mais sentido do que os testes automatizados. Se você tem um processo de teste sistemático, talvez com alguns testadores dedicados, a melhor coisa a fazer é adicionar o caso ao seu plano de teste.

Doc Brown
fonte
Em geral, o teste da interface do usuário não é trivial; você pode fixar, por exemplo, hash uma imagem gerada, simular / automatizar, gravar macros, usar uma solução proprietária, usar testes manuais, depende da situação e da necessidade do teste automatizado da interface do usuário para o seu projeto.
Esoterik 23/05
1
@esoterik: sim, e todas essas técnicas automatizadas são propensas a erros e quebradiças, como eu já escrevi. A única abordagem não frágil que conheço é o teste manual.
Doc Brown
3
Obrigado por responder. Acho que você está certo, espero erroneamente encontrar uma bala de prata no TDD. Não parece haver uma maneira eficiente de testar o que eu quero testar - a comparação da captura de tela e todas as opções acima parecem não fornecer um ROI suficiente. A comparação de capturas de tela, em particular, parece consumir muito tempo e, como você disse, propensa a erros.
Maximedupre 23/05
1
@ maximedupre: encontrei este anúncio para uma ferramenta que tenta solucionar o problema, mas o artigo parece concordar com a minha resposta em geral.
Doc Brown
5

Qual seria a abordagem TDD para esse problema? Escrever o teste antes do código é obrigatório ou opcional?

Uma maneira é aplicar um análogo de uma solução de pico .

James Shore descreveu desta maneira:

Realizamos pequenas experiências isoladas quando precisamos de mais informações.

A idéia básica é que você abaixe as ferramentas de design enquanto descobre o que está acontecendo. Depois de se orientar, você retoma as ferramentas de design.

O truque: você traz o conhecimento de sua investigação de volta à sua base de código de produção, mas não traz o código . Em vez disso, você o recria enquanto usa suas técnicas de design disciplinado.

Cavalos para cursos.

EDITAR:

Como você pode automatizar um teste se o defeito só pode ser visto por um olho humano?

Gostaria de sugerir uma ortografia um pouco diferente: "Como você pode automatizar um teste se a automatização do teste não é rentável?"

A resposta, é claro, é "você não". Em vez disso, esforce-se para separar sua implementação em duas partes - uma grande parte em que o teste é econômico e uma menor que é muito simples de quebrar.

Existem duas maneiras de construir um design de software: Uma maneira é tornar tão simples que obviamente não há deficiências - CAR Hoare

Portanto, ao trabalhar com código de terceiros, teremos um shell muito fino de código que atua como um proxy para a biblioteca de terceiros. No teste, substituímos esse shell por um "teste duplo", que verifica o protocolo , sem se preocupar que produz os efeitos desejados.

Para testar a integração de nossos códigos com o código real de terceiros, contamos com outras técnicas (verificação visual, chamadas de suporte técnico, otimismo ...)

Pode ser útil manter alguns artefatos de demonstração por perto, para que você possa verificar se suas suposições ainda são válidas ao atualizar a biblioteca de terceiros.

VoiceOfUnreason
fonte
Eu amo o que James Shore tem a dizer. Atualmente, estou seguindo o screencast www.letscodejavascript.com e estou aprendendo muito. Vou ler os links que você me indicou.
Maximedupre 23/05
Você está certo, eu li mais sobre TDD e picos. Você realmente precisa saber como é o código que está tentando verificar antes de tentar testá-lo. O TDD não pode ensinar nada que você ainda não saiba, mas pode potencialmente mostrar algumas coisas que você precisa aprender, parafraseando James Shore. Nessa nota, eu gostaria de propor uma etapa adicional no TDD: pico, teste, falha, aprovação, refatoração.
Maximedupre 25/05
0

Apenas com uma perspectiva diferente, o teste em torno da interface do usuário / GUI pode ser feito um pouco melhor em relação ao teste de aceitação (testes centrados no recurso / negócio de fluxo de trabalho).

Para a web, acho que estruturas como o selenium webdriver têm o potencial de se aproximar do teste correto, mas a sobrecarga para começar pode ser um pouco demais, e é uma mudança no fluxo observado no TDD em relação apenas aos testes de unidade .

A parte que ajudaria especificamente a sua situação é algo chamado Modelo de Objeto de Página ( https://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html ). Isso permite um mapeamento explícito da GUI em tempo de execução para algum código, nomeando métodos / eventos / membros da classe.

Os principais argumentos contra isso seriam a sobrecarga, e que essa sobrecarga geralmente poderia ser vista no final do ciclo de desenvolvimento. A sobrecarga é que os testes exigem algum invólucro que parece criar um trabalho duplicado.

No futuro, isso dependeria do custo / benefício da equipe e dos negócios, portanto poderia ser um tópico benéfico a ser discutido para determinar expectativas e pontos de vista.

eparham7861
fonte
Na verdade, eu estava testando testes funcionais e2e (com chave de selênio) no TDD recentemente, mas a sobrecarga é definitivamente muito grande, como você disse. Você não pode ser um desenvolvedor eficiente e fazer TDD com testes e2e. Eu estava usando o POM, mas o único benefício que isso me proporcionou foi uma arquitetura aprimorada na minha base de código de teste.
Maximedupre 24/05
Sim, acho que uma opção mais viável que eu vi de empresas diferentes para equipes diferentes seria incorporar um processo SQA mais manual, em que um membro da equipe / membro da equipe é designado para realizar apenas testes manuais da interface do usuário. Os testes têm principalmente capturas de tela e documentação passo a passo. No mínimo, algo assim produziria alguma evidência de teste em relação a um aplicativo.
Eparham7861
0

Como é uma imagem fantasma? Se você criou uma interface fictícia de uma cor conhecida, onde coloca seu componente arrastável? Haveria uma cor específica presente se houvesse uma imagem fantasma.

Então o teste poderia testar a ausência da cor da imagem fantasma.

Esse teste seria razoavelmente durável e factível.

Esben Skov Pedersen
fonte
Factível - sim. Durável - depende. Apenas alterar a cor / tema da sua interface do usuário pode interromper seus testes, o que não me parece muito durável.
Sean Burton
1
Você não testaria sua interface do usuário inteira. Você criaria uma interface fictícia para o componente arrastar e soltar.
Esben Skov Pedersen
Não sei como realizar o que você está sugerindo. Uma imagem fantasma no meu caso seria uma réplica semi-opaca do elemento que está sendo arrastado. A imagem fantasma segue o cursor o tempo todo enquanto ocorre o arrastar e soltar.
Maximedupre 24/05
Sim. Você teria que automatizar o arrasto. Não seria um teste de unidade, mas sim um teste e2e.
Esben Skov Pedersen