Código de teste de remessa. Por que você não?

17

Gostaria de enviar o código de teste juntamente com um produto. Especificamente, forneça uma opção para que qualquer pessoa com uma cópia do nosso programa possa pressionar um botão de "autoteste" ou passar - autoteste na linha de comando e executar o conjunto completo de unidades | testes de integração.

Eu quero fazer isso principalmente para ajudar a depurar problemas descobertos em campo; portanto, quando um relatório de erro é recebido por um usuário final, é possível que ele seja suportado por "e também, esses três testes falharam na minha máquina". Eu gostaria que os testadores manuais pudessem executar a unidade | testes de integração também.

No entanto, o teste da equipe acredita que o código de teste não é um código de produção e, portanto, não deve ser enviado. Eu realmente não entendo esse argumento, já que a maioria dos projetos de código aberto fornece um conjunto de testes. Parece ser incomum em software fechado.

Eu gostaria de apoiar evidências ou histórias de ambos os lados do argumento. Adotei o meu melhor palpite sobre qual site de troca de pilhas seria o mais adequado, mas informe-me se isso estiver fora do lugar.

Jon Chesterfield
fonte
8
Por que um teste de unidade em um programa de código fechado (ou um programa de código aberto que não foi modificado) nunca falha? Se o seu produto exige uma quantidade razoável de problemas de instalação e configuração geralmente são a fonte de bugs, pode fazer sentido enviar algum tipo de aplicativo "validar minha configuração" que faz coisas como validar a conexão com o banco de dados, validar conexões com outros serviços externos seu código depende etc. Não faria sentido que um teste de unidade falhasse, pois você já validou que o código funciona.
Justin Caverna
leitura recomendada: como explico $ {something} para $ {someone}?
mosquito
15
Por que um teste de unidade falharia em campo? Em cima da minha cabeça: programa corrompido. Hardware desonesto. Condições de corrida que não vimos localmente. Vinculado a uma biblioteca dinâmica diferente. Conflitos com antivírus ou SO. Sendo usado com uma versão surpreendente do software relacionado devido à atualização incompleta. Interação com outros processos que não se comportam conforme o esperado. Há montes de razões pelas quais os erros aparecem no campo, e muitos deles poderiam ser atingido por um teste de unidade (para uma determinada definição de unidade)
Jon Chesterfield
7
@ JonChesterfield: criar um recurso de autoteste em seu programa é provavelmente uma coisa boa. E se esse recurso de autoteste pode reutilizar parcialmente o código dos seus testes de unidade, por que não? Mas esse recurso, bem como as peças reutilizáveis, deve ser desenvolvido com um ponto de vista "é o código de produção".
Doc Brown
2
@ JonChesterfield Tenho dificuldade em imaginar um teste de unidade com falha na maioria dessas causas. Porém, os testes de integração são outra questão - posso ver o mérito em enviá-los se isso puder ser feito sem muita coisa extra.
Loren Pechtel

Respostas:

19

Às vezes, o código de teste contém trechos de código de terceiros, externos e internos à sua empresa. Isso acontece quando os usuários arquivam bugs; seus testes (como testes de regressão) incorporam o código fornecido por eles para reproduzir. Freqüentemente, o licenciamento de tais trechos de código para reproduzir bugs não é claro. Portanto, você deve estar ciente dos problemas de propriedade intelectual. Você não deseja enviar código de teste que revele acidentalmente alguns segredos comerciais ou propriedade intelectual de um departamento diferente da sua empresa ou de seus parceiros externos.

Em outra nota, o código de teste raramente é mantido nos padrões de código de produção: as revisões de código não são necessariamente feitas; padrões de codificação não impostos, etc. Isso é lamentável, mas comum e não deve necessariamente refletir mal a equipe de teste se eles não tiverem esse objetivo em vigor no momento em que esses testes foram desenvolvidos.

Por outro lado, muitos testes são simplesmente embaraçosamente ruins e nem sequer testam o que alguns acham que está sendo testado. Essa é uma questão diferente ...

Por fim, devido a todos esses fatores, convém classificar seus testes como aqueles que podem ser enviados como código aberto e aqueles que simplesmente não podem. (Você pode escrever alguns testes personalizados com a remessa em mente, migrando lentamente os outros para esse conjunto.)

Erik Eidt
fonte
A questão de terceiros é um ponto muito bom. Agrupar o código de teste em "visível externamente" e "talvez confidencial" seria propenso a erros e uma sobrecarga considerável. Isso é praticamente um negócio por si só, obrigado.
Jon Chesterfield
Sim, difícil de fazer após o fato. Eu acho que você teria mais sorte com um esforço dedicado para desenvolver testes de remessa.
precisa
@ErikEidt: Tomei a liberdade de fazer uma sugestão para remover "como código aberto", porque provavelmente não é isso que o OP tinha em mente - acho que ele deseja enviar os testes como código fechado.
Doc Brown
@ DocBrown, eu entendo o seu ponto. Provavelmente, uma questão de interpretação, pois o OP mencionou "código aberto" em algum lugar do post. De qualquer forma, sua edição generaliza bem o argumento.
Erik Eidt 22/06
18

Testes de envio? Sim. Testes de unidade de expedição? Não.

Como você diz no comentário, o problema que você pode enfrentar ao executar o produto em um computador cliente incluirá problemas como vincular à dll errada, geralmente isso não é algo que um teste de unidade detectará (o que sem dúvida zombou da dll para testar o código).

Agora, enviando um conjunto de testes de integração, que chama a interface do usuário que chama a lógica que chama a dll ... que funcionará muito melhor. Os testes de integração podem mostrar outros aspectos de instalações com falha que os testes de unidade não seriam exibidos. (por exemplo, meu produto atual requer uma instalação de codecs k-lite, que não podemos agrupar devido ao licenciamento. Os testes de unidade podem mostrar que nosso código está funcionando bem, mas ainda não está funcionando para satisfação do cliente. Da mesma forma, nossa configuração dos codecs pode não ter funcionado corretamente, os testes de unidade também não mostrariam isso).

Envie então alguns dos seus testes de integração, que seriam exatamente o que você deseja para um produto instalado e integrado.

gbjbaanb
fonte
2

Eu pude entender essa preocupação fortemente em áreas em que você está cobrindo cada centímetro do hardware, como um mecanismo de jogo AAA de última geração multithread que usa todos os núcleos de CPU, intrínsecas SIMD, GPU, GPGPU etc., oferecendo uma plataforma cruzada produtos.

Nesses casos, seu pior pesadelo costuma ser aqueles em que seus testes (unidade e integração) serão aprovados nas primeiras 5.000 máquinas / plataformas diferentes testadas, mas falham na 5.001 devido a um bug no driver de um modelo obscuro de GPU. sobre isso me dá arrepios - você não pode testar ou prever com antecedência.

Especialmente se você escrever shaders de GPU, poderá terminar jogando na loteria reversa, onde metade do código que escrever invocará um comportamento indefinido, pois existem poucas garantias padrão portáteis aplicadas por todos os modelos / drivers de GPU envolvidos. Embora hoje em dia esteja cada vez menos parecido com jogar caça-minas, isso deve dar às pessoas uma idéia: http://theorangeduck.com/page/writing-portable-opengl . Tentar isso no final dos anos 90 e no início dos anos 2000 foi realmente horrível, e foi todo o caminho.

Para esses tipos de casos, muitas vezes você precisa de equipes de mais de 10.000 testadores com uma ampla gama de hardware e sistemas operacionais para solidificar o produto e se sentir confiante em relação a ele antes de uma versão estável. Nem todas as empresas podem se dar ao luxo de ter uma base de testes tão ampla e nem todas têm a disciplina necessária para fazer isso corretamente (todos os problemas amplamente visíveis devem ser corrigidos antes de haver tantos testadores em algum estágio pré-alfa / alfa interno, ou então o uma inundação de relatórios redundantes pode levar os desenvolvedores a entrar em pânico.

O que eu recomendo neste caso é o que os outros sugeriram, focar em um conjunto distribuído de testes de integração. Você pode agrupá-lo com o instalador, exigindo que os usuários passem por uma verificação de diagnóstico básica com muita atenção para fornecer detalhes de por que a instalação falhou e que eles podem passar para você, os desenvolvedores.

Outra coisa (se você pode convencer o chefe) é ter uma ampla gama de hardware disponível para fazer a integração contígua. Quanto maior a variedade de combinações de hardware / sistema operacional, melhor. Você deseja até uma variedade de hardware de baixa qualidade que modela os requisitos mínimos de hardware para seus servidores de CI: você nunca sabe.

Mas há mais uma coisa que eu sugiro:

Exploração madeireira

Se você estiver lidando com algo parecido com o cenário descrito acima, geralmente não poderá testar essas coisas que tendem a ser as mais problemáticas (aquelas piores dicas possíveis que aparecem no pior momento possível e não podem aparecer nem no suíte de testes mais exaustiva, pois é um problema restrito a um conjunto muito específico de hardware / sistema operacional).

No entanto, a maioria desses tipos de problemas, como incompatibilidades obscuras de hardware, falhas diretas de driver ou vinculação ao dylib errado (eu nunca realmente enfrentei essa preocupação), não vai demorar muito para iniciar o software. Normalmente vai falhar e queimar muito em breve, falando mal.

Eu recomendo, por uma questão de sanidade, abraçar o inevitável. Você não pode fazer nada sobre essas coisas que você não pode testar de forma abrangente. Não tente impedir o furacão (impossível), mas feche essas janelas.

Normalmente, aqui, a melhor coisa que podemos fazer é descobrir o problema o mais rápido possível, onde ocorre o mais detalhado possível (para restringir nossa lista de suspeitos) e corrigir o problema o mais rápido possível após a denúncia.

Nesse caso, o log pode ser um salva-vidas. Para esses tipos de campos, você pode criar esses logs técnicos com spam, que ninguém jamais leria. Frequentemente relevante é apenas a última linha registrada no log antes do usuário enfrentar uma falha devido a uma falha no driver, por exemplo, você pode gravar um processo externo ou um gancho que monitora falhas e mostra a última linha do log que os usuários podem copiar e cole para você, por exemplo, além de um despejo de memória.

Como isso geralmente requer informações granulares e muitas das áreas mais suscetíveis de código a esses problemas de hardware / plataforma / driver são críticas para o desempenho, existe um problema estranho em que o log pode estar acontecendo a uma taxa tão frequente que, na verdade, diminui abaixo do software.

Um truque útil nesse caso é confiar na suposição de que algo executado uma vez será executado com sucesso na segunda vez, terceira vez etc. Essa não é a suposição mais sólida, mas geralmente é "suficientemente boa" (e infinitamente melhor que nada) . Com isso, você pode usar um pouco de estado externo para acompanhar quando algo já foi registrado e pular tentativas subseqüentes de registrar casos realmente granulares nos quais o código será invocado repetidamente em um loop.

Enfim, espero que isso ajude. Eu já enfrentei esse tipo de tentação no passado e tenho um pouco de paranóia em torno da codificação da GPU (GPGPU e shaders) como resultado de algumas experiências passadas entre mim e minha equipe (às vezes, apenas vendo outros membros da equipe lidando com isso realmente tarde e pós-lançamento me deram arrepios, como algumas falhas da ATI em um modelo específico da Radeon que trava ao renderizar linhas antialias, mais tarde relatadas e marcadas como um problema conhecido, com apenas uma solução alternativa disponível).

O registro foi o que salvou nossos objetivos, permitindo que vejamos com freqüência o problema na 10.001ª máquina de protótipo obscura com uma GPU integrada que nunca ouvimos falar, com a última linha de código nos permitindo identificar exatamente onde a falha foi reduzida a 2 ou 3 linhas de código como suspeito, por exemplo, se estiver dentro de um shader elaborado, somos um tipo de SOL, já que não podemos fazer logon dentro de um shader de GPU, mas podemos pelo menos usar o log para ver qual shader teve o problema imediatamente para iniciar a investigação.

marstato
fonte
2
Memorizar o código de log é inteligente. No momento, não produzimos logs - principalmente por causa de problemas de desempenho -, portanto, a depuração envolve um dump principal. Incorporar testes de diagnóstico com o instalador também é uma boa idéia. Obrigado pela resposta detalhada.
Jon Chesterfield