Bonnes pratiques de test

Développer une action pour la plate-forme Actions on Google implique souvent d'implémenter Dialogflow pour sa compréhension du langage naturel (NLU) et le traitement Dialogflow, qui gère la logique de votre action. Le fait d'avoir des tests dans votre codebase permet de garantir que votre action fonctionne comme prévu en production.

Lorsque vous implémentez des tests unitaires, d'intégration ou de bout en bout pour votre action, vous devez considérer l'agent Dialogflow et le traitement comme des composants distincts.

Un organigramme passe de la requête d'un utilisateur à Actions on Google, à Dialogflow et à un webhook de fulfillment, avant de renvoyer l'utilisateur à l'utilisateur.

Figure 1. Organigramme décrivant les systèmes à prendre en compte pour les tests

Tester un agent Dialogflow

L'agent Dialogflow et le fulfillment sont testés en tant que composants distincts. Les sous-sections suivantes décrivent comment conceptualiser et tester l'agent Dialogflow pour votre action.

Dialogflow comme système d'entrée et de sortie de requête

Votre agent Dialogflow est chargé de récupérer la requête d'un utilisateur, de la mettre en correspondance avec un intent et d'en extraire les entités prédéfinies. Votre agent interagit avec votre traitement en transmettant un message contenant l'intent correspondant, ses paramètres et les métadonnées Actions on Google.

En tant que développeur, vous contrôlez la configuration de l'agent Dialogflow, comme la structure des intents et des entités. Les métadonnées Actions on Google proviennent d'Actions on Google et peuvent être considérées comme contenant les bonnes données à des fins de test.

Lors des tests, efforcez-vous de rendre votre agent capable d'extraire correctement les paramètres d'intent et de mettre en correspondance les requêtes avec les intents. Cette approche fournit une métrique quantifiable pour évaluer les performances de l'agent. Vous pouvez calculer cette métrique en préparant et en utilisant des scénarios de test individuels ou un ensemble de validation.

Un agent Dialogflow peut être représenté avec une requête de texte en entrée et un intent et des paramètres d'intent extraits en sortie.

Figure 2. Représentation de Dialogflow en tant que système de requête d'entrée et d'intention de sortie

Tests unitaires

Pour votre agent Dialogflow, vous pouvez écrire des tests dans lesquels chaque cas attend une requête textuelle en entrée et génère des métadonnées d'intent en tant que sortie. Ces métadonnées doivent contenir (au minimum) le nom de l'intent correspondant et une liste de paramètres correspondants.

Le point de terminaison detectIntent de l'API Dialogflow prend la requête textuelle comme entrée et produit une sortie structurée contenant le nom de l'intent résolu et des paramètres extraits. Cette sortie est utile pour évaluer les performances de mise en correspondance des intents de l'agent. Pour obtenir une documentation de référence complète sur les autres champs utiles, consultez la documentation de référence sur QueryResult.

Voici un exemple de test:

it('choose_fact', async function() {
  // The `dialogflow` variable is an abstraction around the API that creates
  // and sends payloads to Dialogflow.
  const resJson = await dialogflow.detectIntent(
    'Tell me about the history of Google');
  expect(resJson.queryResult).to.include.deep.keys('parameters');
  // Check that Dialogflow extracted required entities from the query.
  expect(resJson.queryResult.parameters).to.deep.equal({
    'category': 'history',
    // Put any other parameters you wish were extracted
  });
  expect(resJson.queryResult.intent.displayName).to.equal('choose_fact');
});

Cet extrait utilise du mocha et la chaîne Chai. Consultez l'exemple complet du test unitaire Dialogflow écrit en Node.js pour Facts About Google.

Vous pouvez exécuter vos fichiers de test en parallèle, car l'API Dialogflow accepte un sessionId comme argument. Vous pouvez donc disposer d'un bac à sable distinct pour chaque conversation tout en utilisant un seul client de l'API Dialogflow.

Étant donné que vous effectuez des requêtes sur l'API Dialogflow, des frais peuvent vous être facturés si votre quota d'appels sans frais est atteint. Pour plus d'informations, consultez la section Quotas et limites.

Tests d'intégration

Le point de terminaison detectIntent de l'API Dialogflow déclenche également un traitement tiers. Ainsi, il est possible d'écrire des scénarios de test qui couvrent l'intégration entre l'agent et le traitement Dialogflow.

La principale différence entre l'écriture des tests d'intégration et les tests unitaires pour Dialogflow est que, dans le test d'intégration, vous pouvez revendiquer des réponses provenant du webhook, ainsi que de l'intent Dialogflow et de l'extraction d'entités.

Consultez l'exemple complet d'un test d'intégration écrit en Node.js dans le dépôt Facts About Google.

Tester un webhook de fulfillment Dialogflow

L'agent et le traitement Dialogflow sont testés en tant que composants distincts. Les sous-sections suivantes décrivent comment conceptualiser et tester le traitement pour votre action.

Fulfillment en tant que système JSON-in et JSON-out

Votre code de traitement Dialogflow attend des requêtes et génère des réponses au format JSON. Par conséquent, vous pouvez tester votre code de traitement en le considérant comme un système JSON-in et JSON-out. La requête contient des métadonnées provenant à la fois de Dialogflow et d'Actions on Google. Elle dispose donc de tous les éléments nécessaires pour déclencher un gestionnaire d'intent particulier dans votre traitement.

Pour tester le déclenchement d'un gestionnaire d'intents, vous devez envoyer une requête JSON (entrée) à votre action. Cette requête est transmise à votre traitement, qui est accessible sur Internet. Le traitement génère ensuite une réponse JSON (sortie), dont la validation peut être évaluée.

Un fulfillment peut être représenté par une entrée de requête JSON et un résultat de réponse JSON de webhook.

Figure 3. Représentation d'un traitement en tant que systèmes JSON-in et JSON-out

Tests unitaires

Considérez le code du webhook de fulfillment comme un système qui accepte une entrée JSON et génère une sortie JSON. Le processus de test d'une action est ensuite simplifié pour fournir une requête à votre traitement et vérifier le fichier JSON de sortie obtenu.

Cela vous donne la liberté d'héberger le traitement localement et d'envoyer des requêtes HTTP localement à des fins de test. Si vous utilisez la bibliothèque cliente Actions on Google pour Node.js, vous pouvez également envoyer des requêtes JSON directement à la couche de middleware de la bibliothèque cliente.

Si vous testez le code de webhook avec des entrées JSON et recevez les sorties JSON attendues, vous pouvez indiquer avec une confiance raisonnable que les parties que vous contrôlez fonctionnent correctement. Vous pouvez supposer que Dialogflow et Actions on Google fonctionnent correctement, car ils génèrent les charges utiles JSON appropriées. Cette isolation fournit un modèle de programmation simplifié pour l'écriture des tests.

Voici un aperçu général du processus de test:

  1. Utilisez le simulateur dans la console Actions pour obtenir les requêtes JSON pour chaque étape d'un cas d'utilisation. Enregistrez-les au format JSON. Vous pouvez également créer ces requêtes vous-même à l'aide des informations de la documentation de référence du webhook.
  2. Écrivez des tests pour appeler le webhook avec ces charges utiles.
  3. Pour chaque test, assurez-vous que la réponse JSON contient les éléments attendus.

En outre, ce modèle vous permet de tester le traitement Dialogflow dans un paramètre d'intégration continue, car le point de terminaison du fulfillment peut s'exécuter localement et l'API Dialogflow a un concept de session intégré.

Voici un exemple de test:

it('yes-history', function() {
  expect(jsonRes.payload).to.have.deep.keys('google');
  expect(jsonRes.payload.google.expectUserResponse).to.be.true;
  expect(jsonRes.payload.google.richResponse.items).to.have.lengthOf(3);
  expect(jsonRes.payload.google.richResponse.suggestions).to.have
    .deep.members([
      {'title': 'Sure'}, {'title': 'No thanks'},
    ]);
});

L'extrait ci-dessus utilise Mocha et Chai. Consultez l'exemple fonctionnel écrit en Node.js dans le dépôt Facts About Google.

Concevoir un traitement pouvant être testé unitaire

Le code du webhook contient souvent une logique métier personnalisée sur laquelle votre application s'appuie pour répondre à ses besoins. En outre, le code webhook peut également contenir des gestionnaires d'intents.

Pour améliorer la précision des tests unitaires pour votre code de traitement, il est recommandé d'organiser le code de manière à dissocier la logique métier des routines de gestion des intents. Cela implique d'avoir des gestionnaires d'intents et une logique métier dans des modules distincts, de sorte que chaque élément puisse être testé indépendamment.

Pour obtenir un exemple, consultez notre exemple d'action shiritori sur GitHub. Dans cet exemple, functions/index.js et functions/shiritori/*.js contiennent séparément les gestionnaires d'intent et la logique métier, ce qui permet de créer des suites de tests plus robustes.

Tests d'intégration

Pour écrire des scénarios de test couvrant l'intégration entre Dialogflow et votre code de webhook de fulfillment, consultez la section sur les tests d'intégration pour Dialogflow ci-dessus.

Tests de charge

Avant de déployer votre action en production, nous vous recommandons également de tester la charge de votre traitement de webhook pour détecter les problèmes de performances qui entraînent la dégradation ou l'interruption de votre service de traitement.

Voici quelques exemples de problèmes de performances que vous pouvez rencontrer lors des tests de charge:

  • Calcul et mémoire limités
  • Restrictions de quota de vos fournisseurs
  • Lenteur de la lecture et de l'écriture de données
  • Problèmes de simultanéité dans le code

Les scénarios de tests de charge dépendent du modèle d'utilisation attendu ou historique de votre action, mais les scénarios typiques à tester sont les augmentations soudaines de la charge (pic) et les charges soutenues (soins).

Identifiez les scénarios dans lesquels le webhook est appelé et effectue des opérations gourmandes en ressources. Les opérations classiques gourmandes en ressources incluent l'interrogation d'une base de données, l'appel d'une autre API, et les opérations de calcul et de mémoire, telles que le rendu d'un fichier audio.

Pour ces scénarios, vous pouvez capturer les requêtes envoyées par Actions on Google au webhook à partir de vos journaux de webhook ou de vos journaux Stackdriver. Vous pouvez également capturer les requêtes à partir du simulateur de la console Actions.

Une fois les requêtes reçues, vous pouvez utiliser un outil de tests de charge pour découvrir comment votre webhook répond dans différents scénarios de tests de charge. Les sous-sections suivantes fournissent des exemples de tests de pics et de tests de stabilisation à l'aide d'ApacheBench.

Tests de pics

Pour effectuer des tests de pics, vous devez envoyer un nombre constant de requêtes au webhook pendant un certain temps et augmenter soudainement la charge. Par exemple, vous pouvez configurer un test qui envoie une charge de 10 requêtes par seconde (RPS) avec quelques pics de 60 RPS.

Vous pouvez exécuter la commande ApacheBench suivante pour envoyer 60 requêtes simultanées à votre webhook:

ab -n 60 -c 60 -p ActionRequest.json -T 'application/json' https://example.com/webhookFunctionName

Supposons que le fichier ActionRequest.json contient la charge utile de la requête capturée envoyée à votre webhook.

Test de trempage

Les tests de stabilisation nécessitent d'envoyer un nombre constant de requêtes au webhook et d'observer la réponse. Par exemple, vous pouvez configurer un test qui envoie une charge constante de 10 à 20 RPS pendant plusieurs minutes pour voir si les temps de réponse augmentent.

Vous pouvez exécuter la commande ApacheBench suivante pour envoyer 1 200 requêtes, avec 10 requêtes simultanées toutes les secondes:

ab -t 120 -n 1200 -p ActionRequest.json -T 'application/json' https://example.com/webhookFunctionName

Supposons que le fichier ActionRequest.json contient la charge utile de la requête capturée envoyée à votre webhook.

Analyser les résultats des tests de charge

Après avoir exécuté les tests de charge, analysez les résultats pour les temps de réponse du webhook. Les indicateurs de problèmes dans l'implémentation de votre webhook sont généralement des tendances telles qu'un temps de réponse médian qui augmente à chaque exécution de test, ou un temps de réponse dans le pire des cas qui est inacceptable pour votre action.

Test de bout en bout

Les tests complets préalables à l'envoi de votre action pour approbation utilisent le simulateur de la console Actions. Vous trouverez la procédure à suivre pour effectuer des tests de bout en bout via le simulateur de la console Actions dans la documentation du simulateur Actions. Ces tests vous aident à éliminer les incertitudes potentielles du composant d'infrastructure Actions on Google.