Tests CI/CD Synthetic
Rapport de recherche Datadog : Bilan sur l'adoption de l'informatique sans serveur Rapport : Bilan sur l'adoption de l'informatique sans serveur

Tests CI/CD Synthetic

En plus d’exécuter des tests à des intervalles prédéfinis, vous avez la possibilité d’exécuter des tests Datadog Synthetics ponctuellement à l’aide d’endpoints d’API. Ces tests peuvent être exécutés au sein de vos pipelines d’intégration continue (CI), de façon à bloquer le déploiement des branches susceptibles de nuire au bon fonctionnement de votre produit. Les tests CI/CD Synthetics peuvent également être utilisés pour exécuter des tests dans le cadre de votre processus CD, afin d’évaluer l’état de votre application de production dès la fin d’un déploiement. Cela vous permet de détecter les régressions éventuelles susceptibles d’avoir un impact sur vos utilisateurs et de déclencher automatiquement un rollback si un test critique échoue.

Cette fonction réduit les pertes de temps liées à la correction de problèmes en production et vous aide à identifier le plus tôt possible les bugs et régressions qui surviennent.

Les endpoints d’API Datadog sont accompagnés d’une interface de ligne de commande facilitant l’intégration des tests Datadog Synthetics avec vos outils CI. Cette fonctionnalité est open source, et son code source est disponible sur GitHub sur la page DataDog/datadog-ci.

Utilisation de l’API

L’endpoint de déclenchement fournit la liste des checks déclenchés ainsi que les identifiants de leurs résultats. L’endpoint de récupération vous permet d’obtenir tous les résultats des tests disponibles.

Endpoint de déclenchement de tests

L’endpoint de déclenchement de tests peut lancer jusqu’à 50 tests par requête.

  • Endpoint : https://api.datadoghq.com/api/v1/synthetics/tests/trigger/ci
  • Méthode : POST
  • Argument : un objet JSON contenant la liste de tous les tests à déclencher et la configuration à appliquer.
  • Endpoint : https://api.datadoghq.eu/api/v1/synthetics/tests/trigger/ci
  • Méthode : POST
  • Argument : un objet JSON contenant la liste de tous les tests à déclencher et la configuration à appliquer.

Structure de données des requêtes

{
    "tests": [TEST_À_DÉCLENCHER, TEST_À_DÉCLENCHER, ...]
}

Les objets TEST_À_DÉCLENCHER sont composés de l’identifiant public_id (requis) du test à déclencher et des configurations facultatifs à appliquer (la rubrique ci-dessous décrit chaque champ).

L’identifiant public d’un test correspond à l’identifiant du test fourni dans l’URL de la page des détails des tests (pour https://app.datadoghq.com/synthetics/details/abc-def-ghi, l’identifiant est abc-def-ghi) ou à l’URL complète de cette page (c’est-à-dire https://app.datadoghq.com/synthetics/details/abc-def-ghi).

Exemple de requête

#!/bin/sh

api_key="<CLÉ_API_DATADOG>"
app_key="<CLÉ_APPLICATION_DATADOG>"

curl -X POST \
-H 'Content-Type: application/json' \
-H "DD-API-KEY: ${api_key}" \
-H "DD-APPLICATION-KEY: ${app_key}" \
-d '{
    "tests": [
        {
            "public_id": "abc-def-ghi",
            "allowInsecureCertificates": true,
            "basicAuth": { "username": "test", "password": "test" },
            "body": "{\"contenuFictif\":true}",
            "bodyType": "application/json",
            "cookies": "name1=value1;name2=value2;",
            "deviceIds": ["laptop_large"],
            "followRedirects": true,
            "headers": { "NOUVEL_ENTÊTE": "NOUVELLE_VALEUR" },
            "locations": ["aws:us-west-1"],
            "retry": { "count": 2, "interval": 300 },
            "startUrl": "http://nouvelle.url/",
            "variables": { "titleVariable": "nouvelle valeur" }
        }
    ]
}' "https://api.datadoghq.com/api/v1/synthetics/tests/trigger/ci"
#!/bin/sh

api_key="<CLÉ_API_DATADOG>"
app_key="<CLÉ_APPLICATION_DATADOG>"

curl -X POST \
-H 'Content-Type: application/json' \
-H "DD-API-KEY: ${api_key}" \
-H "DD-APPLICATION-KEY: ${app_key}" \
-d '{
    "tests": [
        {
            "public_id": "abc-def-ghi",
            "allowInsecureCertificates": true,
            "basicAuth": { "username": "test", "password": "test" },
            "body": "{\"contenuFictif\":true}",
            "bodyType": "application/json",
            "cookies": "name1=value1;name2=value2;",
            "deviceIds": ["laptop_large"],
            "followRedirects": true,
            "headers": { "NOUVEL_ENTÊTE": "NOUVELLE_VALEUR" },
            "locations": ["aws:us-west-1"],
            "retry": { "count": 2, "interval": 300 },
            "startUrl": "http://nouvelle.url/",
            "variables": { "titleVariable": "nouvelle valeur" }
        }
    ]
}' "https://api.datadoghq.eu/api/v1/synthetics/tests/trigger/ci"

Exemple de réponse

{
  "results": [
    {
      "result_id": "0123456789012345678",
      "public_id": "abc-def-ghi",
      "location": 1
    },
  ],
  "triggered_check_ids": [
    "abc-def-ghi"
  ]
}

Endpoint de récupération des résultats

  • Endpoint : https://api.datadoghq.com/api/v1/synthetics/tests/poll_results
  • Méthode : GET
  • Paramètres : un tableau JSON contenant la liste des identifiants des résultats permettant de récupérer ces résultats.
  • Endpoint : https://api.datadoghq.eu/api/v1/synthetics/tests/poll_results
  • Méthode : GET
  • Paramètres : un tableau JSON contenant la liste des identifiants des résultats permettant de récupérer ces résultats.

Exemple de requête

#!/bin/sh

api_key="<CLÉ_API_DATADOG>"
app_key="<CLÉ_APPLICATION_DATADOG>"

curl -G \
    "https://api.datadoghq.com/api/v1/synthetics/tests/poll_results" \
    -H "DD-API-KEY: ${api_key}" \
    -H "DD-APPLICATION-KEY: ${app_key}" \
    -d "result_ids=[220123456789012345678]"
#!/bin/sh

api_key="<CLÉ_API_DATADOG>"
app_key="<CLÉ_APPLICATION_DATADOG>"

curl -G \
    "https://api.datadoghq.eu/api/v1/synthetics/tests/poll_results" \
    -H "DD-API-KEY: ${api_key}" \
    -H "DD-APPLICATION-KEY: ${app_key}" \
    -d "result_ids=[%220123456789012345678%22]"

Exemple de réponse

{
  "results": [
    {
      "check_id": "123456",
      "timestamp": 1585841351642,
      "orgID": 2,
      "result": {
        "unhealthy": false,
        "eventType": "finished",
        "timings": {
          "firstByte": 14.7,
          "tcp": 11.6,
          "ssl": 45.7,
          "dns": 12.484235048294067,
          "download": 0.2,
          "total": 84.7
        },
        "mainDC": "us1.prod",
        "runType": 2,
        "httpStatusCode": 200,
        "responseSize": 9201,
        "healthCheckRatio": 1
      },
      "dc_id": 1,
      "resultID": "0123456789012345678"
    }
  ]
}
{
  "results": [
    {
      "check_id": "123456",
      "timestamp": 1601639904704,
      "orgID": 2,
      "result": {
        "runType": 2,
        "artifactsBucketKey": "2/e2e-tests/abc-def-ghi/results/17221670732431167/chrome.laptop_large/artifacts__1601639913277.json",
        "browserType": "chrome",
        "eventType": "finished",
        "stepDetails": [
          {
            "browserErrors": [],
            "skipped": false,
            "description": "Navigate to start URL",
            "warnings": [],
            "url": "about:blank",
            "value": "https://example.com",
            "duration": 1002,
            "allowFailure": false,
            "screenshotBucketKey": "2/e2e-tests/abc-def-ghi/results/17221670732431167/chrome.laptop_large/step-0__1601639913294.jpeg",
            "type": "goToUrlAndMeasureTti",
            "stepId": -1
          },
          {
            "browserErrors": [],
            "stepElementUpdates": {
              "version": 1,
              "multiLocator": {
                "ab": "/*[local-name()=\"html\"][1]/*[local-name()=\"body\"][1]/*[local-name()=\"div\"][1]/*[local-name()=\"h1\"][1]",
                "co": "[{\"text\":\"example domain\",\"textType\":\"directText\"}]",
                "cl": "/*[local-name()=\"html\"]/*[local-name()=\"body\"]/*[local-name()=\"div\"][1]/*[local-name()=\"h1\"][1]",
                "at": "/*[local-name()=\"html\"]/*[local-name()=\"body\"]/*[local-name()=\"div\"][1]/*[local-name()=\"h1\"][1]",
                "clt": "/descendant::*[text()[normalize-space(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ', 'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ')) = \"example domain\"]]",
                "ro": "//*[local-name()=\"h1\"]"
              }
            },
            "skipped": false,
            "description": "Test heading \"Example Domain\" content",
            "url": "https://www.example.com/",
            "checkType": "contains",
            "value": "Example Domain",
            "duration": 204,
            "allowFailure": false,
            "screenshotBucketKey": "2/e2e-tests/abc-def-ghi/results/17221670732431167/chrome.laptop_large/step-1__1601639913410.jpeg",
            "type": "assertElementContent",
            "stepId": 2275176
          }
        ],
        "browserVersion": "84.0.4147.135",
        "mainDC": "us1.prod",
        "timeToInteractive": 269,
        "device": {
          "name": "Laptop Large",
          "height": 1100,
          "width": 1440,
          "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
          "id": "chrome.laptop_large",
          "isMobile": false,
          "browser": "chrome"
        },
        "passed": true,
        "duration": 1206,
        "startUrl": "https://www.example.com",
        "metadata": {}
      },
      "dc_id": 30005,
      "resultID": "17221670732431167",
      "metadata": {}
    }
  ]
}

Utilisation de l’interface de ligne de commande

Installation du package

Le package est publié sous @datadog/datadog-ci dans le registre NPM.

Installez le package via NPM :

npm install --save-dev @datadog/datadog-ci

Installez le package via Yarn :

yarn add --dev @datadog/datadog-ci

Configurer le client

Pour configurer votre client, les clés d’API et d’application Datadog doivent être définies. Ces clés peuvent être définies de trois manières différentes :

  1. En tant que variables d’environnement :

    export DATADOG_API_KEY="<API_KEY>"
    export DATADOG_APP_KEY="<APPLICATION_KEY>"
    
  2. Via l’interface de ligne de commande lors de l’exécution de vos tests :

    datadog-ci synthetics run-tests --apiKey "<API_KEY>" --appKey "<APPLICATION_KEY>"
    
  3. Dans un fichier de configuration globale :

    Vous pouvez également créer un fichier de configuration JSON pour spécifier des options plus avancées. Définissez le chemin vers ce fichier à l’aide du flag --config lorsque vous lancez vos tests. Nommez votre fichier de configuration globale datadog-ci.json pour ne pas avoir à modifier le chemin par défaut.

    • apiKey : la clé d’API utilisée pour interroger l’API Datadog.
    • appKey : la clé d’application utilisée pour interroger l’API Datadog.
    • datadogSite : l’instance Datadog vers laquelle la requête est envoyée (valeurs autorisées : datadoghq.com ou datadoghq.eu). Valeur par défaut : datadoghq.com.
    • files : l’expression globale utilisée pour les fichiers de configuration des tests Synthetic.
    • global : les configurations à appliquer à tous les tests Synthetic (consultez ci-dessous la description de chaque champ).
    • proxy : le proxy à utiliser pour les connexions sortantes vers Datadog. Les clés host et port sont des arguments obligatoires. Par défaut, la clé protocol a pour valeur http. Elle peut prendre pour valeur http, https, socks, socks4, socks4a, socks5, socks5h, pac+data, pac+file, pac+ftp, pac+http ou pac+https. La bibliothèque proxy-agent est utilisée pour configurer le proxy.
    • subdomain : le nom du sous-domaine personnalisé permettant d’accéder à votre application Datadog. Si l’URL utilisée pour accéder à Datadog est myorg.datadoghq.com, la valeur de subdomain doit alors être définie sur myorg.

    Exemple de fichier de configuration globale :

    {
        "apiKey": "<DATADOG_API_KEY>",
        "appKey": "<DATADOG_APPLICATION_KEY>",
        "datadogSite": "datadoghq.com",
        "files": "{,!(node_modules)/**/}*.synthetics.json",
        "global": {
            "allowInsecureCertificates": true,
            "basicAuth": { "username": "test", "password": "test" },
            "body": "{\"fakeContent\":true}",
            "bodyType": "application/json",
            "cookies": "name1=value1;name2=value2;",
            "deviceIds": ["laptop_large"],
            "followRedirects": true,
            "headers": { "<NEW_HEADER>": "<NEW_VALUE>" },
                "locations": ["aws:us-west-1"],
            "retry": { "count": 2, "interval": 300 },
            "executionRule": "skipped",
            "startUrl": "{{URL}}?static_hash={{STATIC_HASH}}",
            "variables": { "titleVariable": "new value" },
            "pollingTimeout": 180000
        },
        "proxy": {
          "auth": {
            "username": "login",
            "password": "pwd"
          },
          "host": "127.0.0.1",
          "port": 3128,
          "protocol": "http"
        },
        "subdomain": "subdomainname"
    }
    

Configurer des tests

Par défaut, le client découvre et exécute automatiquement tous les tests spécifiés dans les fichiers **/*.synthetics.json (le chemin peut être configuré dans le fichier de configuration globale. Ces fichiers incluent une clé tests, qui contient un tableau d’objets avec les identifiants des tests à exécuter et toutes les configurations potentielles à appliquer à ces tests.

Exemple de fichier de configuration de test basique :

{
    "tests": [
        {
            "id": "<ID_TEST_PUBLIC>"
        },
        {
            "id": "<ID_TEST_PUBLIC>"
        }
    ]
}

Configuration supplémentaire

Par défaut, les tests utilisent leur configuration d’origine. Vous pouvez la consulter dans l’interface utilisateur ou lors de la récupération des configurations de vos tests depuis l’API).

Cependant, dans le cadre de votre déploiement CI, vous pouvez choisir de remplacer certains (ou l’ensemble) des paramètres de vos tests en utilisant les paramètres ci-dessous. Si vous souhaitez modifier la configuration de tous vos tests, ces mêmes paramètres peuvent être définis au niveau du fichier de configuration globale.

  • allowInsecureCertificates (booléen) : désactive les vérifications de certificat dans les tests API.
  • basicAuth (objet) : identifiants à utiliser pour une authentification basique.
    • username (chaîne) : nom d’utilisateur à utiliser pour l’authentification basique.
    • password (chaîne) : mot de passe à utiliser lors de l’authentification basique.
  • body (chaîne) : données à envoyer avec le test API Synthetic.
  • bodyType (chaîne) : type de données envoyées avec le test API Synthetic.
  • cookies (chaîne) : chaîne utilisée en tant qu’en-tête de cookie dans un test Browser ou API.
  • deviceIds (tableau) : liste des appareils sur lesquels le test Browser s’exécute.
  • followRedirects (booléen) : indique s’il faut suivre ou non les redirections HTTP dans les tests API.
  • headers (objet) : en-têtes à remplacer dans le test. La clé de cet objet est définie sur le nom de l’en-tête à remplacer, et sa valeur sur la nouvelle valeur de l’en-tête.
  • locations (tableau) : liste des emplacements à partir desquels le test s’exécute.
  • retry (objet) : stratégie définissant le comportement à adopter pour les nouvelles tentatives de test.
    • count (nombre entier) : nombre de tentatives à effectuer en cas d’échec d’un test.
    • interval (nombre entier) : intervalle entre chaque tentative (en millisecondes).
  • executionRule (chaîne) : règle d’exécution du test définissant le comportement de l’interface de ligne de commande en cas d’échec du test.
    • blocking : l’interface de ligne de commande renvoie une erreur si le test échoue.
    • non_blocking : l’interface de ligne de commande affiche seulement un avertissement si le test échoue.
    • skipped : le test n’est pas du tout exécuté.
  • startUrl (chaîne) : nouvelle URL de départ à fournir au test.
  • variables (objet) : variables à remplacer dans le test. La clé de cet objet est définie sur le nom de la variable à remplacer, et sa valeur sur la nouvelle valeur de la variable.
  • pollingTimeout (entier) : la durée après laquelle un test Synthetic est considéré comme un échec (en millisecondes).

Remarque : les nouvelles configurations de test sont prioritaires sur les configurations globales.

Exemple de fichier de configuration de test avancé :

{
    "tests": [
        {
            "id": "<ID_TEST_PUBLIC>",
            "config": {
                "allowInsecureCertificates": true,
                "basicAuth": { "username": "test", "password": "test" },
                "body": "{\"fakeContent\":true}",
                "bodyType": "application/json",
                "cookies": "name1=value1;name2=value2;",
                "deviceIds": ["laptop_large"],
                "followRedirects": true,
                "headers": { "<NOUVEL_ENTÊTE>": "<NOUVELLE_VALEUR>" },
            "locations": ["aws:us-west-1"],
                "retry": { "count": 2, "interval": 300 },
                "executionRule": "skipped",
                "startUrl": "{{URL}}?static_hash={{STATIC_HASH}}",
                "variables": { "titleVariable": "new value" },
                "pollingTimeout": 180000
            }
        }
    ]
}

Règle d’exécution

La règle d’exécution de chaque test peut également être définie dans l’application, au niveau du test. Utilisez le menu déroulant à proximité de l’option CI Execution.

La règle d’exécution associée au test est toujours la règle la plus restrictive ayant été définie dans le fichier de configuration. Les règles sont les suivantes (de la plus restrictive à la moins restrictive) : skipped, non_blocking, blocking. Ainsi, si votre test est configuré sur skipped dans l’interface, mais sur blocking dans le fichier de configuration, il sera ignoré (skipped) lors de l’exécution de vos tests.

URL de départ

Vous pouvez configurer l’URL de départ de votre test en indiquant la startUrl de l’objet de votre test. Pour créer votre propre URL de départ, utilisez l’une des parties de l’URL de départ d’origine de votre test et les variables d’environnement suivantes :

Variable d’environnementDescriptionExemple
URLURL de départ d’origine du testhttps://www.example.org:81/chemin/vers/element?abc=123
DOMAINNom de domaine du testexample.org
HOSTHost du testwww.example.org:81
HOSTNAMEHostname du testwww.example.org
ORIGINOrigine du testhttps://www.example.org:81
PARAMSParamètres de la requête du test?abc=123
PATHNAMEChemin de l’URl du test/chemin/vers/element
PORTPort du host du test81
PROTOCOLProtocole du testhttps:
SUBDOMAINSous-domaine du testwww

Par exemple, si l’URL de départ de votre test est https://www.example.org:81/chemin/vers/element?abc=123, elle peut s’écrire sous la forme suivante :

  • {{PROTOCOL}}//{{SUBDOMAIN}}.{{DOMAIN}}:{{PORT}}{{PATHNAME}}{{PARAMS}}
  • {{PROTOCOL}}//{{HOST}}{{PATHNAME}}{{PARAMS}}
  • {{URL}}

Exécution des tests

Vous pouvez faire en sorte que votre interface de ligne de commande découvre automatiquement tous vos tests Synthetic **/*.synthetics.json (ou tous les tests associés au chemin spécifié dans votre fichier de configuration globale) ou spécifier les tests que vous souhaitez exécuter à l’aide du flag -p,--public-id.

Exécutez des tests via l’interface de ligne de commande :

yarn datadog-ci synthetics run-tests

Remarque: si vous lancez vos tests avec un fichier de configuration globale personnalisé, ajoutez--config <CHEMIN_FICHIER_CONFIGURATION_GLOBALE> à votre commande.

Ajoutez les lignes suivantes à votre package.json :

{
  "scripts": {
    "datadog-ci-synthetics": "datadog-ci synthetics run-tests"
  }
}

Exécutez ensuite :

npm run datadog-ci-synthetics

Remarque : si vous lancez vos tests avec un fichier de configuration globale, ajoutez datadog-ci-synthetics --config <CHEMIN_FICHIER_CONFIGURATION_GLOBALE> à votre script datadog-ci-synthetics.

Afficher les résultats du test

Dans vos pipelines CI

Vous pouvez consulter les résultats des tests directement dans vos pipelines CI au fur et à mesure qu’ils s’exécutent.

Vous pouvez identifier la cause de l’échec d’un test en consultant les logs d’exécution et en recherchant les causes de l’assertion ayant échoué :

Dans l’application Datadog

Vous pouvez également consulter les résultats de vos tests répertoriés sur la page des détails des tests Datadog :

Pour aller plus loin