È ragionevole strutturare i test unitari in una classe per l'esecuzione dei test e uno per la configurazione?

3

Durante la scrittura di unit test per classi (specialmente quando si utilizza DI e mock) ultimamente ho spesso trovato utile strutturare i miei test su una classe che esegue effettivamente i test e una responsabile per l'installazione, che mi aiuta a mantenere i miei test puliti e leggibili .

La classe di test avrà il seguente aspetto

public class MyFooBarTests
{
    MyFooBarTestFixture _testFixture = new MyFooBarTestFixture();

    [SetUp]
    public void SetUp()
    {
        _testFixture.SetUp();
    }

    [Test]
    public void ATest()
    {
        _testFixture.GivenRepositoryReturnsPi();
        _testFixture.CallMyFancyMethod();
        _testFixture.AssertQuxBaxIs(3.14159);
    }
}

e quello che chiamo test fixture sarà simile a questo

internal class MyFooBarTestFixture
{
    private Mock<IRepository> _repositoryMock;
    private MyFooBar _cut;

    public void SetUp()
    {
        SetUpRepositoryMock(); // elided
        SetUpCut();
    }

    private void SetUpCut()
    {
        _cut = new MyFooBar(_repositoryMock.Object);
    }

    public void GivenRepositoryReturnsPi()
    {
        _repositoryMock.Setup(r => r.GetValue()).Returns(Math.PI);
    }

    public void CallMyFancyMethod()
    {
        _cut.MyFancyMethod();
    }

    public void AssertQuxBaxIsEqual(double expectedValue)
    {
        Assert.That(_cut.QuxBaz, Is.EqualTo(expectedValue)); // elided correct floating point comparison
    }
}

Dal mio punto di vista, questa separazione è davvero utile. Quando osservi la classe dei test, è chiaro come cosa fanno i test, mentre i dettagli di come sono fatti sono nascosti e ben incapsulati nel dispositivo di prova. Il dispositivo di prova a sua volta ha metodi accurati e brevi.

Quali sono gli svantaggi di organizzare i miei test unitari in questo modo?

Alcuni pensieri:

  • Sono consapevole che alcuni test richiederanno un trattamento speciale in questo paradigma
  • Quando ci sono un bel po 'di mock, il dispositivo di test perderà la coesione, ma questo potrebbe essere uno spunto per il fatto che il componente in prova lo fa comunque molto
  • L'emergere di questo schema è un segno che le mie classi stanno già facendo molto?
  • Il test del nome potrebbe essere fuorviante? Da un punto di vista tecnico è ragionevole, poiché in altri campi ingegneristici è installato un apparecchio di prova per eseguire i test, ma non esegue necessariamente i test stessi. Ad ogni modo, nello sviluppo del software, il termine potrebbe sollevare aspettative non soddisfatte da ciò che chiamo test fixture.
posta Paul Kertscher 11.12.2017 - 08:41
fonte

2 risposte

3

È un buon paradigma e anche "sì" il tuo nome è fuorviante. In realtà è un Test Helper . Non è utile solo nell'impostazione, ma è utile anche per la verifica (in generale, Assert.cs in NUnit si adatta a questo schema).

Il vantaggio non è limitato a rendere il tuo codice di prova molto leggibile (valido per prova come documentazione ). Consente inoltre di scrivere test contro questi metodi di aiuto. Pertanto, viene raggiunta la localizzazione dei difetti .

Secondo gli inconvenienti, non riesco a trovare quelli concreti. L'unica cosa che riesco a vedere è che dopo aver ottenuto questi aiutanti, potresti volerli usare in diversi casi di test. Questo è il posto dove le cose si complicano. Se non li organizzi attentamente, questi aiutanti si ingrassano facilmente. Quindi

Più modelli di unità, checkout xTest di test di identità: codice di test di refactoring

    
risposta data 11.12.2017 - 09:30
fonte
-1

A seconda della lingua, questo non è l'unico modo per separare quel tipo di codice. In .NET esiste il concetto di classi parziali che possono raggiungere lo stesso risultato. Esistono anche regioni di codice, ma queste stanno cadendo in disgrazia per diversi motivi .

Da un punto di vista personale, tendo ad aspettare che l'oggetto di impostazione debba essere riutilizzato in un'altra serie di test (si pensi: regola di tre ) prima di metterli in una classe separata - YMMV.

Tieni presente che una classe senza logica è un noto odore di codice . Assicurati che la classe helper stia effettivamente facendo qualcosa e non sia solo una serie di proprietà.

Una buona regola empirica per impedire che le classi di test diventino ingombranti è assicurarsi che rispecchino le classi sottostanti. Un vantaggio di questo è che puoi vedere a colpo d'occhio quali classi devono ancora essere testate. Naturalmente una classe enorme potrebbe fornire una grande classe di test, ma questi dovrebbero essere l'eccezione.

    
risposta data 11.12.2017 - 10:09
fonte

Leggi altre domande sui tag