Os testes são difíceis
Eles são difíceis de escrever, de manter e é ainda mais difícil estabilizar um teste superficial. No Avance Network, temos um orgulho especial em nossa capacidade (na maior parte) de fornecer novos recursos à produção e fazê-lo com a confiança que somente testes confiáveis podem oferecer. Esses testes desempenham um papel crucial em nossa capacidade de fornecer código rápido, bom e estável, garantindo que nenhum erro de regressão seja introduzido no processo. É crucial, portanto, não apenas manter bons conjuntos de testes (testes de unidade, integração e e2e), mas também corrigir qualquer teste que se comporte incorretamente (testes inadequados).
Temos um ambiente especial para facilitar a integração e os testes e2e chamados ambiente de simulação (é apenas um dos conjuntos de ferramentas que temos para esse fim). Este é um conjunto dedicado de servidores que usamos para simular nosso ambiente de produção. Implantamos todas as novas versões de nossos serviços nesse ambiente antes de implantarmos em produção e executamos testes que verificam novos fluxos de código, regressão e interoperabilidade para outros serviços.
Para escrever um teste eficaz para um novo recurso, às vezes precisamos configurar o ambiente com entidades necessárias para o recurso que estamos testando. Se, por exemplo, nosso novo recurso é registrar um carro em um proprietário (uma entidade Pessoa). Antes de executar os testes, precisamos das entidades necessárias, um carro e uma pessoa em nosso banco de dados. Não estamos tentando testar um fluxo para criar um carro novo ou uma nova pessoa nesse cenário. Portanto, não há necessidade de criar explicitamente o carro e / ou as entidades da pessoa no teste antes que o cenário de teste real ocorra. E para tornar nossos testes o mais claro e sucinto possível - não queremos criar esses dados explicitamente em todos os testes.
Más Práticas
Portanto, era uma prática comum (embora ruim) ter dados preexistentes nos quais confiaríamos para executar testes (para todo o ambiente de simulação!). Isso levou a dois grandes problemas (interconectados):
- Sem isolamento de teste - um teste que exclui por engano alguns ou todos os dados preexistentes, por exemplo, faria isso para todos os testes executados nesse ambiente
- Testes esquisitos - testes executados simultaneamente estão criando, excluindo e geralmente alterando dados que afetam outras pessoas, o que, por sua vez, falharia nos testes sem uma boa razão - o que torna muito difícil analisar e corrigir um teste com falha
Resolvemos esse problema criando os dados necessários antes dos testes em uma classe de teste e excluindo-os após a execução do teste. O que mitigou um pouco o problema - não apenas os testes da mesma classe foram interconectados, mas também adicionaram clichê à classe de teste. Agora, uma classe de teste era algo parecido (assumindo que sejam entidades geradas automaticamente pelo Scalike para as tabelas relevantes):
ScalaTest:
Especificações2:
Nota: No entanto, no Specs2, é possível obter uma solução melhor usando a característica 'Scope' da seguinte forma:
Inserir padrão de empréstimo
Encontramos esse padrão pela primeira vez ao usar o ScalaTest e passamos rapidamente a usá-lo também no Specs2 (como a maioria dos nossos testes está escrita no Specs2). Na documentação do ScalaTest para compartilhar dispositivos elétricos:
“Um acessório de teste é composto pelos objetos e outros artefatos (arquivos, soquetes, conexões com o banco de dados, etc.) que os testes usam para realizar seu trabalho. Quando vários testes precisam trabalhar com os mesmos equipamentos, é importante tentar evitar a duplicação do código do equipamento nesses testes. ”
“Se você precisar passar um objeto de fixação em um teste e executar a limpeza no final do teste, precisará usar o padrão de empréstimo”
O que significa que podemos usar acessórios para configurar 'artefatos' para os testes, promovendo o princípio DRY, minimizando a duplicação de código. Também é uma boa maneira de reduzir o clichê ao escrever testes. Então, nós escrevemos essa característica simples:
ScalaTest:
Ao misturar essa característica em nossa classe de teste, obtemos o seguinte código:
A versão Specs2 do Loan Pattern é um pouco mais complexa, pois adicionamos mais alguns sinos e assobios para facilitar a criação dessas entidades em nosso domínio. Estamos usando o Scalike para criar as entidades no banco de dados MySQL, e precisamos de um controle um pouco mais refinado sobre a sessão que estamos usando, nome do banco de dados etc '.
Especificações2: