Test unitari: asserzioni posticipate con Linq

18

Va bene aggiungere asserzioni posticipate come questa

var actualKittens = actualKittens.Select(kitten => {
    Assert.IsСute(kitten);
    return kitten
});

Perché? Quindi posso ripetere una sola volta anche con le dichiarazioni che prevedono una raccolta materializzata, ad esempio:

CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

Inoltre, potrebbe non essere solo Seleziona ma un metodo con iteratore definito e con molti controlli e logica (ad esempio alcuni conteggi e filtri).

Il seme del dubbio è la complessità della lettura e del debug di tale codice in caso di fallimento del test.

    
posta SerG 02.07.2017 - 19:29
fonte

1 risposta

37

Is it ok to add deferred assertions like this [..]

No , non lo è. Perché? Perché se per qualsiasi motivo rimuovi la seconda affermazione, il test diventerebbe ancora verde e penseresti che funzioni ancora, ma non lo farà poiché la raccolta non verrà enumerata. Se hai due o più affermazioni indipendenti, continueranno a fare il loro lavoro anche se disabiliti uno di loro.

Considera questa combinazione:

Assert.IsTrue(actualKittens.All(x => x.IsCute());
CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

Ora, anche se si disabilita o si rimuove una delle affermazioni, l'altra continuerà a svolgere il proprio lavoro. Inoltre, se dimentichi per materializzare la raccolta, potrebbe richiedere più tempo per essere eseguita, ma continuerà a funzionare. I test indipendenti sono più robusti e affidabili.

C'è anche un secondo no . Non sono sicuro di come altri framework lo gestiscano, ma se utilizzi la piattaforma MS Test non sapresti quale test è fallito. Se fai doppio clic sul test non riuscito, ti mostrerà CollectionAssert come fallito, ma in realtà è stato il% co_de nidificato a essere andato storto e sarà estremamente difficile eseguire il debug. Ecco un esempio:

    [TestMethod]
    public void TestMethod()
    {
        var numbers = new[] { 1, 2, 3 }.Select(x =>
        {
            Assert.Fail("Wrong number.");
            return x;
        });

        // This will fail and you won't be sure why.
        CollectionAssert.AreEqual(new[] { 1, 2, 3 }, numbers.ToList()); 

    }

Questo significa che il primo test è in realtà inutile perché non aiuta a trovare un bug. Non sai se ha fallito perché un numero non era valido o perché entrambe le collezioni erano diverse.

Why? So I can iterate just once even with statements expecting materialized collection

Mi chiedo perché ti importa di questo? Questi sono test unitari. Non devi ottimizzare ogni bit di questi e di solito i test non richiedono milioni di articoli, quindi le prestazioni non dovrebbero essere un problema.

Avrai bisogno di mantenere tali test quindi perché dovresti renderli più complessi del necessario? Scrivi affermazioni semplici che funzionano.

    
risposta data 02.07.2017 - 19:57
fonte

Leggi altre domande sui tag