Testes Automatizados em C# com xUnit e NUnit: Guia Prático

Imagine poder garantir que cada parte do seu código funcione perfeitamente, mesmo após refatorações, adições de novas funcionalidades ou correções de bugs. É aí que entram os testes automatizados com xUnit e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. NUnit: duas ferramentas poderosas para escrever testes de unidade🧪 Testes de Unidade para Tratamento de Erros: Previna Falhas Futuras!🧪 Testes de Unidade para Tratamento de Erros: Previna Falhas Futuras!Descubra como implementar testes de unidade focados em tratamento de erros, evitando surpresas em produção e garantindo sistemas confiáveis e robustos. em C#. Neste artigo, vamos explorar como começar a usar cada framework, mostrar exemplos práticos e aprofundar nos conceitos que fazem seus testes serem profissionais.

Além disso, você aprenderá técnicas avançadas usadas em projetos reais📁 Portfólio .NET: Projetos que Impressionam Recrutadores!📁 Portfólio .NET: Projetos que Impressionam Recrutadores!Descubra dicas práticas e estratégicas para criar um portfólio .NET que demonstra expertise e atrai recrutadores, com projetos reais e arquitetura limpa., como testes parametrizados, simulação de falhas controladas e integração com pipelines de CI/CD. Vamos além do básico, explorando como escrever testes que validam cenários complexos e garantem a qualidade do seu software.

Tabela de Conteúdo🔗

Motivação: Por que Criar Testes?🔗

Testes de unidade🧪 Testes de Unidade para Tratamento de Erros: Previna Falhas Futuras!🧪 Testes de Unidade para Tratamento de Erros: Previna Falhas Futuras!Descubra como implementar testes de unidade focados em tratamento de erros, evitando surpresas em produção e garantindo sistemas confiáveis e robustos. trazem confiança ao seu projeto. Quando você sabe que cada pedaço do código está validado, fica muito mais fácil refatorar, adicionar novas funcionalidades ou até integrar com outros sistemas. Testes bem estruturados reduzem o risco de regressões (quando algo que funcionava antes, para de funcionar), além de ajudarem a documentar o comportamento esperado do seu software.

Visão Geral: xUnit vs. NUnit🔗

xUnit e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. NUnit são dois frameworks populares para🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! testes em C#. Ambos oferecem:

A principal diferença está em algumas convenções🤝 GitHub Básico: Versionamento para Iniciantes!🤝 GitHub Básico: Versionamento para Iniciantes!Descubra como o GitHub facilita colaboração, versionamento e organização de código com este tutorial prático e essencial para desenvolvedores iniciantes. de nomenclatura e em detalhes de estrutura de testes. De forma geral:

Se você está começando, escolher um ou outro não fará grande diferença. O importante é escrever bons testes, independente do framework.

Configuração e Estrutura de Projeto🔗

Para configurar um projeto de testes, você pode usar o dotnet CLI ou o Visual Studio🛠️ Instalação do Visual Studio: Prepare sua Nave para Decolar!🛠️ Instalação do Visual Studio: Prepare sua Nave para Decolar!Prepare seu ambiente de desenvolvimento com o Visual Studio em uma aventura C#. Este tutorial prático ensina a instalar, configurar e personalizar sua IDE.. Seguem dois exemplos usando o .NET CLI:

# Criar um novo projeto de teste com xUnit
dotnet new xunit -o MinhaApp.Tests
# Ou criar um novo projeto de teste com NUnit
dotnet new nunit -o MinhaApp.Tests

Depois, você pode adicionar referências🏗️ Classes vs. Structs: Quando Usar Cada Uma (e Não Quebrar a Cabeça)!🏗️ Classes vs. Structs: Quando Usar Cada Uma (e Não Quebrar a Cabeça)!Descubra como escolher entre classes e structs em C#. Aprenda sobre alocação de memória, passagem por valor e referência, e performance nesta explicação clara. ao projeto principal (aquele que contém o código que você quer testar) e instalar pacotes adicionais se necessário.

Em termos de estrutura:

Primeiros Exemplos de Testes com xUnit🔗

No xUnit, cada método de teste é marcado com o atributo📜 Atributos Customizados: Metadados que Guiam seu Código!📜 Atributos Customizados: Metadados que Guiam seu Código!Descubra como atributos customizados potencializam a organização do código, facilitam auditorias e testes, e garantem eficiência. [Fact]. Confira um exemplo simples:

using Xunit;
public class CalculadoraTests
{
    [Fact]
    public void Somar_DeveRetornarResultadoCorreto()
    {
        // Arrange
        var calculadora = new Calculadora();
        // Act
        var resultado = calculadora.Somar(2, 3);
        // Assert
        Assert.Equal(5, resultado);
    }
}

Repare que criamos um cenário (Arrange), executamos a ação (Act) e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. verificamos o resultado (Assert). O xUnit executa cada teste de forma isolada, garantindo que não haja interferência entre testes.

Primeiros Exemplos de Testes com NUnit🔗

No NUnit, o atributo📜 Atributos Customizados: Metadados que Guiam seu Código!📜 Atributos Customizados: Metadados que Guiam seu Código!Descubra como atributos customizados potencializam a organização do código, facilitam auditorias e testes, e garantem eficiência. principal é [Test]. O fluxo é parecido, mas📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. mudam alguns nomes:

using NUnit.Framework;
public class CalculadoraTests
{
    [Test]
    public void Somar_DeveRetornarResultadoCorreto()
    {
        // Arrange
        var calculadora = new Calculadora();
        // Act
        var resultado = calculadora.Somar(2, 3);
        // Assert
        Assert.AreEqual(5, resultado);
    }
}

O conceito é o mesmo. Você prepara o objeto, executa a ação desejada e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. verifica os resultados.

Boas Práticas de Nomenclatura de Testes🔗

Independente do framework, dar nomes claros aos métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. de teste é fundamental. Exemplos:

  • Metodo_Condicao_EfeitoEsperado()
  • Somar_ValoresPositivos_ResultadoCorreto()

Ou ainda:

  • DadoDoisNumerosQuandoSomarEntaoRetornaSomaCorreta()

O objetivo é que qualquer pessoa que olhe para o método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. de teste entenda facilmente o que está sendo validado.

Asserções e Métodos Úteis🔗

Nos testes, utilizamos métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. de asserção para🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! verificar se o resultado é o esperado.

Exemplo com xUnit

Exemplo com NUnit

Usando Coleções e Categorias🔗

Também é comum usar “categorias” para agrupar🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. testes (por exemplo, [Trait("Categoria", "Unitário")] no xUnit ou [Category("Unitário")] no NUnit). Assim, você pode executar🔍 Comandos: Desacople Ações dos Botões!🔍 Comandos: Desacople Ações dos Botões!Aprenda a implementar comandos em C# para desacoplar lógica e interface usando MVVM, com exemplos práticos e dicas para melhor testabilidade e manutenção. apenas um conjunto específico quando precisar.

Testando Código Assíncrono🔗

Ambos os frameworks suportam métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. assíncronos. Basta retornar Task no método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. de teste e fazer o await⚡ Async/Await: Programação Assíncrona sem Callbacks!⚡ Async/Await: Programação Assíncrona sem Callbacks!Aprenda a aplicar Async/Await em C# para criar aplicações responsivas, evitar travamentos e melhorar a escalabilidade com exemplos práticos e dicas essenciais. normalmente:

// xUnit
[Fact]
public async Task Exemplo_DeveExecutarAcaoAssincrona()
{
    await Task.Delay(10);
    Assert.True(true);
}
// NUnit
[Test]
public async Task Exemplo_DeveExecutarAcaoAssincrona_NUnit()
{
    await Task.Delay(10);
    Assert.IsTrue(true);
}

Dessa forma, você mantém a legibilidade do teste sem se preocupar com callbacks ou blocos try-catch extras.

Casos de Teste do Mundo Real🔗

Teste de Exceções

[Fact]
public void Dividir_PorZero_DeveLancarDivideByZeroException()
{
    var calc = new Calculadora();
    Assert.Throws<DivideByZeroException>(() => calc.Dividir(10, 0));
}

Testes Assíncronos

[Fact]
public async Task BuscarUsuario_QuandoExistir_RetornaObjetoUsuario()
{
    var usuarioService = new UsuarioService();
    var resultado = await usuarioService.BuscarPorId(1);
    Assert.NotNull(resultado);
    Assert.IsType<Usuario>(resultado);
}

Testes com Mock Objects

[Fact]
public void ProcessarPagamento_DeveChamarGatewayCorretamente()
{
    var mockGateway = new Mock<IPagamentoGateway>();
    var processor = new PagamentoProcessor(mockGateway.Object);
    processor.Processar(new Pagamento(100.00m));
    mockGateway.Verify(g => g.EnviarPagamento(100.00m), Times.Once);
}

Testes Parametrizados com Theory e TestCase🔗

xUnit (Theory + InlineData)

[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, 1, 0)]
[InlineData(100, 200, 300)]
public void Somar_VariosNumeros_RetornaSomaCorreta(int a, int b, int esperado)
{
    var resultado = _calc.Somar(a, b);
    Assert.Equal(esperado, resultado);
}

NUnit (TestCase)

[Test]
[TestCase(1, 2, 3)]
[TestCase(-1, 1, 0)]
[TestCase(100, 200, 300)]
public void Somar_VariosNumeros_RetornaSomaCorreta(int a, int b, int esperado)
{
    var resultado = _calc.Somar(a, b);
    Assert.AreEqual(esperado, resultado);
}

Fixtures: Compartilhando Contexto Entre Testes🔗

xUnit (Class Fixture)

public class DatabaseFixture : IDisposable
{
    public BancoDados Banco { get; }
    public DatabaseFixture()
    {
        Banco = new BancoDados();
        Banco.Inicializar();
    }
    public void Dispose()
    {
        Banco.Fechar();
    }
}
public class TestesBancoDados : IClassFixture<DatabaseFixture>
{
    private readonly DatabaseFixture _fixture;
    public TestesBancoDados(DatabaseFixture fixture)
    {
        _fixture = fixture;
    }
    [Fact]
    public void TesteConsulta()
    {
        var resultado = _fixture.Banco.ExecutarConsulta("SELECT...");
        Assert.NotNull(resultado);
    }
}

Integração com CI/CD Pipelines🔗

Exemplo GitHub Actions

name: .NET Tests
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:

      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 8.x
  • name: Run tests
run: dotnet test --configuration Release --logger "trx;LogFileName=test-results.trx"

Práticas Recomendadas por Experts🔗

1. Nomes Descritivos:

UsuarioService_AtualizarEmail_QuandoEmailInvalido_DeveRetornarErroDeValidacao

2. Testes Independentes:

Nunca dependa da ordem de execução

3. Regra 1:1:

1 assert por teste (com exceções💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!Descubra como tratar exceções em C# com práticas eficientes utilizando try/catch. Aprenda a gerenciar erros e aumentar a robustez do seu código. justificáveis)

4. Dados de Teste Realistas:

var cpfValido = GeradorCpf.Validar(); // Não usar "111.111.111-11"

5. Avoid Magic Numbers:

const int LimiteIdade = 18; // Em vez de usar 18 diretamente

6. Testes de Performance⏱️ Testes de Performance: Garanta Velocidade Além da Funcionalidade!⏱️ Testes de Performance: Garanta Velocidade Além da Funcionalidade!Descubra como medir, diagnosticar e otimizar performance em aplicações .NET com dicas práticas e ferramentas essenciais para devs.:

[Fact]
public void ProcessamentoGrande_DeveConcluirEmMenosDe2Segundos()
{
    var stopwatch = Stopwatch.StartNew();
    Processador.ExecutarTarefaPesada();
    stopwatch.Stop();
    Assert.True(stopwatch.ElapsedMilliseconds < 2000);
}

7. Relatório de Cobertura:

dotnet test --collect:"XPlat Code Coverage"

Com xUnit ou NUnit, o segredo é escrever testes claros, organizados e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. que cubram os cenários📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. mais importantes do seu software. Dessa forma, você garante a manutenção de alta qualidade, melhora a confiança no código e ainda ganha tranquilidade ao evoluir seu projeto🤝 GitHub Básico: Versionamento para Iniciantes!🤝 GitHub Básico: Versionamento para Iniciantes!Descubra como o GitHub facilita colaboração, versionamento e organização de código com este tutorial prático e essencial para desenvolvedores iniciantes..

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Compartilhar artigo

Artigos Relacionados