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>→ statutFAILUREdans SquashTM - Élément
<error>→ statutBLOCKEDdans SquashTM - Élément
<skipped>→ statutSKIPPEDdans SquashTM - Pas de failure/error/skipped → statut
SUCCESSdans 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 xUnitreport.html: Rapport HTML généré par Robot Frameworklog.html: Log détaillé des testsoutput.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'étapetestneeds: Attend le jobrobotframework-testset télécharge ses artefacts (incluantxunit.xml). Cela garantit que le job de parser a accès au fichierxunit.xmlgé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 échouescript: Exécute le script Python de parserartifacts: Sauvegarde le fichierresult.jsongé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
- Allez dans votre projet GitLab
- Naviguez vers Build → Pipelines
- Cliquez sur le dernier pipeline
- Vous devriez maintenant voir deux jobs :
robotframework-testsetparse-and-publish - Cliquez sur le job
parse-and-publishpour voir la sortie du parser - Une fois terminé, téléchargez l'artefact
result.jsonpour 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.jsonavec 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