C# - Usando NUnit (testes unitários)


Embora o Visual Studio tenha embutido um recurso para realizar testes unitários neste artigo eu vou mostrar como usar o NUnit.

O NUnit é um framework para testes unitários para todas as linguagens da plataforma .NET. Inicialmente portado do JUnit (do Java), a versão de produção atual, a versão 2.6, é a sétima versão principal desta ferramenta de teste unitários para a plataforma .NET. Ele é inteiramente escrito na linguagem C# e foi completamente redesenhado para tirar proveito de muitos recursos das linguagens da plataforma .NET, como por exemplo, atributos personalizados e as capacidades de reflexão.

O Teste de unidade ou Teste Unitário é a fase do processo de teste em que se testam as menores unidades de software desenvolvidas (pequenas partes ou unidades do sistema). O alvo são os métodos dos objetos ou módulos/funções ou mesmo pequenos trechos de código. O objetivo é encontrar falhas de funcionamento em uma pequena parte do sistema funcionando independentemente do todo.(wikipedia)

Os testes de unidade são feitos pelo próprio programador geralmente usando o método caixa branca ou funcional. Eles são criados durante a fase de desenvolvimento ou no seu inicio. O objetivo dos testes unitário é testar a menor funcionalidade existente do software, ou seja, isolar parte dos códigos e métodos, e analisar se essas funcionalidades tenham o retorno esperado mediando a um valor informado.

Você pode baixar a última versão disponível do NUnit neste link: http://nunit.org/index.php?p=download

Após baixar o executável a instalação é simples e requer apenas alguns segundos.

Após a instalação abrindo o NUnit iremos visualizar a seguinte interface:

Depois de iniciar o NUnit ja podemos abrir um projeto na forma de um arquivo DLL ou EXE em que todos os casos de teste de unidade serão executados. Para isso, clique no menu File e selecione Open Project, agora escolha a DLL ou arquivo EXE e o processo de Testes Unitários estará pronto para ser executado.

O NUnit realiza testes unitários na plataforma .NET em que todo o aplicativo é isolado em diversos módulos. Cada módulo é testado de forma independente para assegurar que o objetivo seja cumprido. O framework NUnit atende uma gama de atributos que são usados durante testes de unidade. Eles são usados para definir Test-Fixture, métodos de ensaio, ExpectedException e também para ignorar métodos.

NOTA: O NUnit só vai abrir um assembly (EXE ou DLL) que foram desenvolvidos sob a métodologia Test Driven Project.

Vejamos a definição de alguns atributos usados para realização de testes unitários com o NUnit e depois irermos preparar um projeto para ser usado com esta ferramenta.

Atributo TestFixture

O atributo TestFixture é uma indicação de que uma classe contém métodos de teste. Quando você menciona esse atributo para uma classe em seu projeto, a aplicação Test Runner irá procurar por métodos de testes. O código a seguir ilustra o uso deste atributo:

using NUnit.Framework;
using System.Text;

namespace UNitTestando
{
    [TestFixture]
    public class Program
    {
    }
}

Atributo Test

O atributo de Test indica que um método dentro de um Testfixture deve ser executado pela aplicação Test Runner. O método deve ser público e retornar void.

using NUnit.Framework;
using System.Text;

namespace UNitTestando
{
[TestFixture]
  public class Program
  {
     [Test]
     public void Test()
     {
        ...
      }
   }
}

Classse Assert

A classe Assert é usada para confirmar se os casos de testes estão produzindo o resultado esperado ou não usando métodos auxiliares como AreEqual() ou AreNotEqual().

Atributo ExpectedException

Você pode fortalecer o seu código para tratar várias exceções usando blocos try/catch. Mas em algumas circustâncias você quer ter certeza de que uma exceção vai ocorrer. Para contornar este problema você pode usar o atributo ExpectedException conforme abaixo:

[TestFixture]
public class Program
{
[Test]
  [ExpectedException(typeof(DivideByZeroException))]
  public void Test()
  {
     int i=10,j=0,x;
     x = i / j;
  }
}

Atributo Ignore

Estea atributo é requerido para indicar que o teste não deverá ser executado em um método particular.

public class Program
{
    [Test]
    [Ignore("este método não será executado")]
    public void Test()
    {
         ...
    }
}

Criando um projeto para ser processado pelo NUnit

Vamos criar um pequeno projeto para mostrar o funcionamento do NUnit.

Abra o Visual C# 2010 Express Edition e no menu FIle clique em New Project;

Selecione o projeto do tipo Class Library e informe o nome Utilitarios;

A seguir renomeie a classe Class1.cs para Desconto.cs e digite o código abaixo nesta classe:

A classe desconto foi projetada para aplicar um percentual de desconto dependendo do valor da venda através do método calculcaDesconto(double ValorVenda);

Após isso podemos dar um Build no projeto e gerar o arquivo Utilitarios.dll na pasta bin\Release da solução.

Criando o projeto para processar os testes unitários

Vamos agora criar o projeto que irá processar o arquivo Utilitarios.dll usando os recursos do NUnit. Será um projeto do tipo Test Drive que depois será aberto pelo NUnit para realizar os testes unitários.

Abra o Visual C# 2010 Express Edition e no menu FIle clique em New Project;

Selecione o projeto do tipo Class Library e informe o nome UnitTestLib;

Vamos agora referenciar a dll nunit.framework no projeto.

No menu Project clique em Add Reference;

A seguir selecione a pasta onde você instalou o NUnit e selecione o arquivo nunit.framework.dll na pasta \framework;

Agora vamos incluir uma referência ao projeto Utilitarios que criamos anteriormente.

No menu Project clique em Add Reference;

A seguir selecione a pasta onde você criou o projeto Utilitarios e selecione o arquivo utilitarios.dll na pasta \bin\Release;

Ao final teremos na nossa solução com as referências conforme mostra a figura a seguir:

Vamos agora criar na solução UnitTestLib uma classe e definir alguns métodos para realizar os testes unitários.

A seguir renomeie a classe Class1.cs para CasoTeste.cs e digite o código abaixo nesta classe:

using System;
using NUnit.Framework;
using Utilitarios;

namespace UnitTestLib
{
    public class CasoTeste
    {

        // Casao de Teste#1: ´Valor das Vendas é Maior ou Igual a 1000 : Verificação
        [Test]
        public void MaiorOuIgual_1000()
        {
            Desconto oDesconto = new Desconto();
            Assert.AreEqual(950, oDesconto.calcularDesconto(1000));
        }

        // Caso de Teste#2: Valor das Vendas e Maior ou Igual a 2000 : Verificação
        [Test]
        public void MaiorOuIgual_2000()
        {
            Desconto obj = new Desconto();
            Assert.AreEqual(1800, obj.calcularDesconto(2000));
        }

        // Caso de Teste#3: Valor das Vendas é Maior ou igual a 5000 : Verificação
        [Test]
        public void MaiorOuIgual_5000()
        {
            Desconto obj = new Desconto();
            Assert.AreEqual(2500, obj.calcularDesconto(5000));
        }

        // Caso de Teste#4: Valor das Vendas é 0 : Verificação
        [Test]
        public void ValorZero()
        {
            Desconto obj = new Desconto();
            try
            {
                obj.calcularDesconto(0);
            }
            catch (Exception ex) { throw ex; }
        }

        // Caso de Teste#5: Valor das Vendas é menor que 1000 : Verificação
        [Test]
        public void AbaixoDe_1000()
        {
            Desconto obj = new Desconto();
            Assert.AreEqual(999, obj.calcularDesconto(999));
        }

        // Caso de Teste#6: Valor das Vendas não produziu os resultados esperados : Verificação
        [Test]
        public void Mil()
        {
            Desconto obj = new Desconto();
            Assert.AreNotEqual(930, obj.calcularDesconto(1000));
        }

        // Caso de Teste#7: Valor das Vendas não produziu os resultados esperados : Verificação
        [Test]
        public void DoisMil()
        {
            Desconto obj = new Desconto();
            Assert.AreNotEqual(1900, obj.calcularDesconto(2000));
        }
    }
}

No código acima definimos 7 casos de testes para realizar os testes unitários no método calculcarDesconto da classe Desconto.

Observe que definimos os imports para NUnit.Framework e para Utilitarios.

Pronto ! Agora podemos compilar (Build) o projeto gerando o arquivo UnitTestLib.dll;

Processando os testes unitários no NUnit

Abra o NUnit e no menu File clique Open Project e selecione o arquivo UnitTestLib.dll;

O aplicativo irá então mostrar-lhe uma visão gráfica de cada classe. Para executar toda a suíte de testes, basta clicar no botão Run.

Se você quiser executar apenas uma instalação de teste ou até mesmo apenas um teste simples, você pode clicar duas vezes na árvore selecionar o método e executá-lo.

Depois de abrir o arquivo de projeto, todos os métodos declarados no arquivo DLL irão aparecer no painel esquerdo conforme abaixo:

Agora clique no botão Run do lado direito para iniciar o teste de unidade.

Pode levar algum tempo para que sejam verificadas todas as condições indicadas nos casos de teste.

Se todos os métodos funcionarem adequadamente, conforme especificado pela condição de testem, então a interface gráfica irá produzir os resultados na barra de progresso verde como a seguir:

No cenário, se o código contiver alguma falha, em seguida, eles são facilmente corrigidas durante o processo de testes NUnit.

A imagem seguinte mostra um problema no método ValorZero() com o sinal da cruz.

No exemplo o relatório indica que todas as implementações dos métodos estão funcionando corretamente, exceto para o método ValorZero() e indica a exceção obtida:

Para obter mais detalhes podemos clicar no ícone - Display souce-code context - teremos o código fonte com a indicação da linha onde o erro ocorreu:

E assim vimos como é muito fácil usar o NUnit para criar testes unitários.

Pegue os projetos aqui: Utilitarios.zip e UnitTestLib.zip

João 5:19 Disse-lhes, pois, Jesus: Em verdade, em verdade vos digo que o Filho de si mesmo nada pode fazer, senão o que vir o Pai fazer; porque tudo quanto ele faz, o Filho o faz igualmente.

João 5:20 Porque o Pai ama ao Filho, e mostra-lhe tudo o que ele mesmo faz; e maiores obras do que estas lhe mostrará, para que vos maravilheis.

João 5:21 Pois, assim como o Pai levanta os mortos e lhes dá vida, assim também o Filho dá vida a quem ele quer.

Referências:


José Carlos Macoratti