Disposizione di test usando il sistema sotto test

5

Ho alcuni test di integrazione sui proc memorizzati. In genere eseguo l'installazione di test utilizzando Dapper. Questo va bene per i casi semplici, ma in alcuni casi per configurare correttamente il sistema sarebbe molto più semplice chiamare i proc memorizzati necessari. Sarebbe più semplice perché alcune entità hanno molte relazioni e vincoli e replicare che in Dapper richiede molto tempo, in più se cambio il sistema devo modificare anche il mio codice di configurazione del test Dapper.

È una buona idea usare il sistema per configurare il sistema per testare o devo mantenere la configurazione del sistema indipendente dal sistema?

Ho aggiunto un semplice esempio di codice, di seguito, (non rappresentativo del mio sistema attuale) per aiutare a chiarire cosa intendo. Nel primo test sto verificando che CreatePerson aggiunga effettivamente un'entità nella tabella Persona. Nel secondo test utilizzo il metodo appena testato, CreatePerson, per configurare il sistema e quindi provare qualcos'altro.

public class When_CreatePerson_is_called
{
    [Fact]
    public void It_should_create_entity()
    {
        // arrange
        var db = new Database();

        // act - testing CreatePerson does what is expected of it
        int id = db.CreatePerson();
        Person p = db.GetPerson(id);

        Assert.NotNull(p);
    }
}

public class When_UpdatePerson_is_called
{
    [Fact]
    public void It_should_update_untity()
    {
        // arrange
        var db = new Database();
        int id = db.CreatePerson(); // Should I use a different way to initialize the system or is it ok to use the system?

        // act
        db.UpdatePerson(id, "John Smith");
        Person p = db.GetPerson(id);

        Assert.Equal("John Smith", p.FullName);
    }
}
    
posta andygjp 21.05.2016 - 19:25
fonte

2 risposte

3

In qualsiasi test, questa può essere una buona o una cattiva cosa. Molto probabilmente, è una buona cosa che tu possa scrivere questo test, ed è una buona cosa avere un test che esegue il CreatePerson reale a fianco del UpdatePerson reale.

In generale, il fatto che puoi utilizzare un codice di produzione nei test è già una buona cosa. È assolutamente necessario eseguire test che esercitino tutto il codice di produzione, ma è più difficile distinguere due parti del codice di produzione insieme o separatamente.

Quando trovi difficile scrivere un test che eserciti un solo metodo nel codice di produzione, senza chiamare altri metodi attorno ad esso, solitamente si intende uno dei seguenti:

  1. A causa di come funziona l'API, non ha senso chiamare quel metodo da solo, quindi è perfettamente corretto per nessuno dei test chiamarlo da solo. Ad esempio, quasi tutti i test su un metodo dbConnection.executeQuery() devono chiamare database.makeConnection() . Questo è il modo in cui funzionano i database.

  2. I tuoi metodi sono troppo accoppiati tra loro e c'è un'opportunità di refactoring in modo che sia più facile scrivere sia i test che il codice di produzione.

Per l'esempio specifico che hai fornito, # 1 sembra molto più probabile per me. Non ha alcun senso aggiornare una persona che ancora non esiste ancora, quindi nel codice di produzione nessuno chiamerà mai UpdatePerson senza prima chiamare CreatePerson (altrimenti ottengono un errore ... che tu dovrebbe avere un altro test per).

Una utile cartina del tornasole per aiutare a decidere è considerare ciò che questi due diversi test stanno dicendo sulla tua API pubblica. Se scrivi un test che chiama UpdatePerson su un database prepopolato fittizio, stai dicendo che UpdatePerson dovrebbe sempre assumere quella particolare struttura di database , anche se è stata creata da qualche altra API. Se scrivi un test che chiama UpdatePerson dopo aver chiamato CreatePerson , stai dicendo che UpdatePerson dovrebbe sempre restituire tutto ciò che è stato passato in CreatePerson , indipendentemente da come è stato memorizzato . Quale di questi suoni è più corretto per il tuo progetto?

    
risposta data 21.05.2016 - 19:57
fonte
2

È perfettamente corretto utilizzare il codice di produzione per i test purché non si interrompa il test. Ad esempio, non farlo:

var expected = 4;
var actual = Calc.Subtract(Calc.Add(expected, 1));
Assert.AreEqual(expected, actual);

Se sai che il test fallisce quando c'è qualcosa di sbagliato, penso che sia ancora meglio riutilizzare il codice di produzione per le impostazioni di test.

    
risposta data 21.05.2016 - 19:37
fonte

Leggi altre domande sui tag