La seule vraie logique réside dans la syntaxe de requête de l'API externe. Je ne veux pas tester s'il interroge l'API, je veux tester qu'il l'interroge de manière à ce que les données correctes soient renvoyées. Par exemple, certains pseudo-code:
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 exemple plus concret avec une API composée:
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;
}
The query is in a syntax custom to the API and is complex and there are multiple ways to achieve the same or similar results. The purpose of the function is not to get data identified by id
but to find a subset of other data based on a fuzzy relationship to the data identified by id
that also meets a few other requirements. The other requirements are always the same regardless of id
but may change over time as the system is modified. For example, if the example api added support for gravity information, we may want to change the query to also use gravity to refine the results. Or maybe we come up with a more efficient way to check the temp range, but it doesn't change the results.
Ce que je veux tester, c'est que pour une entrée donnée, id
l'ensemble de données correct est renvoyé. Je veux tester cela afin que si quelqu'un gâche la requête de telle sorte qu'elle ne renvoie plus les données correctes en fonction de id
cela, elle échouera, mais je veux également que les gens puissent modifier la requête pour l'affiner sans avoir besoin de la modifier également. le test.
Options que j'ai envisagées:
Je pourrais bloquer l'api, mais ce serait soit trop simple (vérifiez que le
id
est présent dans la requête, puis retournez un ensemble de données attendu s'il l'est ou un ensemble inattendu sinon), trop fragile (vérifiez que la chaîne de requête est exactement ce qui se trouve dans la fonction), ou trop complexe (vérifiez que la requête utilisée est syntaxiquement correcte et entraînera le retour des données correctes).Je pourrais soumettre la requête à la vraie API, mais les résultats attendus pourraient changer au fil du temps à mesure que les données du système externe changent, en dehors du contrôle du système de test.
Je pourrais envisager de configurer une installation de test de la véritable API afin de contrôler les données dont elle dispose, mais cela demande beaucoup d'efforts.
Je me penche vers le n ° 2 et en fais plus un test d'intégration qui n'est pas souvent exécuté et je vois à quelle fréquence les changements dans les données du système externe provoquent la rupture du test. Je pense que ce serait plus simple pour l'instant, mais je me demande s'il existe des alternatives auxquelles je ne pense pas ou de meilleures façons de résoudre ce problème. Tout avis sera le bienvenu.
la source
Réponses:
Il peut sembler qu'en validant la réponse de l'API externe, nous testerions notre fonction, mais ce ne serait pas totalement vrai. D'une manière ou d'une autre, nous testerions l'API externe et l'environnement dans lequel l'API s'exécute.
Nos tests doivent être adressés pour garantir le comportement attendu du code que nous avons écrit, pas celui écrit par des tiers.
Dans une certaine mesure, nous devons faire confiance au bon fonctionnement des API et des bibliothèques sur lesquelles nous nous appuyons. Par exemple, nous ne testons généralement pas les composants de framework que nous implémentons.
Pourquoi est-ce que je le dis?
Qu'est-ce qui serait testé ici? Comme vous l'avez dit, les données et leur exactitude ne sont pas sous notre contrôle, donc nous limiterions le succès de la phase de test à un agent externe que nous n'avons aucun contrôle. Ces tests sont susceptibles de devenir non déterministes et définitivement, nous ne voulons pas de ce type de tests dans notre pipeline de bâtiments .
Une autre préoccupation est de valider le contrat. Je trouverais très utile un contrat teste 1 pour s'assurer que l'intégration fonctionne toujours comme prévu, avant toute version ou déploiement.
Que faire si la requête est correcte, mais que les données sont incorrectes en raison de bogues dans l'API? Non seulement les données sont hors de notre contrôle. La logique l'est aussi.
L'implémentation de tests fonctionnels ou de test de bout en bout peut aider ici. Vous pouvez traiter ces tests pour valider certains chemins d'exécution de sorte que si les API retournent des données incorrectes, cela provoquera probablement des comportements et des sorties inattendus. D'un autre côté, je m'attendrais à ce que l'API génère des erreurs si mes requêtes étaient mal formatées.
Je suggère de mettre en œuvre un outil à cette fin. Cela pourrait être aussi simple que:
Ou quelque chose de plus sophistiqué. Par exemple, un client autonome.
En tout cas, la fonction sous la question vaut bien deux types de tests:
Test de l'unité. Comme vous l'avez dit, vous devez bloquer l'API externe, mais c'est tout le but des tests unitaires. Tester notre code en isolant les dépendances.
Test d'intégration. Vérifiez que le code envoie non seulement la demande correcte mais qu'il gère correctement le contenu des réponses, les erreurs, les redirections, etc. Faites des tests pour tous ces cas, mais ne testez pas les données .
Note latérale: Votre question est similaire à - comment testez-vous les instructions SQL de l'application -?
Questions connexes :
1: Vous pourriez être intéressé par la réponse de @ DocBrown à ce sujet
la source
J'ai vu des vérifications d'unité qui vérifient que la chaîne de requête générée correspond à une valeur attendue.
Pourtant. C'était à mon avis en cas d'utilisation limitée. La syntaxe de la requête était compliquée, peut-être boguée, donc A il y avait une infinité de possibilités de vérification et B même si la chaîne était 'correctement' générée, des résultats inattendus pouvaient être retournés dans l'environnement en direct.
Je pense que vous avez raison d'aller pour votre option 2. exécuter des tests d'intégration contre l'instance en direct.
Tant qu'ils ne sont pas destructifs, ce sont les premiers tests que vous devez écrire, car ils détectent, sans identifier la cause, toute erreur.
L'option 3 «déployer une instance de test avec des données factices» est supérieure. Mais cela n'affecte pas votre écriture de test, car vous pouvez pointer les mêmes tests vers le serveur de test si et quand cela devient une bonne utilisation du temps pour en déployer un.
la source
Cela dépend de l'API, mais si possible, optez pour l'option # 3 (instance de test privée).
Stubbing l'API (option # 1) est la pire option, pour les raisons que vous avez mentionnées, et emprunter cette voie fera probablement plus de mal que de bien (beaucoup de temps perdu).
L'exécution avec la véritable API (option n ° 2) rend les tests floconneux et peu fiables, et après quelques faux positifs, les gens cesseront de les utiliser. Non seulement les données peuvent changer, mais le service peut également être en panne. À mon avis, cela revient à n'avoir aucun test pour les requêtes et à s'appuyer sur des tests d'intégration / système pour trouver les problèmes. Cela dit, si les données de l'API changent rarement et que l'API elle-même est presque toujours active, cela pourrait être une option viable. La plupart des API ne correspondent pas à cette description.
Finalement, cela revient à l'importance et à la complexité de ces requêtes: s'il y en a plus d'une poignée, et certaines sont suffisamment complexes pour que vous ressentiez le besoin de les tester, j'investirais l'effort de configurer une instance privée pour les tests . Il se paiera tout comme les autres tests unitaires.
la source