Aprenda a Escrever Testes de Coleções com xUnit Assert.Collection (2023)

O xUnit é uma ferramenta de teste de unidade amplamente utilizada entre os desenvolvedores .NET. Entre as várias bibliotecas de asserção disponíveis para o xUnit, o Xunit.Assert é a opção básica para realizar asserções simples. No entanto, quando se trata de testar coleções, a biblioteca de asserção do xUnit pode ser limitada em termos de documentação e clareza das mensagens de erro.

Neste artigo, vamos explorar uma asserção específica do xUnit chamada Assert.Collection, que permite criar testes de coleções claros e significativos em C#. Veremos como essa asserção pode melhorar a legibilidade do código de teste e fornecer mensagens de erro mais úteis em comparação com as asserções básicas do xUnit.

Testando uma lista de eventos

Vamos considerar um exemplo em que o objeto de teste é um agregado de Event Sourcing chamado Project, que possui um método público que retorna uma lista de objetos Event não salvos. Nosso objetivo é validar se:

  1. A lista tem o número correto de eventos.
  2. Os eventos são do tipo esperado.
  3. Os eventos têm o número de versão correto no campo Version.
  4. Os eventos estão na ordem correta.

Aqui está um exemplo de como esse teste poderia ser escrito usando apenas asserções básicas do xUnit:

[Fact]
public void APoorExample()
{
    List<Event> events = _project.UnsavedEvents();
    Assert.Equal(4, events.Count);
    Assert.IsType<ProjectCreatedEvent>(events[0]);
    Assert.IsType<PhraseCreatedEvent>(events[1]);
    Assert.IsType<TranslationUpdatedEvent>(events[2]);
    Assert.IsType<TranslationUpdatedEvent>(events[3]);
    for (var i = 0; i < 4; i++)
    {
        Assert.Equal(i, events[i].Version);
    }
}

Neste exemplo, recuperamos uma lista de eventos do objeto de teste e realizamos várias asserções para validar os critérios mencionados acima. No entanto, se alguma das asserções falhar, a mensagem de erro fornecida será básica e não fornecerá informações úteis sobre o conteúdo real da lista ou o motivo da falha.

Introdução ao Assert.Collection

Para melhorar a legibilidade do código de teste e fornecer mensagens de erro mais úteis, podemos usar a asserção Assert.Collection do xUnit. Essa asserção verifica se o número de itens na lista é igual ao número de inspetores de elementos fornecidos e se todas as asserções passam.

Aqui está como podemos reescrever o teste anterior usando a asserção Assert.Collection:

[Fact]
public void ABetterExample()
{
    Assert.Collection(_project.UnsavedEvents(),
        e =>
        {
            Assert.IsType<ProjectCreatedEvent>(e);
            Assert.Equal(0, e.Version);
        },
        e =>
        {
            Assert.IsType<PhraseCreatedEvent>(e);
            Assert.Equal(1, e.Version);
        },
        e =>
        {
            Assert.IsType<TranslationUpdatedEvent>(e);
            Assert.Equal(2, e.Version);
        },
        e =>
        {
            Assert.IsType<TranslationUpdatedEvent>(e);
            Assert.Equal(3, e.Version);
        });
}

Neste exemplo, usamos a asserção Assert.Collection para verificar se a lista de eventos não salvos do objeto de teste atende aos critérios especificados. As asserções são agrupadas de forma clara e concisa, facilitando a compreensão do que está sendo testado para cada elemento da lista.

Mensagens de erro mais úteis

Uma das principais vantagens de usar a asserção Assert.Collection é que ela fornece mensagens de erro mais úteis em comparação com as asserções básicas do xUnit. Vamos ver alguns exemplos de mensagens de erro que podemos obter ao usar a asserção Assert.Collection.

Se a lista tiver um número de itens menor do que o esperado, a mensagem de erro será a seguinte:

Xunit.Sdk.CollectionException
Assert.Collection() Failure
Collection: [ ProjectCreatedEvent { Type = "ProjectCreatedEvent", Version = 0, ... }, PhraseCreatedEvent { Type = "PhraseCreatedEvent", Version = 1, ... }, TranslationUpdatedEvent { Type = "TranslationUpdatedEvent", Version = 2, ... }]
Expected item count: 4
Actual item count: 3
at ABetterExample() in ProjectTest.cs:line 4

Essa mensagem de erro mostra o conteúdo real da lista e informa claramente que o número de itens é menor do que o esperado.

Se houver uma incompatibilidade de tipo de evento, a mensagem de erro será semelhante a esta:

Xunit.Sdk.CollectionException
Assert.Collection() Failure
Collection: [ ProjectCreatedEvent { Type = "ProjectCreatedEvent", Version = 0, ... }, PhraseCreatedEvent { Type = "PhraseCreatedEvent", Version = 1, ... }, PhraseCreatedEvent { Type = "PhraseCreatedEvent", Version = 2, ... }, TranslationUpdatedEvent { Type = "TranslationUpdatedEvent", Version = 3, ... }]
Error during comparison of item at index 2
Inner exception: Assert.IsType() Failure
Expected: TranslationUpdatedEvent
Actual: PhraseCreatedEvent
at ProjectTest.<>c.<ABetterExample>b__6_2(Event e) in ProjectTest.cs:line 17

Essa mensagem de erro mostra o conteúdo real da lista, menciona o índice do item em que a asserção falhou e exibe a saída dessa asserção específica. Isso facilita a identificação do problema e a correção do comportamento sem a necessidade de depurar o teste.

Melhores práticas de teste

Em minha opinião pessoal, é mais eficaz testar um único aspecto por caso de teste, em vez de vários aspectos em um único caso de teste. Ao dividir nossos testes em casos separados para versões de eventos e tipos de eventos, podemos simplificar o código e deixar sua intenção mais clara.

Aqui estão os exemplos mais concisos até agora, reduzindo o número de linhas em comparação com a versão original:

[Fact]
public void Project_WithUnsavedEvents_HasEventVersions() => Assert.Collection(_project.UnsavedEvents(),
    e => Assert.Equal(0, e.Version),
    e => Assert.Equal(1, e.Version),
    e => Assert.Equal(2, e.Version),
    e => Assert.Equal(3, e.Version));

[Fact]
public void Project_WithUnsavedEvents_HasEventTypes() => Assert.Collection(_project.UnsavedEvents(),
    e => Assert.IsType<ProjectCreatedEvent>(e),
    e => Assert.IsType<PhraseCreatedEvent>(e),
    e => Assert.IsType<TranslationUpdatedEvent>(e),
    e => Assert.IsType<TranslationUpdatedEvent>(e));

Esses exemplos são mais concisos e deixam claro o que está sendo testado em cada caso. Se o comprimento da lista tiver uma importância semântica significativa, podemos criar um caso de teste adicional para validar explicitamente esse critério.

[Fact]
public void Project_WithUnsavedEvents_HasCorrectCount() => Assert.Equal(4, _project.UnsavedEvents().Count);

Essa abordagem de teste mais granular pode facilitar a manutenção do código de teste e a identificação de problemas específicos.

Conclusão

Neste artigo, exploramos a asserção Assert.Collection do xUnit e como ela pode ser usada para escrever testes de coleções mais claros e significativos em C#. Vimos como essa asserção melhora a legibilidade do código de teste e fornece mensagens de erro mais úteis em comparação com as asserções básicas do xUnit.

Ao usar a asserção Assert.Collection, podemos agrupar as asserções por elemento da lista, facilitando a compreensão do que está sendo testado. Além disso, as mensagens de erro fornecidas pela asserção Assert.Collection são mais descritivas e ajudam a identificar problemas específicos sem a necessidade de depuração.

Espero que este artigo tenha sido útil para você entender como escrever testes de coleções com o xUnit Assert.Collection. Com essa técnica, você pode melhorar a qualidade dos seus testes e facilitar a manutenção do código de teste.

References

Top Articles
Latest Posts
Article information

Author: Gov. Deandrea McKenzie

Last Updated: 10/01/2024

Views: 5909

Rating: 4.6 / 5 (46 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Gov. Deandrea McKenzie

Birthday: 2001-01-17

Address: Suite 769 2454 Marsha Coves, Debbieton, MS 95002

Phone: +813077629322

Job: Real-Estate Executive

Hobby: Archery, Metal detecting, Kitesurfing, Genealogy, Kitesurfing, Calligraphy, Roller skating

Introduction: My name is Gov. Deandrea McKenzie, I am a spotless, clean, glamorous, sparkling, adventurous, nice, brainy person who loves writing and wants to share my knowledge and understanding with you.