Código de teste para copiar e colar: quão ruim é isso?


12

Meu trabalho atual é principalmente escrever código de teste da GUI para vários aplicativos em que trabalhamos. No entanto, acho que tenho a tendência de copiar e colar muito código nos testes. A razão para isso é que as áreas que estou testando tendem a ser semelhantes o suficiente para precisar de repetição, mas não o bastante para encapsular o código em métodos ou objetos. Acho que, quando tento usar classes ou métodos de forma mais abrangente, os testes se tornam mais difíceis de manter e, às vezes, difíceis de escrever em primeiro lugar.

Em vez disso, costumo copiar um grande pedaço de código de teste de uma seção e colá-lo em outra e fazer pequenas alterações necessárias. Não uso maneiras mais estruturadas de codificação, como usar mais princípios ou funções de OO.

Outros codificadores se sentem assim ao escrever o código de teste? Obviamente, quero seguir os princípios DRY e YAGNI, mas acho que o código de teste (código de teste automatizado para testes de GUI de qualquer maneira) pode dificultar o cumprimento desses princípios. Ou eu só preciso de mais prática de codificação e um sistema geral melhor de fazer as coisas?

EDIT: A ferramenta que estou usando é o SilkTest, que está em uma linguagem proprietária chamada 4Test. Além disso, esses testes são principalmente para aplicativos de área de trabalho do Windows, mas eu também testei aplicativos da web usando essa configuração também.


Qual ferramenta de teste você está usando? Pode ser que sua estrutura de teste não suporte os tipos de testes que você está escrevendo. Recortar e colar de mais de três linhas geralmente é muito ruim, mas se você puder adicionar claramente mais valor a longo prazo automatizando um teste de GUI do que executando manualmente todas as vezes, o que estiver fazendo provavelmente será bastante Boa.
GlenPeterson

Além disso, que idioma é esse? Você pode ter algo disponível que simplesmente não está aparecendo, o que permitiria a reutilização (como funções de primeira classe). Por outro lado, casos de teste são suposto ser simples, para mantê-lo menos provável que eles têm bugs-se ...
Izkata

3
Em qualquer coisa que eu escrevi, o código de teste não é excluído da refatoração.
Simon Whitehead

Respostas:


23

Casos de teste colados e depois editados geralmente são bons.

Os testes devem ter o menor número possível de dependências externas e ser o mais direto possível. Os casos de teste tendem a mudar com o tempo, e casos de teste anteriormente quase idênticos podem divergir repentinamente. Atualizar um caso de teste sem ter que se preocupar em quebrar outros casos é uma coisa boa.

Obviamente, o código padrão , que é idêntico em muitos casos de teste e precisa mudar de concerto, pode e deve ser fatorado.


1
É principalmente assim que me sinto. O código de teste quase idêntico está correto em muitos casos, mas o código de teste idêntico repetido é uma má notícia.
Joshin4colours

12

Repetição é a raiz de todo mal

Isso está certo! A repetição é a raiz de todo mal . Provavelmente foi Knuth dizendo em seu livro "Otimização prematura é a raiz de todo mal", mas acho que é repetição.

Sempre que você olha para um programa ou escreve um e descobre algum tipo de repetição: Remova-o! Mate-o imediatamente ... qualquer coisa, exceto se livrar dele !

Cada vez que introduzi algum tipo de repetição e tive que corrigir um bug, esqueci de corrigir a réplica ... (Donald Knuth) Então, sempre que houver uma repetição, remova-a da melhor maneira possível, não hackear !

Pense em um design enxuto limpo (como encapsular seus blocos de código repetidos nas classes auxiliares) e escreva alguns testes antes de alterar alguma coisa (apenas para ter certeza de que você não quebrou alguma coisa). Isso é verdade para qualquer parte do código gravada e os códigos de teste não são excepção.

Aqui está uma boa leitura do Code Horror que me inspira - Uma Proposta Modesta para a Escola de Reutilização de Copiar e Colar .


"Cada vez que introduzia algum tipo de repetição e tinha que consertar um bug, esqueci de consertar a réplica ..." exatamente. Além disso, se você c & p e você se esqueça de ajustar o texto copiado para o seu contexto atual, isso vai doer muito. O código de teste com erros não soa como a situação ideal, agora é?
marktani

yeap, eu levei as estações de Knuth :)
Yusubov

9
Você se repetiu: Você se repetiu dizendo "Repetição é a raiz de todo mal" no título e na frase de introdução.
Thomas Eding

Pois é, eu fiz isso intencionalmente para salientar a importância e você está convidado a editar isso é parte :)
Yusubov

1
Thomas Eding, você se repetiu também. Você repetiu-se bem =)
marktani

7

Ainda é muito ruim cortar e colar. Há alguns problemas.

Seus testes podem ser frágeis, porque você está vulnerável a algo que requer uma alteração em todo esse código copiado e colado. Você terá que reescrever todos os testes?

Se você não pode encapsular a lógica em métodos auxiliares fora de seus testes, não poderá escrever testes desses métodos auxiliares. Escrever testes de métodos de teste geralmente é muito difícil de valer a pena, pois você precisa quebrar seu código para testar o teste. Mas você pode métodos auxiliares de teste de unidade.

Pode muito bem tornar os testes menos legíveis. Um grande bloco de código copiado pode ser mais difícil de ler do que um método de chamada para auxiliar com um nome descritivo.

Tudo o que listei é algo que pode ser um problema. Se você achar que nenhum deles é realmente um problema, é claro que tudo bem.


> um método de chamada para auxiliar com um nome descritivo. Não é o problema com isso que seus testes de unidade agora estão se tornando programas em si - qual deles deve ser evitado. E se alguns testes falharem - é o código que está quebrado ou os assistentes de teste?
dwjohnston

4

Eu costumava concordar com você. Mas então, com o tempo, descobri que todas as alterações que eu fazia (principalmente as alterações de DI nos testes de unidade) exigiam vários testes para mudar, o que era complicado. Agora, assino a escola de DRY, mesmo quando faço testes.

Para teste da GUI, convém examinar o padrão PageObject para reduzir o código repetido.


2

Eu recomendaria pegar padrões XUnit. Eu costumava ter exatamente o mesmo problema até começar a alavancar esse livro. O padrão Mãe do Objeto parece ser o mais útil para o seu cenário.

Como alguém mencionado, encapsular adequadamente esse código de instalação pode ser oneroso, mas ter que alterá-lo em todos os lugares que você copia e cola é ainda mais.


+1 para o Object Mother patterncódigo de inicialização comum.
K3b

2

As pessoas devem tentar limitar a repetição quando podem - sim. Mas a recompensa depende da situação. Isso poderia voltar ao debate sobre "melhores práticas". Mas a questão é o que é melhor para você nessa situação. Há exceções para todas as regras.

Algumas coisas que eu gostaria de perguntar são: 1) Qual a probabilidade de que essa funcionalidade sendo testada no UAT seja alterada? Se for improvável que isso mude, há menos chances de que você precise atualizar cada um de seus conjuntos de códigos. 2) Se houver uma alteração no UAT, ele sempre afetará cada conjunto do código copiado ou somente um ou dois conjuntos? Se puder ser isolado e exigir apenas uma alteração em um conjunto, pode ser útil separar as coisas. 3) Quão complexo será o método inicial se você tentar fazer com que ele lide com todos os cenários? Você está adicionando muitos if / else / loops aninhados? Se você começar a exagerar toda a ramificação, poderá acabar com um código difícil de compreender. Seria mais fácil fazer a atualização em cada um dos textos copiados do que revisitar toda a lógica de ramificação?

Se você está preso copiar / colar / alterar, acho que você gostaria de adicionar comentários como 'Isso é copiado no método xyz'. Dessa forma, você será lembrado para atualizar todas as versões coladas do código. Ou (vindo de outro usuário do SilkTest), você pode adicionar um arquivo inc separado que se concentre apenas nesse código repetido. Dessa forma, você tem todas as variações em um só lugar e pode ver facilmente os diferentes métodos que exigiriam atualização.


0

Um grande procedimento

Um pensamento: parece que você está tentando evitar código cut-n-paste, criando métodos como:

testScreen(title, fieldList, linkList, param1, param2, param3,...) {
    test that the layout at the top of the screen is correct
    test if PageTitle == title?
    for each field in fieldList:
        check that it appears in order on the screen
    for each field in linkList:
        check that it appears in order on the screen
    test if param1 is whatever...
    test if param2 is whatever...
    etc.
    test that the bottom of the screen is correct
}

Muitos pequenos procedimentos (kit de ferramentas)

Você também considerou a abordagem oposta? Em vez de passar um milhão de parâmetros para um grande procedimento testScreen (), talvez faça sua própria estrutura ou kit de ferramentas com pequenos procedimentos auxiliares que você escolhe conforme necessário. Gostar:

testScreenTop()
verifyLinks(list)
testScreenBottom()

Você ainda recorta e cola esses procedimentos em todas as telas, mas está recortando e colando pedaços menores de código e criando pedaços comuns que não são recortados e colados (o conteúdo de cada pequeno procedimento).

Copiar e colar

O único momento em que o código recortado e colado não me picou foi quando o código foi jogado fora antes que eu tivesse que alterá-lo. Minha maior preocupação com os testes de interface do usuário é a rapidez com que eles se tornam obsoletos. Se você descobrir que joga todo o seu código fora antes de alterá-lo, talvez tenha encontrado um nicho em que recortar e colar está OK! Além disso, não é tão ruim quando não há código a jusante do código recortado e colado (por exemplo, na interface do usuário de um aplicativo). Se você estiver colando mais de três linhas, eu realmente gostaria de fazer algo sobre isso. Pelo menos tome medidas para minimizá-lo!

Teste de UI automatizado

Caramba, se você puder provar maior produtividade com testes automatizados de interface do usuário do que com testes manuais, usando qualquer técnica (o custo de escrever / manter testes automatizados é menor do que testar manualmente todas as vezes, mas a qualidade é a mesma). Acho que você deveria escrever um artigo. Eu leria! Agora posso ver o título "Recortar e colar código uma vitória líquida para testes de interface do usuário!"


0

Realmente não é tão ruim assim. De fato, se você descobrir que certos padrões de código estão sendo usados ​​com muita frequência e as alterações são muito rotineiras (como algumas seqüências de caracteres ou valores de parâmetros), você pode até escrever um gerador de código que gere código de teste repetitivo com base em um pequeno (- ish?) lista de entrada de valores que mudam. Eu fiz isso (código de teste gerado) várias vezes, usando arquivos em lotes, scripts SQLPlus e até macros do Excel (parece feio, mas as variáveis ​​para os diferentes scripts de teste já estavam em uma planilha) e isso pode economizar muito tempo . O fato é que, se alguma coisa mudar na estrutura geral do código do caso de teste repetitivo, você poderá gerar novamente o que precisar.


0

É o mesmo que a maioria das outras respostas, mas de uma maneira que um gerente não técnico possa entender.

Imagine o seguinte cenário de erro:

  • Alguém faz alterações na tabela de dados em que muitos dos seus testes dependem.
  • Consequência: repentinamente 117 de seus 2933 testes automatizados falham.

O que você vai fazer?

  • (1) corrigir 117 testes?
  • (2) exclua os 117 testes e reimplemente-os via nova cópia e colagem. isso pode ser mais fácil do que (1)
  • (3) refatorar os testes para extrair código comum, para que no futuro você tenha que adaptar apenas um método (ou alguns) para corrigir os testes (consulte as respostas de @pdr ou @Michael Brown)
  • (4) excluir os 117 testes sem reimplementar os testes

Da minha experiência:

Ao introduzir testes automatizados, o gerenciamento gosta de "copiar e colar-testes": você realiza muitos testes em pouco tempo.

Após alguns dos "cenários de erro", o gerenciamento prefere (4) porque a correção de "copiar e colar-testes" é muito cara.

Faça certo em primeiro lugar (3) não será tão rápido, mas aumenta as chances de os testes sobreviverem

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.