SDK / DB isDeleted vs Test di integrazione

2

((Uso di "utenti" come esempio per rappresentare uno dei molti tipi di record))

Un'applicazione con tracciamento utente ha in genere una tabella Utente. Molte, se non tutte, le aziende impongono che un record utente non venga mai effettivamente eliminato. Invece, dovrebbe essere aggiunto un campo di discrezione "isDeleted". L'altra possibilità è una tabella shadow che tiene traccia degli utenti eliminati e della propria serie di domande che non dovrebbero essere affrontate qui.

Quindi, in generale, per recuperare un elenco di utenti, potrei avere un metodo come questo:

public ICollection<User> GetUsers() {
    return Users.Where(x => x.isDeleted == false);
}

Quindi ho un SDK che avvolge un servizio web che chiama servizi di dominio che dipendono dall'accesso ai dati che colpisce il mio database. L'eventualità è qualcosa del genere:

public void DeleteUser(int id) {
    var user = Users.Where(x => x.id == id).Single();
    user.isDeleted = true;
    user.SaveDatShiz();
}

Quindi, per quanto riguarda il mio test di integrazione? Ho un test di integrazione qualcosa del genere:

public void TestUserCreation() {
    Dependency.CreateUser(user);
    var integratedUser = Dependency.GetUserBySomething(user.Something);
    Assert.AreEqual(integratedUser, user, "wut?");
    Dependency.DeleteUser(integratedUser.id); //Clean up!
}

La chiave sopra è che il mio Test di integrazione pensa che stia pulendo, ma in realtà il mio database di produzione ha tre volte più utenti di test falsi rispetto agli utenti reali. La tabella è SUPER gonfiata dall'esecuzione di test di integrazione sulla distribuzione in un ambiente di distribuzione continua.

Quindi, come faccio a lasciare che i miei test di integrazione EFFETTIVAMENTE cancellino un utente? Non sto chiedendo una risposta in codice, sto chiedendo una risposta architettonicamente corretta.

E.G .: Devo creare un endpoint che esegue effettivamente un'eliminazione, ma richiede una chiave che solo il test di integrazione conosce? Sembra disordinato ...

E.G.2: Devo accedere direttamente al database di produzione ed eseguire query di eliminazione su di esso? (Lol, total lawl no.)

E.G.3: Nessun altro si preoccupa di questo, quindi non dovrei (Non Rimborsabile !!! Voglio dire .. Non Accettabile !!!!)

    
posta Suamere 15.06.2015 - 05:35
fonte

2 risposte

1

In primo luogo, proverei a non eseguire test sui veri database di produzione, se possibile, ma so che questo non può sempre essere evitato.

Nei miei test di questo tipo, garantisco che il database sia come previsto con un intervallo di semplici AddEntry , DeleteEntry , AssertEntry e AssertEntryCount routine che inseriscono, eliminano, asseriscono il contenuto di, o asserire il conteggio previsto di righe nelle tabelle con campi e valori specificati.

Hanno un parametro TableName e poi un parametro ParamArray chiamato ColumnsAndValuesAndOptionalConnectString (oltre a un paio di sovraccarichi di query SQL diritte) che si aspetta nomi di campo, quindi lo stesso numero di valori e infine una stringa di connessione opzionale .

Nel tuo caso, avrei un test (o il più piccolo possibile) che crea un nuovo utente e, se ha esito positivo, la rimozione fa effettivamente cadere l'utente creato.

Il resto dovrebbe riferirsi a un singolo (o ancora il meno possibile) "Test di integrazione" che viene normalmente contrassegnato come cancellato, ma che l'utente non viene eliminato mentre i test vengono eseguiti su di esso.

Per rispondere alla tua domanda: "Devo fornire un modo per eliminare davvero un utente?" Se non si desidera accedere direttamente al database per "eseguire query di eliminazione su di esso", è necessario scegliere tra la creazione di nuovi utenti di test per ogni test o la creazione di un percorso di codice che elimina effettivamente gli utenti. Se scegli la seconda opzione, puoi rendere la routine di cancellazione degli utenti disponibile solo per il tuo codice di test con un numero di mezzi e, a seconda del tuo ambiente di sviluppo, potresti riuscire a non mostrarlo sulla tua API pubblica.

Forse la soluzione più semplice è quella di identificare gli utenti di test in modo esplicito e definire un'API pubblica DeleteTestUser documentata per eliminare solo gli utenti di test, ma lo fa completamente.

    
risposta data 15.06.2015 - 09:03
fonte
2

In casi come quelli descritti qui, di solito installo (o utilizzo) un ambiente di test di integrazione dedicato. In tale ambiente, lo script di test / codice di test ha accesso al database completo e diretto e può fare tutto ciò che gli piace nel database, inclusa la creazione / eliminazione di materiale a suo piacimento. Idealmente, il DB è un DB incorporato, che viene convertito esplicitamente per il test. Se questo non è abbastanza, hai bisogno di un tipo di DB "reale", ma con le moderne tecnologie di virtualizzazione come Docker anche questo è fattibile.

Ora, questo può sembrare un "imbroglio", un test che mette direttamente a disagio il DB. Tuttavia, per essere in grado di testare a fondo un sistema, è necessario essere in grado di riprodurre lo stato del sistema arbitrario. Questo include lo stato che non puoi produrre tramite normali chiamate API, come ad esempio:

  • enormi quantità di dati che richiederebbero sempre l'utilizzo dell'API
  • dati non validi, forse per simulare qualche bug del DB o un bug in una versione precedente del tuo software
  • vecchi dati - ad esempio, test di scadenza di record più vecchi di un anno
  • e, ultimo non meno importante, un DB vuoto per avere una lavagna pulita per il prossimo test - che è il problema dalla domanda

Per un test approfondito, il codice di test richiede un accesso diretto e completo al DB - qualsiasi altra cosa ti morderà ad un certo punto.

    
risposta data 14.12.2015 - 00:01
fonte

Leggi altre domande sui tag