Wie testen Sie eine Funktion, deren einziger Zweck darin besteht, eine externe API abzufragen, die jedoch eine komplexe Abfragesyntax verwendet?

16

Die einzige echte Logik liegt in der Abfragesyntax für die externe API. Ich möchte nicht testen, ob die API abgefragt wird. Ich möchte testen, ob die API so abgefragt wird, dass die korrekten Daten zurückgegeben werden. Zum Beispiel ein Pseudocode:

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;
}

Ein konkreteres Beispiel mit einer erfundenen API:

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;
}

Die Abfrage hat eine an die API angepasste Syntax und ist komplex. Es gibt mehrere Möglichkeiten, die gleichen oder ähnliche Ergebnisse zu erzielen. Der Zweck der Funktion besteht nicht darin, Daten zu identifizieren, idsondern eine Teilmenge anderer Daten zu finden, die auf einer unscharfen Beziehung zu den durch identifizierten Daten basiert id, die auch einige andere Anforderungen erfüllt. Die anderen Anforderungen sind immer gleich id, können sich jedoch im Laufe der Zeit ändern, wenn das System geändert wird. Wenn die Beispiel-API beispielsweise die Unterstützung für Schwerkraftinformationen hinzufügt, möchten wir die Abfrage möglicherweise ändern, um auch die Schwerkraft zu verwenden, um die Ergebnisse zu verfeinern. Oder wir haben eine effizientere Methode zur Überprüfung des Temperaturbereichs entwickelt, die die Ergebnisse jedoch nicht verändert.

Was ich testen möchte, ist, dass für eine bestimmte Eingabe idder richtige Datensatz zurückgegeben wird. Ich möchte dies testen, damit, wenn jemand die Abfrage durcheinander idbringt und nicht mehr die richtigen Daten zurückgibt , dies fehlschlägt. Ich möchte jedoch auch, dass die Abfrage geändert werden kann, um sie zu verfeinern, ohne dass Änderungen erforderlich sind der Test.

Optionen, über die ich nachgedacht habe:

  1. Ich könnte die API stummschalten, aber das wäre entweder zu einfach (überprüfen Sie, ob die idin der Abfrage vorhanden ist, und geben Sie dann eine erwartete Menge von Daten zurück, wenn dies der Fall ist, oder eine unerwartete Menge, wenn dies nicht der Fall ist), zu spröde (überprüfen Sie, ob die Abfragezeichenfolge vorhanden ist genau das, was in der Funktion enthalten ist) oder zu komplex (stellen Sie sicher, dass die verwendete Abfrage syntaktisch korrekt ist und die richtigen Daten zurückgegeben werden).

  2. Ich könnte die Abfrage an die echte API senden, aber die erwarteten Ergebnisse könnten sich im Laufe der Zeit ändern, da sich die Daten im externen System außerhalb der Kontrolle des Testsystems ändern.

  3. Ich könnte versuchen, eine Testinstallation der echten API einzurichten, um die darin enthaltenen Daten zu kontrollieren, aber das ist ein großer Aufwand.

Ich neige zu # 2 und mache dies eher zu einem Integrationstest, der nicht oft ausgeführt wird und sehe, wie oft Änderungen an den Daten des externen Systems dazu führen, dass der Test abgebrochen wird. Ich denke, das wäre im Moment am einfachsten, aber ich frage mich, ob es Alternativen gibt, über die ich nicht nachdenke, oder bessere Möglichkeiten, um dieses Problem anzugehen. Jeder Rat wäre dankbar.

Joshua Coady
quelle
Ich habe das als Unit-Test betrachtet, aber vielleicht ist es wirklich ein Integrationstest oder ein Low-Level-Akzeptanztest?
Joshua Coady
2
Ist es eine schreibgeschützte API? Oder können Sie Daten schreiben , anhand derer Sie Ihre Lesevorgänge zuverlässig überprüfen können ?
Svidgen
Unterscheidet sich diese Frage von "Wie teste ich, ob mein SQL (= komplexe Syntax) die korrekten Daten zurückgibt"? Bei Datenbanken gibt es normalerweise einige Integrationstests, die die Crud-SQL-Syntax und ein verspottetes Repository testen, um die Geschäftslogik zu überprüfen
k3b

Antworten:

7

Es mag so aussehen, als würden wir unsere Funktion testen, wenn wir die externe API-Antwort validieren, aber das wäre nicht ganz richtig. Irgendwie würden wir die externe API und die Umgebung testen, in der die API ausgeführt wird.

Unsere Tests sollten angesprochen werden, um das erwartete Verhalten des von uns geschriebenen Codes zu gewährleisten, nicht das von Dritten.

Bis zu einem gewissen Grad müssen wir uns auf die ordnungsgemäße Funktion der APIs und Bibliotheken verlassen, auf die wir uns verlassen. Zum Beispiel testen wir normalerweise nicht die Framework-Komponenten, die wir implementieren.

Warum sage ich das?

Was ich testen möchte, ist, dass für eine bestimmte Eingabe-ID der richtige Datensatz zurückgegeben wird

Was würde hier getestet werden? Wie Sie sagten, sind die Daten und ihre Richtigkeit nicht unter unserer Kontrolle, daher würden wir den Erfolg der Testphase auf einen externen Agenten beschränken, auf den wir keine Kontrolle haben. Diese Tests sind ein Kandidat, um nicht deterministisch zu werden, und definitiv. Wir wollen diese Art von Tests nicht in unserer Baupipeline haben .

Ein anderes Anliegen ist es, den Vertrag zu validieren. Ich würde einen Vertragstest 1 als sehr nützlich erachten, um sicherzustellen, dass die Integration vor jeder Veröffentlichung oder Bereitstellung noch wie erwartet funktioniert.

Ich möchte dies testen, damit, wenn jemand die Abfrage durcheinander bringt und nicht mehr die korrekten Daten basierend auf der ID zurückgibt, dies fehlschlägt

Was ist, wenn die Abfrage in Ordnung ist, die Daten jedoch aufgrund von Fehlern in der API falsch sind? Nicht nur die Daten sind außerhalb unserer Kontrolle. Die Logik ist auch.

Hier kann die Implementierung von Funktionstests oder End-to-End-Tests hilfreich sein. Sie können diesen Test verwenden, um bestimmte Ausführungspfade zu validieren. Wenn die APIs falsche Daten zurückgeben, führt dies wahrscheinlich zu unerwarteten Verhaltensweisen und Ausgaben. Andererseits würde ich erwarten, dass die API Fehler auslöst, wenn meine Abfragen schlecht formatiert sind.

Ich möchte aber auch, dass Benutzer die Abfrage ändern können, um sie zu verfeinern, ohne den Test ändern zu müssen.

Ich schlage vor, ein Tool für diesen Zweck zu implementieren. Es könnte so einfach sein wie:

  • Eine Klasse, die als Test ausgeführt wird, aber nicht zum Testplan gehört
  • Ein Shell-Skript + Curl

Oder etwas Anspruchsvolleres. Zum Beispiel ein eigenständiger Client.

In jedem Fall ist die Funktion unter der Frage durchaus zwei Arten von Tests wert:

  • Gerätetest. Wie Sie sagten, müssen Sie die externe API blockieren, aber das ist der ganze Zweck von Komponententests. Testen Sie unseren Code, um die Abhängigkeiten zu isolieren.

  • Integrationstest. Vergewissern Sie sich, dass der Code nicht nur die richtige Anforderung sendet, sondern auch den richtigen Umgang mit Antwortinhalten, Fehlern, Weiterleitungen usw. hat. Führen Sie in all diesen Fällen Tests durch, testen Sie jedoch keine Daten .

Randnotiz: Ihre Frage ähnelt -wie testen Sie die SQL-Anweisungen der App-?

Verwandte Fragen :


1: Möglicherweise interessieren Sie sich für die Antwort von @ DocBrown zu diesem Thema

Laiv
quelle
"Das Problem (IMO) ist, dass Sie sich zu sehr auf das Testen der externen API konzentrieren." - Ich sehe nichts, was darauf hindeutet, dass der Fragesteller die externe API überhaupt testen möchte. Sie sagen auch "stub the external API", haben aber Vorschläge, ob der Fragesteller die Option "too simple", die Option "too brittle", die Option "too complex" oder eine vierte Option verwenden soll?
Tanner Swett
In der OP-Frage wird gefragt, wie eine Funktion getestet werden soll, die eine externe API aufruft. Aber das Lesen seiner Zweifel scheint mir, dass er zu viel Wert darauf legt, die Abfrage und ihre Ergebnisse zu testen. Ich habe 4 Vorschläge gemacht: (1) Teste die API nicht. (2) Verwenden Sie die Integrationstests nicht als Workbench, um die Abfrage zu optimieren. Machen Sie stattdessen ein Werkzeug. (3) Zurück zur Hauptfrage: Führe den Einheits- und Integrationstest durch. Der Inhalt der API-Antwort wird jedoch nicht überprüft. (4) Fragen Sie den Projektmanager, ob er eine Testsuite der externen API als Teil des Testplans des Projekts erstellen soll / kann.
Laiv
1
Ich betrachte die Abfrage selbst als "von uns geschriebener Code". Das Endziel ist das automatisierte Testen, um uns zu warnen, wenn wir einen Fehler in unserem Code eingeführt haben. Ich nehme an, es ist ähnlich wie das, was Sie über SQL - Anweisungen gesagt haben. Ich glaube, meine Frage ist, wie Sie testen, ob Ihr Code eine externe API auf eine Weise abfragt, dass die API wie beabsichtigt reagiert (vorausgesetzt, a nominelle Antwort). Ich denke, was Sie sagen, ist, das aus den Unit- und Integrationstests herauszulassen, aber wenn die Abfragen geschäftskritisch sind, könnten wir einige andere automatisierte Tests separat einrichten, um die externe Live-API zu testen.
Joshua Coady
1
IMO, der beste Weg ist, einen Funktionstest durchzuführen. Die Änderung der where-Klausel, die niemals zutreffen wird, wird in einem oder mehreren meiner Funktionstests ein anderes Verhalten hervorrufen. UT sind nur ein kleines Stück im Testplan.
Laiv
2
Vielen Dank, dass Sie ein Resonanzboden sind. Obwohl die Abfrage eine benutzerdefinierte Logik enthält, liegt sie letztendlich außerhalb des Bereichs des Komponententests, da es sich bei der Abfrage um Code handelt, der außerhalb des zu testenden Systems "ausgeführt" wird. Ich brauchte nur jemanden, der mir das mehrmals auf unterschiedliche Weise sagte, bevor ich es sah;)
Joshua Coady
2

Ich habe Unit Checks gesehen, bei denen überprüft wurde, ob die generierte Abfragezeichenfolge einem erwarteten Wert entspricht.

Jedoch. Dies war meiner Meinung nach nur bedingt zu gebrauchen. Die Abfragesyntax war kompliziert, möglicherweise fehlerhaft. Daher gab es unzählige Überprüfungsmöglichkeiten, und auch wenn die Zeichenfolge "korrekt" generiert wurde, konnten unerwartete Ergebnisse in der Live-Umgebung zurückgegeben werden.

Ich denke, Sie haben Recht, Ihre Option 2 zu wählen. Führen Sie Integrationstests für die Live-Instanz durch.

Solange sie nicht destruktiv sind, sind dies die ersten Tests, die Sie schreiben sollten, da sie die Fehlerursache erkennen, aber nicht identifizieren.

Die Option 3 "Bereitstellen einer Testinstanz mit Dummy-Daten" ist überlegen. Dies wirkt sich jedoch nicht auf das Schreiben von Tests aus, da Sie dieselben Tests auf den Testserver verweisen können, wenn die Bereitstellung eines Tests zeitaufwendig wird.

Ewan
quelle
0

Dies hängt von der API ab. Wenn möglich, wählen Sie Option 3 (private Testinstanz).

Das Stoppen der API (Option 1) ist aus den von Ihnen genannten Gründen die schlechteste Option, und diese Route wird wahrscheinlich mehr schaden als nützen (viel verschwendete Zeit).

Die Verwendung der echten API (Option 2) macht die Tests unzuverlässig und unzuverlässig, und nach ein paar falschen Positiven werden die Benutzer sie einfach nicht mehr verwenden. Es können sich nicht nur die Daten ändern, sondern auch der Service kann ausfallen. Meiner Meinung nach bedeutet dies, keine Tests für die Abfragen zu haben und sich auf Integrations- / Systemtests zu stützen, um die Probleme zu finden. Wenn sich die API-Daten jedoch selten ändern und die API selbst fast immer aktiv ist, ist dies möglicherweise eine praktikable Option. Die meisten APIs passen nicht zu dieser Beschreibung.

Letztendlich kommt es darauf an, wie wichtig und komplex diese Abfragen sind: Wenn es mehr als eine Handvoll Abfragen gibt und einige von ihnen so komplex sind, dass Sie sie testen müssen, würde ich den Aufwand investieren, eine private Instanz zum Testen einzurichten . Das zahlt sich aus wie bei anderen Unit-Tests.

Michal Tenenberg
quelle
Sie sagen also, dass Unit-Tests (# 1) und Integrationstests (# 2) schädlich sind? Während # 3 der beste unter ihnen zu sein scheint, könnte es auch der teuerste sein. Es muss bei jeder Änderung der API gewartet werden. Ohne Nummer 2 werden Sie nicht über mögliche Fehleränderungen in der realen API informiert, bis Ihre App in Produktion ist (zu spät, um Maßnahmen zu ergreifen). Ok, # 1 scheint nicht benötigt zu werden, weil es keine Codezeilen zum Testen gibt ... heute ... Morgen, woher weiß ...
Laiv
Ich sage, schlechte Tests sind definitiv schädlich. Flockige Tests verschwenden viel Zeit und Mühe und führen dazu, dass Menschen das Vertrauen in Unit-Tests als Ganzes verlieren. Tests, die mit Implementierungsänderungen (# 1) brechen oder nur zufällig, wenn sich Daten ändern (# 2), sind keine guten Tests.
Michal Tenenberg
Integrationstest testet keine Daten. Das ist es. Sie können den Test nicht abbrechen, sondern nur die Integration validieren. Testen ist keine Frage des Glaubens ist eine Frage der guten Gewohnheiten, die der Anwendung einen Mehrwert verleihen
Laiv,