Um pouco de contexto: Hoje cedo eu tive que atualizar um código SQL que outro colega meu forneceu e, como é um script bastante grande, ele é armazenado como um arquivo separado (que é lido e executado em tempo de execução). Ao fazer isso, acidentalmente reintroduzi dois bugs que tivemos alguns meses atrás, a saber:
- Por qualquer motivo, o arquivo ASCII foi codificado em UTF-16 (o colega me enviou o arquivo, o que pode ter causado).
- Faltavam
SET
instruções iniciais no script (necessárias devido a algumas coisas do driver na produção, mas não em uma instalação limpa localmente).
Depois de depurar isso por cerca de uma hora (novamente), decidi escrever alguns testes de unidade para garantir que isso nunca acontecesse novamente (e inclua uma maneira rápida de corrigi-lo na mensagem de asserção para fornecer uma solução fácil para futuros desenvolvedores).
No entanto, quando introduzi esse código, outro colega (que também é o líder da nossa equipe) se aproxima de mim e me diz que não devo fazer essas coisas novamente porque:
"Essas coisas não pertencem a testes de unidade"
"Os testes de unidade devem ser usados apenas para verificar o fluxo do seu código"
Estou em conflito agora, pois ainda acho que o que estou fazendo não está errado, pois esse bug não seria reintroduzido no futuro, no entanto, esse colega trabalha como sênior e, no final do dia, decide o que nós gastamos nosso tempo. O que devo fazer? Estou errado por fazer dessa maneira? É considerado má prática?
fonte
Respostas:
Provavelmente, os testes que você escreveu estão mais próximos dos testes de integração ou regressão do que os testes de unidade. Embora a linha possa ser muito confusa e às vezes se transformar em pedantismo sobre o que é ou não um teste de unidade, eu voltaria ao seu colega e perguntaria onde deveriam estar os testes que você escreveu, pois eles agregam valor, garantindo a correção do código.
Eu não focaria muito no que é ou não é um teste de unidade e perceberia que, mesmo que seja um teste de integração, ainda pode haver valor no teste.
fonte
Tecnicamente, não é um teste de unidade e mais uma etapa de validação. A abordagem adequada realmente depende do que seu fluxo de trabalho precisa ser. O líder da sua equipe está correto quanto ao objetivo dos testes de unidade. Meu sentimento é que este é um caso de usar a ferramenta errada para um trabalho que ainda precisa ser feito. Então comece com isso:
Pela descrição, você precisa validar se todos os scripts do banco de dados estão em conformidade com alguns padrões.
A qualidade do código-fonte geralmente é verificada por ferramentas de análise estática . Se você não tiver uma ferramenta de análise estática para validar seu SQL, poderá criar uma ferramenta rápida e suja que executa a verificação de qualquer arquivo SQL passado para ele. Não custa verificar se existem ferramentas de análise estática que podem lidar com os problemas de que você está falando.
Se você fizer parte da sua infraestrutura de construção, como incorporá-la ao Jenkins ou algo parecido, ela poderá ser aplicada a todos os arquivos SQL do seu projeto.
Os testes de unidade resolvem apenas o problema do seu arquivo atual.
Isso é muito fácil, você fala com o líder da sua equipe. Ele pode trabalhar com o proprietário do produto e você para determinar o risco / recompensa de investir nas ferramentas. Se este é provavelmente um problema pontual, as ferramentas provavelmente serão um exagero. Se as ferramentas para detectar os maiores problemas são fáceis, pode valer a pena apenas pela verificação de sanidade.
O líder da sua equipe pode ter algumas idéias que você (ou eu) não considerou, que podem solucionar o problema mais corretamente.
fonte
É uma prática recomendada chamar testes que acessam arquivos "Testes de Unidade".
Infelizmente, que tipos de testes existem e como eles são organizados são inteiramente específicos da empresa. Então, você precisará descobrir como sua empresa lida com esses testes.
Se você ainda não tem como executar testes automatizados que não sejam testes de unidade, a abordagem pragmática é marcar os testes de unidade que na verdade não são testes de unidade com um prefixo, até que você tenha o suficiente para começar a descobrir que tipo de testes que você realmente tem / precisa. Depois disso, você pode começar a organizar.
fonte
Michael Feathers diz isso em seu livro Working Effective With Legacy Code:
Seu teste ajudará a localizar erros rapidamente e a executar rapidamente? Se sim, faça-o! Se não, então não! É simples assim!
Dito isto, você está trabalhando em um ambiente com outras pessoas e precisa se dar bem com elas. Você pode ter que acabar fazendo do jeito dele, mesmo que não concorde com isso.
fonte
Escrevi testes semelhantes, ocasionalmente, contra arquivos de código-fonte, arquivos de configuração e assim por diante. Eu não os chamaria de testes unitários porque (a) eles estão acessando o sistema de arquivos e podem não ser ultra-rápidos (b) não me importo se eles são executados em todos os check-in (em vez de noturnos em um Servidor de CI).
Você pode chamá-los de testes de integração; certamente, eles estão mais próximos dessa perspectiva do que os testes de unidade.
Meu próprio termo para eles é testes de recursos . IMHO, eles são totalmente justificados se executados todas as noites em um servidor de IC: há um custo mínimo e, quando usado criteriosamente, agrega claramente valor. Uma definição criteriosa : se o teste está verificando um problema que causou um problema (como a codificação mencionada).
fonte
Um teste de unidade é sobre testar um método ou 'unidade' de código. Você está testando o menor grupo de lógica e código do seu software.
Mais tarde, quando você ingressar com outras unidades, você executará testes de integração.
Espero que o líder de sua equipe incentive sua iniciativa e deva ter oferecido sugestões alternativas. Você definitivamente tem a ideia certa.
Seu SQL é código como qualquer linguagem de geração mais baixa como C # ou Java e deve ser testado como tal. E verificação e validação pertencem a todos os níveis de teste. Portanto, as instruções de codificação e SET estão incluídas, mas não necessariamente testadas exclusivamente. Coisas gerais, como terminações de linhas ou caixas, geralmente você pode usar apenas um gancho ou recurso SCM.
A melhor prática é fazer testes de regressão para garantir que erros anteriores não sejam reintroduzidos. Geralmente, os testes são criados juntamente com qualquer resolução do bug. Se esses erros não são cobertos por testes de regressão no nível da unidade / integração ou sistema e, em seguida, reintroduzem, é um problema de equipe, um problema de processo, não individual.
O problema é que ... erros de sintaxe, instruções ausentes ou blocos lógicos dentro de uma 'unidade' normalmente não são testados. Você está testando as entradas e saídas da unidade em diferentes combinações, testando as muitas possibilidades que podem ser geradas.
Voltando às instruções SET ausentes - elas ajudam a informar as muitas possibilidades de entrada e saída a serem testadas. Que teste você escreveria que falharia se estivesse faltando algum SET escolhido?
fonte
Se você possui arquivos que se tornam parte do seu produto, o conteúdo deles deve estar correto. Não há razão para você não verificar isso. Por exemplo, se você precisar de seis imagens 1024x 1024 em alguma pasta, faça um teste de unidade que verifique se você tem exatamente isso.
Mas você provavelmente não possui apenas os arquivos, também possui algum código que os lê. Você pode escrever um teste de unidade para esse código. No exemplo acima, a função de ler uma das seis imagens retorna uma imagem de 1024 x 1024 na memória (ou o que ela deveria produzir).
De qualquer forma, pode não ser um teste de unidade, mas é um teste útil. E se você usa uma estrutura de teste de unidade que permite fazer um teste útil (que não é um teste de unidade), por que não usar a estrutura de teste de unidade?
fonte
Talvez eu esteja entendendo mal o seu problema, mas para mim isso parece um problema que não precisa ser capturado por nenhum tipo de teste dedicado, mas simplesmente pelo sistema de controle de versão . Qualquer alteração em uma base de código deve ser revisada patch a patch antes de confirmar. Uma maneira simples de fazer isso no git é adicionar as alterações com
Para cada alteração em um arquivo de texto, o diretório de trabalho perguntará se você realmente deseja mantê-lo. Isso permitiria ver, por exemplo, a exclusão dessas "
SET
declarações iniciais ".Caso a codificação de um arquivo inteiro seja alterada, algo diferente aconteceria: o algoritmo falharia em diferenciar o arquivo antigo e o novo e, portanto
git add -p
, não acrescentaria nada. Isso seria visível no outro comando que eu faria antes de qualquer confirmação, a saberAqui você veria o arquivo destacado em vermelho, indicando que não são mudanças. Investigar por que eles não entraram
git add -p
rapidamente tornaria o problema óbvio.fonte
git
é o melhor exemplo disso - uma ótima ferramenta, mas quase inutilizável para meros mortais .Outro ângulo a considerar: como essas duas condições são requisitos para a execução do seu programa, você não deve incorporar a lógica próxima à lógica de execução? Quero dizer: você testa a existência de um arquivo antes de lê-lo e / ou valida seu conteúdo, certo? então como isso é diferente? Eu acho que, como esse é um recurso externo ao código, ele deve ser validado em tempo de execução, antes de ser realmente usado. Resultado: aplicativo mais forte, sem necessidade de escrever testes adicionais.
fonte
Os testes são do mesmo código que qualquer outro e, se suficientemente complexo, também se beneficiam com ... testes de unidade. Parece mais simples adicionar essas verificações de pré-condição diretamente no teste.
A maioria dos testes é simples o suficiente para não exigir isso, mas se alguns forem suficientemente complexos, não vejo nada de fundamentalmente errado com essas verificações de pré-condição. Obviamente, o teste também deve falhar sem eles, mas um bom teste de unidade também informa qual unidade está falhando.
Um script usado como parte do teste e deve ter determinado conteúdo e codificação provavelmente é uma unidade. Pode ter muito mais código e lógica do que o restante do teste. Um teste com esse script não é o melhor design de todos os tempos e, se possível, deve ser refatorado para algo mais direto (a menos que seja um teste de integração).
fonte
Em primeiro lugar - um dos objetivos dos testes é impedir a ocorrência de problemas no seu código -, portanto, você deve continuar escrevendo testes dessa natureza.
Em segundo lugar - nomear é difícil. Sim, esses claramente não são "testes de unidade", mas podem ser partes desejáveis e necessárias do processo de compilação, porque protegem você de erros óbvios e porque fornecem feedback sobre erros mais cedo (principalmente se você não vê o conseqüências em uma caixa de desenvolvimento).
Portanto, a questão é realmente (deve estar no seu contexto) mais sobre quando e como esses testes são executados do que o que são.
Eu usei esse tipo de teste extensivamente no passado - eles nos salvaram uma boa dose de dor.
fonte
Os testes de unidade são sobre executar uma unidade de código isoladamente para confirmar que está produzindo o resultado correto para a entrada correta. O isolamento deve tornar a unidade em teste e o próprio teste repetível, ou seja, não deve depender ou apresentar efeitos colaterais.
O SQL não é exatamente algo que pode ser testado isoladamente; portanto, qualquer teste do SQL não é exatamente um teste de unidade e, exceto pelas instruções SELECT, é quase certo que tenha um efeito colateral. Podemos chamá-lo de teste de integração em vez de teste de unidade.
É sempre aconselhável garantir que qualquer defeito que possa ser introduzido possa ser detectado o mais cedo possível no ciclo de desenvolvimento, e é benéfico fazê-lo de uma maneira que facilite a identificação da origem do defeito para que ele possa ser rapidamente detectado. corrigido.
Os testes em questão podem ser realocados mais apropriadamente fora do corpo dos "testes de unidade" e colocados em outro lugar, mas não devem ser removidos por completo se estiverem fazendo algo útil, como proteção contra a possível introdução de um defeito que pode levar horas para rastrear baixa.
fonte