Introdução ao framework de testes Microsoft Moles - Artigo Revista . Net Magazine 87
Artigos .NET Introdução ao framework de testes Microsoft Moles - Artigo Revista . Net Magazine 87
O Microsoft Moles permite a simulação de retorno de objetos com o objetivo de facilitar o trabalho com as dependências que os objetos que estão sob testes possuem. Para isso, duas estratégias são utilizadas: objetos dublês do tipo stub e desvio de chamadas de métodos.
Os testes unitários permitem que façamos a validação do funcionamento das nossas classes de forma rápida e descomplicada, garantindo a qualidade do código produzido e minimizando erros que podem ser introduzidos durante manutenções das aplicações.
A utilização de frameworks de testes ajuda muito na construção de testes unitários. A Microsoft Research desenvolveu o Moles, uma biblioteca capaz de implementar objetos dublês do tipo stub para interfaces e classes abstratas, além de permitir o desvio de qualquer método .NET com o intuito de simular retornos de objetos durante a execução dos testes. Neste artigo, iremos ver os principais conceitos envolvendo testes unitários, objetos dublês e como utilizar o Microsoft Moles.
Desde os primórdios, o mundo dos negócios exige do mundo da TI soluções eficazes e eficientes para resolver seus problemas. O ITIL descreve a TI provendo serviços como uma forma dos nossos clientes (ou usuários, termo que utilizamos com mais frequência) terceirizarem seu trabalho e riscos. Como provedores de serviços, devemos fornecê-los com um mínimo de qualidade aceitável.
Várias técnicas têm sido utilizadas para melhorar a qualidade dos produtos criados no desenvolvimento de softwares, principalmente na disciplina de testes, como é o caso do TDD (ou Test Driven Development), BDD (Behavior Driven Development) entre outros. E dentro das técnicas utilizadas, uma das que mais tem tido foco nos últimos anos é o teste unitário.
Testes unitários são um método no qual trechos de código são testados isoladamente para averiguar seu correto funcionamento. O interessante dos testes unitários é que, uma vez escritos, podem ser executados automaticamente, seja através de uma solicitação do próprio desenvolvedor na sua IDE de trabalho, como o Visual Studio, ou durante o processo de compilação dos fontes, num cenário de integração contínua. Este é um dos principais pontos em que percebemos a vantagem de testar isoladamente cada parte do sistema, pois qualquer modificação no seu código pode ser validada para ver se a funcionalidade não foi "quebrada". Além disso, o processo não toma muito tempo do desenvolvedor. É rápido e simples de ser feito, por isso será feito mais vezes.
Hoje vamos explorar um pouco a técnica de testes unitários e conhecer a ferramenta de isolamento de testes Moles, da Microsoft.
TDD (Test Driven Development) é uma técnica de desenvolvimento de software que utiliza bastante o conceito de testes unitários. Ela se baseia na codificação em ciclos (veja figura), partindo da criação do teste unitário que irá validar a funcionalidade, antes mesmo de escrever qualquer classe de negócios, intercalados com a execução destes testes e refactoring de código até que o mesmo se mostre funcional e livre de bugs.
As vantagens dessa abordagem incluem uma detecção de bug precoce, visto que a execução automatizada dos testes é simples e a cobertura de código é total; facilidade na identificação de impactos nas mudanças; melhor design da aplicação, já que com o foco em testes o software é desenvolvido se baseando no uso que o cliente terá dele; produtividade, pois apesar da maior codificação dos testes unitários, o trabalho é feito apenas uma vez e reaproveitado posteriormente, além de uma menor necessidade em se utilizar ferramentas de debug.
Anatomia de um teste unitário
Dentro da plataforma .NET, existem vários frameworks que auxiliam na tarefa de executar isoladamente uma funcionalidade, como o nUnit, xUnit e as ferramentas de testes disponibilizadas no próprio Visual Studio. Nos exemplos deste artigo, iremos utilizar este último.
Em um projeto do tipo "Test Project" no Visual Studio 2010, cada método decorado com o atributo TestMethod dentro de uma classe decorada com o atributo TestClass representa um teste unitário. Cada teste segue um ciclo de atividades para o seu funcionamento. São estes passos a inicialização, execução, verificação e limpeza. Vamos olhar a Listagem 1 para ficar mais fácil de entender cada uma dessas partes.
Listagem 1. Exemplo de estrutura de um teste unitário
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 namespace TesteUnitario
5     [TestClass]
6     public class UnitTest1
8         [TestInitialize]
9         public void Inicializar()
11             // algum código de inicialização da classe, quando necessário
14         [TestMethod]
15         public void CalcularJurosSimples_Capital1000Taxa20PorcentoPeriodo6_Calculado()
17             // 1. inicialização
18             double capital = 1000, taxa = 0.2;
19             int periodo = 6;
20             double jurosEsperados = 1200;
21             var calculadora = new CalculadoraJuros();
22             // 2. execução
23             double resultado = calculadora
24                 .CalcularJurosSimples(capital, taxa, periodo);
25             // 3. verificação
26             Assert.AreEqual(jurosEsperados, resultado);
29         [TestCleanup]
30         public void Limpeza()
32             // 4. algum código de limpeza executado em todos os testes, se necessário
Antes de mais nada, se a classe de testes necessita de algum tipo de inicialização, como preparação de uma base de dados, ou mesmo a criação de objetos globais, o método Inicializar – decorado com o atributo TestInitialize – se encarrega de executar as rotinas necessárias (linhas 8 a 12).
Feito isso, o método de teste deve ser escrito, decorado com o atributo TestMethod. A primeira das quatro partes de um ciclo de testes é a inicialização (linhas 18 a 21), onde os objetos que serão utilizados no teste neste teste são criados. Neste exemplo, não fazemos muita coisa senão declarar as variáveis que serão usadas nos testes e suas atribuições de valores, mas em casos mais complexos onde haja a necessidade de outros objetos (dependências) para a conclusão dos testes, este é o trecho em que eles devem ser preparados. Com a ferramenta de testes do Visual Studio é possível criar um método que seja sempre executado na inicialização do teste unitário, bastando que para isso ele seja decorado com o atributo TestInitialize. O mesmo conceito existe para outros frameworks de testes, como o nUnit, sendo que para este o método deve ser decorado com o atributo SetUp.