Recentemente, tive muitas ocasiões em que precisei manter procedimentos e funções armazenados complexos. Eles já estavam quebrados, geralmente de maneiras bastante sutis - havia muito poucas ocasiões em que você chamava o SP com parâmetros válidos e simplesmente não funcionava.
Minha solução foi desenvolver uma estrutura que execute os procedimentos armazenados dentro de uma transação, depois de inicializar o banco de dados para as condições iniciais necessárias, testando o resultado esperado, também dentro da mesma transação. A transação foi revertida no final do teste.
Isso funcionou muito bem. Mas alguns chamariam isso de "teste de integração", pois envolve a integração com o banco de dados. Eu chamo isso de teste de unidade, desde que testei componentes individuais e casos de teste individuais para esses componentes e desde que controlei completamente o estado inicial do banco de dados.
Mas onde deve ser traçada a linha? Isso é teste de integração ou teste de unidade? Existe uma razão prática para esse tipo de teste ser uma má idéia? Se este for "apenas" teste de integração, alguém tem sugestões sobre como fazer "testes de unidade" reais nesses procedimentos armazenados?
Atualização, três anos e meio depois. No meu projeto atual, comecei a usar testes de unidade SSDT, com sucesso, embora pudessem ser melhores. Consulte Verificando o código do banco de dados usando testes de unidade do SQL Server . Normalmente, eles implantam o projeto de banco de dados em sua instância do SQL Server LocalDB, portanto, isso remove qualquer dúvida sobre o ambiente de banco de dados que afeta o teste. Eu preencho o banco de dados com os dados necessários durante o pré-teste, o que remove perguntas sobre o conteúdo do banco de dados. Na verdade, eu uso as instruções MERGE para fazer isso, garantindo que todos os dados que não sejam necessários para o teste atual sejam removidos, inseridos ou atualizados no banco de dados antes do teste. Eles têm problemas:
- Eles não são rápidos
- Não é possível reutilizar as condições de teste
- Não é possível reutilizar pré-testes (a menos que você os torne comuns a todos os testes em um projeto)
- A interface do usuário pode ser melhorada
Uma das razões para os problemas acima é que eu ainda não reclamei deles. Eu recomendo que qualquer pessoa interessada tente esse recurso e depois reclame. É assim que as melhorias são feitas.
fonte
Respostas:
O objetivo do teste de unidade não é fazer com que uma fada mágica de teste de unidade venha e valide sua opinião. É para testar os blocos de construção menores e mais simples do seu sistema, para que você não esteja testando algumas funcionalidades mais abrangentes e tropeçou porque algo não funcionou da maneira que você pensava. Então, você pode dividir isso ainda mais? Eu não acho que você pode, nesse caso:
(a) Parece um teste de unidade para mim; e (b) Não importa se é um teste de unidade ou não, porque testa o que você precisa testar, que é o ponto de usar testes de unidade em primeiro lugar!
Se você acha que os procedimentos são muito complexos, convém dividi-los em partes menores (em procedimentos de banco de dados ou em código), mas, para fazer isso, obviamente você gostaria de ter esses testes em primeiro lugar!
fonte
O teste de unidade, por definição, gira em torno do teste de uma "unidade" de código em seu ambiente ou plataforma em execução. A plataforma que você está usando é um banco de dados, então você precisa usá-lo, não é integrador.
Uma pergunta melhor é por que você se importa. Desde que seja automatizado e agregue valor, o seu teste é realizado em um teste de unidade, em um teste de aceitação, em um teste de fumaça ou em um teste funcional?
No meu trabalho, atualmente alavancamos a estrutura de teste de unidade para fazer o ATDD (Acceptance Test Driven Development). Alguns testes são integrativos, outros não. Quase nenhum deles é teste de unidade, mas não nos importamos desde que:
Atualizar
É tudo uma questão de custo e benefício. Quanto mais partes móveis você tiver, maior o risco de ter um teste não determinístico. Os testes de unidade clássicos têm a menor quantidade de partes móveis e, portanto, a menor chance de serem não determinísticos. A desvantagem é que você não está testando os pontos de integração (código, banco de dados, fs, rede etc.). É útil ter tudo isso coberto em um teste, desde que o risco de falsa falha ou sucesso seja baixo o suficiente.
Os testes fornecem valor naquilo que eles não fazem. A chave é com que freqüência você terá falhas e sucesso falsos. Se eu tenho falhas falsas por 2 horas todos os meses porque essa é a janela de manutenção da rede, o valor dos testes é aparente. Quando eles falham, é óbvio que há algo errado com o recurso de rede, não um teste específico. E agora você tem mais cobertura de teste precisamente porque está testando esses pontos de integração.
fonte
Eu acho que depende de onde os dados vêm. Se você estiver criando suas condições de teste no prefixo, acho razoável chamá-lo de teste de unidade. Caso contrário, você terá argumentos minuciosos sobre o que conta como "pré-existente" para um teste de unidade. Assim como seus testes de unidade de banco de dados dependem da existência de tabelas de banco de dados e assim por diante, os testes de unidade fora do banco de dados dependem de coisas como definições de classe e, muitas vezes, instâncias dessas clssses. Isso não é ruim, é realista.
fonte
Eu consideraria isso um teste de integração:
No entanto, testes como você descrevem são inestimáveis. Recentemente, começamos a adicionar testes assim, para testar procedimentos armazenados impossíveis de serem testados manualmente em determinados ambientes. Não conheço outra maneira de ter testes automatizados para procedimentos armazenados.
Portanto, esses testes são uma ótima idéia, mas os chame de testes de integração - use uma categoria ou sufixo de nome para diferenciá-los dos testes de unidade regulares. Dessa forma, você pode sinalizar falhas de teste de integração de maneira diferente das falhas de teste de unidade em sua automação de construção.
fonte
SqlCommand
classe funcione e que o transporte TCP funcione. Ainda não me enganei sobre isso.Onde o teste é executado? No banco de dados ou por meio de equipamento de teste baseado em código (JUnit)?
No banco de dados, é provável que seja um teste de unidade (por ser autônomo); o equipamento de teste do tipo JUnit se conecta a um banco de dados externo e, como tal, um teste de integração.
Por que as citações? Os testes de integração não são um tipo de animal que você nunca deve fazer.
Geralmente, acho que a única unidade razoável para um procedimento armazenado é o código de chamada¹ e o procedimento. Então, eu testei a integração do conjunto completo em um conjunto de testes que se parecem com testes de unidade.
Como ele permite que você divida os testes. Os testes de integração levam mais tempo para serem executados, exigem configuração adicional e provavelmente acesso a um recurso compartilhado por muitos testes (o banco de dados, por exemplo).
1) O código de chamada terá testes de unidade adicionais, se necessário.
fonte
Microteste é um termo útil que pode ajudá-lo a contornar o debate sobre terminologia e se o seu teste é um teste de unidade ou não.
Uma definição comum de teste de unidade inclui que o sistema em teste é uma pequena unidade de funcionalidade e você deve poder executar todos os testes na memória, sem a ajuda de sistemas de arquivos, redes ou mecanismos de banco de dados . Se você precisar de um mecanismo de banco de dados real para executá-lo, não será um teste de unidade.
Embora essa definição funcione muito bem para todas as camadas de aplicativos, não é muito útil para a camada de acesso ao banco de dados mais baixa. Temos que reconhecer que é especial. Se seus testes testarem apenas pequenas unidades de funcionalidade de armazenamento / recuperação / atualização / exclusão, seus testes serão claramente tão valiosos quanto os testes de unidade "estritos" escritos nas camadas superiores do seu sistema.
fonte
SELECT
, então não me importo em testá-lo.