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