Aller au contenu

Parser le rapport

Maintenant que vos tests s'exécutent et génèrent des rapports, vous devez convertir ces rapports dans un format que SquashTM peut comprendre.

Ce que vous apprendrez dans cette section :

  • Parser un rapport de test xUnit XML issu de Robot Framework
  • Le convertir au format JSON de SquashTM
  • Faire correspondre les résultats de tests aux références de test automatisé que vous avez configurées dans SquashTM

Exemple Robot Framework et xUnit XML

Cette section démontre le parsing de sortie xUnit XML depuis Robot Framework. Si vous utilisez un framework de test ou un format de rapport différent (ex. Cucumber JSON), vous devrez adapter la logique du parser pour correspondre à la structure spécifique de votre rapport.

Dans la section précédente, vous avez configuré un pipeline qui exécute Robot Framework et produit un rapport xunit.xml. Dans cette section, vous ajouterez un parser au pipeline qui convertit xunit.xml au format JSON de SquashTM.

Voir le script de parser complet

Vous pouvez consulter le script de parser complet ici : parse_robot_results.py.

Exemple : GitLab CI/CD + Robot Framework

Étape 1 : Créer le script de parser

Créez un script Python qui parse le fichier XML xUnit et génère un fichier JSON compatible avec SquashTM.

Créez un répertoire ci dans votre projet et ajoutez le script de parser :

your-project/
├── .gitlab-ci.yml
├── ci/
│   └── parse_robot_results.py    ← Créez ce fichier
├── tests/
│   └── login_validation_tests.robot
└── ...

Fichier : ci/parse_robot_results.py

#!/usr/bin/env python3
"""
Parse xUnit/JUnit XML test results and generate a SquashTM-compatible JSON report.

This script extracts test results from xUnit/JUnit XML files and creates
a structured JSON report compatible with SquashTM API format.
"""

import base64
import json
import xml.etree.ElementTree as ET
from pathlib import Path


def encode_file_to_base64(file_path):
    """Encode a file to base64."""
    with open(file_path, 'rb') as f:
        return base64.b64encode(f.read()).decode('utf-8')


def parse_tests(xml_file):
    """Parse xUnit/JUnit XML file."""
    tree = ET.parse(xml_file)
    root = tree.getroot()

    tests = []
    suite_name = root.get('name', 'Suite')

    # Loop through all test cases
    for testcase in root.findall('.//testcase'):
        test_name = testcase.get('name', 'Test')
        classname = testcase.get('classname', suite_name)
        time_seconds = float(testcase.get('time', '0'))

        # Determine status
        failure = testcase.find('failure')
        error = testcase.find('error')
        skipped = testcase.find('skipped')

        if failure is not None:
            status = 'FAILURE'
            failure_message = failure.get('message', failure.text or 'Test failed')
            failure_details = [failure_message.strip()]
        elif error is not None:
            status = 'BLOCKED'
            failure_details = None
        elif skipped is not None:
            status = 'SKIPPED'
            failure_details = None
        else:
            status = 'SUCCESS'
            failure_details = None

        # Build reference as '<InnermostSuite>.<TestName>'
        suite_for_ref = classname.split('.')[-1]

        # Create test result
        result = {
            'reference': f"{suite_for_ref}.{test_name}",
            'status': status,
            'duration': round(time_seconds * 1000)  # Convert to milliseconds
        }

        # Add failure details if present
        if failure_details:
            result['failure_details'] = failure_details

        tests.append(result)

    return tests


def create_attachments():
    """Create attachments (test report files encoded in base64)."""
    attachments = []
    files = ['xunit.xml', 'report.html', 'log.html', 'output.xml']

    for file in files:
        if Path(file).exists():
            attachments.append({
                'name': file,
                'content': encode_file_to_base64(file)
            })

    return attachments


def main():
    """Main function."""
    tests = parse_tests('xunit.xml')

    attachments = create_attachments()

    report = {
        'automated_test_suite': {
            'attachments': attachments
        },
        'tests': tests
    }

    with open('result.json', 'w', encoding='utf-8') as f:
        json.dump(report, f, indent=2, ensure_ascii=False)

    print(f"{len(tests)} test(s) parsed")
    print(f"result.json created with {len(attachments)} attachment(s)")


if __name__ == '__main__':
    main()

Comment fonctionne le parser

Le script effectue plusieurs opérations : il parse le fichier XML xUnit, crée les pièces jointes et génère le JSON SquashTM.

Implémentation spécifique au format

Les sections suivantes expliquent la logique de parsing spécifique au format xUnit XML. Si vous utilisez un format de rapport différent, ces sections vous aideront à comprendre ce qui doit être adapté pour votre format.

1. Parser la structure XML xUnit

La fonction parse_tests() lit le format xUnit qui contient des éléments <testcase> avec des attributs comme name, classname et time. Chaque cas de test peut contenir des éléments enfants : <failure>, <error> ou <skipped> qui indiquent le statut du test.

2. Mapper le statut des tests

Le parser mappe les résultats xUnit aux statuts SquashTM :

  • Élément <failure> → statut FAILURE dans SquashTM
  • Élément <error> → statut BLOCKED dans SquashTM
  • Élément <skipped> → statut SKIPPED dans SquashTM
  • Pas de failure/error/skipped → statut SUCCESS dans SquashTM
3. Construire la référence de test automatisé

La référence identifie de manière unique chaque test dans SquashTM :

  • Format : <SuiteName>.<TestName> (par exemple, Login Validation Tests.Valid Login Passes)
  • Cette référence doit correspondre au champ référence du test automatisé configuré dans vos cas de test SquashTM
4. Créer les pièces jointes

Pièces jointes spécifiques à Robot Framework

Les pièces jointes suivantes sont spécifiques à Robot Framework. Adaptez les noms de fichiers et les types pour correspondre aux fichiers de sortie de votre framework de test.

La fonction create_attachments() encode les fichiers de rapport en base64 :

  • xunit.xml : Rapport de test au format xUnit
  • report.html : Rapport HTML généré par Robot Framework
  • log.html : Log détaillé des tests
  • output.xml : Sortie XML complète de Robot Framework
5. Extraire des informations supplémentaires
  • Durée : Convertie de secondes (xUnit) en millisecondes (SquashTM)
  • Détails d'échec : Extraits du message ou du contenu texte de l'élément <failure>
6. Générer le fichier JSON

Le script crée un fichier result.json contenant la structure complète avec les tests et les pièces jointes, prêt à être envoyé à SquashTM.

Exemple de transformation

Entrée XML xUnit (test échoué) :

<testcase classname="Login Validation Tests" name="Invalid Login Fails" time="0.456">
  <failure message="AssertionError: Expected login to fail but it succeeded">
    Login with invalid credentials should have been rejected.
  </failure>
</testcase>

Sortie JSON SquashTM :

{
  "reference": "Login Validation Tests.Invalid Login Fails",
  "status": "FAILURE",
  "duration": 456,
  "failure_details": [
    "AssertionError: Expected login to fail but it succeeded"
  ]
}

Pour la référence complète de la structure JSON incluant les champs optionnels comme automated_test_suite et les pièces jointes, consultez la spécification détaillée du format

Envoi vers SquashTM

Dans la section suivante, vous ajouterez le code pour envoyer automatiquement ce fichier result.json à SquashTM via l'API. Pour l'instant, le fichier est simplement généré et sauvegardé comme artefact.

Étape 2 : Ajouter le job de parser au pipeline

Maintenant, ajoutez un nouveau job à votre .gitlab-ci.yml qui exécute le parser après la fin des tests.

Ouvrez votre fichier .gitlab-ci.yml et ajoutez une étape post et le job de parser :

stages:
  - test
  - post  # Ajoutez cette nouvelle étape

# ... (conservez votre job robotframework-tests existant)

parse-and-publish:
  stage: post
  needs:
    - job: robotframework-tests
      artifacts: true
  when: always
  allow_failure: false
  script:
    - python --version
    - python ci/parse_robot_results.py
  artifacts:
    when: always
    expire_in: 7 days
    paths:
      - result.json

Ce que cela fait :

  • stage: post : S'exécute après la fin de l'étape test
  • needs : Attend le job robotframework-tests et télécharge ses artefacts (incluant xunit.xml). Cela garantit que le job de parser a accès au fichier xunit.xml généré par le job de test.
  • when: always : S'exécute même si les tests ont échoué (nous voulons parser tous les résultats), garantissant que tous les résultats sont capturés.
  • allow_failure: false : Fait échouer le pipeline si le parsing échoue
  • script : Exécute le script Python de parser
  • artifacts : Sauvegarde le fichier result.json généré pour inspection et traçabilité

Fichier de pipeline complet

À ce stade, votre .gitlab-ci.yml complet devrait ressembler à ceci :

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
    - when: never

variables:
  ROBOT_VERSION: "7.4.1"

default:
  image: python:3.14-slim

stages:
  - test
  - post

robotframework-tests:
  stage: test
  allow_failure: true
  script:
    - python --version
    - pip install --upgrade pip --root-user-action=ignore
    - pip install robotframework==${ROBOT_VERSION} --root-user-action=ignore
    - robot --xunit xunit.xml ./tests/
  artifacts:
    when: always
    expire_in: 7 days
    paths:
      - output.xml
      - log.html
      - report.html
      - xunit.xml
    reports:
      junit: xunit.xml

parse-and-publish:
  stage: post
  needs:
    - job: robotframework-tests
      artifacts: true
  when: always
  allow_failure: false
  script:
    - python --version
    - python ci/parse_robot_results.py
  artifacts:
    when: always
    expire_in: 7 days
    paths:
      - result.json

Étape 3 : Commiter et vérifier

Commitez vos changements et poussez vers GitLab :

git add ci/parse_robot_results.py .gitlab-ci.yml
git commit -m "Add test results parser"
git push

Vérifier le parser

  1. Allez dans votre projet GitLab
  2. Naviguez vers Build → Pipelines
  3. Cliquez sur le dernier pipeline
  4. Vous devriez maintenant voir deux jobs : robotframework-tests et parse-and-publish
  5. Cliquez sur le job parse-and-publish pour voir la sortie du parser
  6. Une fois terminé, téléchargez l'artefact result.json pour inspecter les résultats parsés

Ce que vous avez accompli

Votre pipeline CI/CD maintenant :

  • Exécute les tests automatisés
  • Parse les résultats de tests au format JSON de SquashTM
  • Génère un fichier result.json avec tous les résultats de tests
  • Fait correspondre les résultats de tests aux références de test automatisé

Prochaine étape

Maintenant que vous avez des résultats de tests parsés au format JSON de SquashTM, l'étape finale est de publier ces résultats dans votre instance SquashTM via l'API.

Dans la section suivante, vous apprendrez comment ajouter un job qui envoie le fichier result.json à SquashTM.

Passez à Publier dans SquashTM