Come testare una funzione il cui unico scopo è di interrogare un'API esterna, ma l'API utilizza una sintassi complessa della query?

17

L'unica vera logica è nella sintassi della query per l'API esterna. Non voglio testare se interroga l'API, voglio verificare che lo interroghi in modo tale che vengano restituiti i dati corretti. Ad esempio, alcuni pseudo-codice:

function retrieve_related_data(id)
{
  query = "[potentially long, syntactically complex query that
            uses param id to get some data]";
  results = api_wrapper.query(query);
  return results;
}

Un esempio più concreto con un'API composta:

function retrieveLifeSupportingObjectsWithinRegion(id)
{
  query = "
    within region(" + id + ") as r
    find objects matching hydration>0 and temp_range has 75
    send name, id, relative(position, r)        
  ";
  results = astronomicalObjectApiWrapper.query(query);
  return results;
}

La query è in una sintassi personalizzata per l'API ed è complessa e ci sono diversi modi per ottenere risultati uguali o simili. Lo scopo della funzione non è quello di ottenere dati identificati da id ma di trovare un sottoinsieme di altri dati basato su una relazione fuzzy con i dati identificati da id che soddisfa anche alcuni altri requisiti. Gli altri requisiti sono sempre gli stessi indipendentemente da id , ma possono cambiare nel tempo man mano che il sistema viene modificato. Ad esempio, se l'API di esempio ha aggiunto il supporto per le informazioni sulla gravità, potremmo voler cambiare la query per utilizzare anche la gravità per perfezionare i risultati. O forse abbiamo un modo più efficiente per controllare l'intervallo di temperatura, ma non cambia i risultati.

Quello che voglio testare è che per un dato input id viene restituito il set di dati corretto. Voglio testare questo in modo che se qualcuno scombina la query in modo tale che non restituisca più i dati corretti basati su id che fallirà, ma voglio anche che le persone siano in grado di modificare la query per perfezionarla senza bisogno per modificare anche il test.

Opzioni che ho considerato:

  1. Potrei stubare l'api, ma sarebbe troppo semplice (controlla che id sia presente nella query e poi restituisca un insieme di dati previsto se lo è o un set imprevisto se non lo è), troppo fragile (controlla che la stringa di query sia esattamente ciò che è nella funzione), o troppo complessa (controlla che la query utilizzata sia sintatticamente corretta e comporterà la restituzione dei dati corretti).

  2. Potrei inviare la query alla vera API, ma i risultati attesi potrebbero cambiare nel tempo man mano che i dati nel sistema esterno cambiano, fuori dal controllo del sistema di test.

  3. Potrei cercare di configurare un'installazione di prova della vera API per controllare i dati che ha, ma questo è un grande sforzo.

Mi sto avvicinando al n. 2 e questo rende più di un test di integrazione che non viene eseguito spesso e osservando con quale frequenza i cambiamenti nei dati del sistema esterno causano la rottura del test. Penso che sarebbe più semplice per ora, ma mi chiedo se ci sono alternative a cui non sto pensando o modi migliori per affrontare questo problema. Qualsiasi consiglio sarebbe apprezzato.

    
posta Joshua Coady 25.03.2017 - 20:25
fonte

3 risposte

8

Potrebbe sembrare che convalidando la risposta dell'API esterna verificheremmo la nostra funzione, ma non sarebbe del tutto vero. In qualche modo, testeremo l'API esterna e l'ambiente in cui è in esecuzione l'API.

I nostri test devono essere indirizzati per garantire il comportamento previsto del codice che abbiamo scritto, non quello scritto da terze parti.

In una certa misura, dobbiamo affidarci alla funzione corretta delle API e delle librerie su cui facciamo affidamento. Ad esempio, di solito non testiamo i componenti del framework che implementiamo.

Perché lo dico?

What I want to test is that for a given input id the correct set of data is returned

Cosa verrebbe testato qui? Come hai detto, i dati e la loro correttezza non sono sotto il nostro controllo, quindi limiteremmo il successo della fase di test a un agente esterno che non abbiamo alcun controllo. Questi test sono candidati a diventare non deterministici e in via definitiva, non vogliamo questo tipo di test nella nostra pipeline di costruzione .

Una preoccupazione diversa è quella di convalidare il contratto. Trovo che sia molto utile un test del contratto 1 per garantire che l'integrazione funzioni ancora come previsto, prima di qualsiasi rilascio o distribuzione.

I want to test this so that if someone messes up the query such that it is no longer returning the correct data based on id that it will fail

Che cosa succede se la query è corretta, ma i dati sono errati a causa di errori nell'API? Non solo i dati sono fuori dal nostro controllo. Anche la logica.

L'implementazione di test funzionali o test end-to-end può essere d'aiuto. È possibile indirizzare questi test per convalidare determinati percorsi di esecuzione in modo che se le API restituiscono dati errati, ciò probabilmente causerà comportamenti e output imprevisti. D'altra parte, mi aspetterei che l'API generasse errori se le mie query fossero formattate male.

But I also want people to be able to modify the query to refine it without needing to also modify the test.

Suggerisco di implementare uno strumento per tale scopo. Potrebbe essere semplice come:

  • Una classe che viene eseguita come test ma non appartiene al piano di test
  • Uno script di shell + curl

O qualcosa di più sofisticato. Ad esempio, un client standalone.

In ogni caso, la funzione sotto la domanda vale due tipi di test:

  • Test unitario. Come hai detto, devi stubbare l'API esterna, ma questo è l'intero scopo dei test unitari. Test del nostro codice isolando le dipendenze.

  • test di integrazione. Verifica che il codice non solo invii la richiesta corretta ma che gestisca correttamente il contenuto della risposta, errori, reindirizzamenti, ecc. Esegui test per tutti questi casi, ma non testare i dati .

Nota a margine: La tua domanda è simile a -come testare le istruzioni SQL dell'app -?

Domande correlate :

1: Potresti essere interessato alla risposta di @ DocBrown riguardo questo topic

    
risposta data 27.03.2017 - 00:07
fonte
2

Ho visto i controlli delle unità che controllano che la stringa di query generata corrisponda a un valore previsto.

Tuttavia. Questo è stato a mio parere se l'uso è limitato. La sintassi della query era complicata, probabilmente buggata, quindi A c'erano infinite possibilità di controllo e B anche se la stringa era "correttamente" generata, i risultati imprevisti potevano essere restituiti nell'ambiente live.

Penso che tu abbia ragione ad optare per l'opzione 2. esegui test di integrazione contro l'istanza live.

Fintanto che non sono distruttivi, questi sono i primi test che dovresti scrivere, poiché cattureranno, anche se non identificheranno la causa di, qualsiasi errore.

L'opzione 3 "distribuire un'istanza di test con dati fittizi" è superiore. Ma non influisce sulla scrittura del test, poiché puoi puntare gli stessi test sul server di prova se e quando diventa un buon uso del tempo per distribuirne uno.

    
risposta data 03.04.2017 - 13:25
fonte
0

Dipende dall'API, ma se possibile, vai per l'opzione n. 3 (istanza di test privata).

Lo stub dell'API (opzione n. 1) è l'opzione peggiore, a causa dei motivi che hai menzionato, e percorrere questa rotta probabilmente farà più danni che benefici (molto tempo perso).

L'esecuzione contro la vera API (opzione # 2) rende i test instabili e inaffidabili, e dopo alcuni falsi positivi la gente smetterà di usarli. Non solo i dati possono cambiare, ma anche il servizio potrebbe essere inattivo. Secondo me, è come non avere test per le query e fare affidamento sui test di integrazione / sistema per trovare i problemi. Detto questo, se i dati API cambiano raramente e l'API stessa è quasi sempre attiva, questa potrebbe essere un'opzione valida. La maggior parte delle API non si adatta a questa descrizione.

Alla fine si tratta di quanto siano importanti e complesse queste domande: se ce ne sono più di una manciata, e alcune sono abbastanza complesse da far sentire la necessità di testarle, vorrei investire nello sforzo di creare un privato istanza per il test. Si pagherà da solo come gli altri test unitari.

    
risposta data 03.04.2017 - 15:03
fonte

Leggi altre domande sui tag