Les contrôles ATC automatisés sont indispensables pour assurer une qualité de code continue dans SAP BTP ABAP Environment. Alors que vous exécutez ATC manuellement dans ADT au quotidien, l’API ATC permet l’intégration dans les pipelines CI/CD pour des Quality Gates automatisés.
Pourquoi automatiser ATC ?
L’exécution manuelle des contrôles ATC a ses limites :
| Aspect | Manuel | Automatisé |
|---|---|---|
| Timing | Avant le transport | À chaque commit |
| Cohérence | Dépend du développeur | Toujours les mêmes vérifications |
| Oubli | Possible | Impossible |
| Reporting | Ponctuel | Continu |
| Analyse de tendances | Impossible | Données historiques |
| Standard d’équipe | Difficile à imposer | Automatiquement appliqué |
┌────────────────────────────────────────────────────────────────┐│ Pipeline CI/CD avec Quality Gate ATC │├────────────────────────────────────────────────────────────────┤│ ││ Git Push ──▶ Build ──▶ ABAP Unit ──▶ API ATC ──▶ Deploy ││ Tests Checks ││ │ ││ ▼ ││ ┌──────────────┐ ││ │ Quality │ ││ │ Gate │ ││ │ ──────────── │ ││ │ Erreurs: 0 │ ││ │ Warnings: <5 │ ││ └──────────────┘ ││ │└────────────────────────────────────────────────────────────────┘Prérequis
Avant de pouvoir utiliser l’API ATC, vous avez besoin de :
- SAP BTP ABAP Environment (instance Steampunk)
- Communication Arrangement pour les services ADT (SAP_COM_0763)
- Communication User avec les autorisations correspondantes
- Variante de vérification pour l’exécution automatisée
Configuration du Communication Arrangement
Le Communication Arrangement de l’ABAP Unit Runner s’applique également pour ATC :
┌────────────────────────────────────────────────────────────────┐│ Communication Arrangement: SAP_COM_0763 │├────────────────────────────────────────────────────────────────┤│ ││ Inbound Services (activés): ││ ☑ ADT Core Services ││ ☑ ADT ABAP Unit ││ ☑ ADT ATC (ABAP Test Cockpit) ││ ││ Autorisations requises: ││ • S_DEVELOP (lire objets de développement) ││ • S_ATC_ADM (administration ATC) ││ │└────────────────────────────────────────────────────────────────┘API ATC sur BTP
L’API ATC est basée sur le framework REST ADT et permet l’exécution programmatique de contrôles ATC.
Point de terminaison API
POST https://<system-url>/sap/bc/adt/atc/runsFormat de requête
<?xml version="1.0" encoding="UTF-8"?><atc:run xmlns:atc="http://www.sap.com/adt/atc" xmlns:adtcore="http://www.sap.com/adt/core" maximumVerdicts="100"> <objectSets> <objectSet kind="inclusive"> <adtcore:objectReferences> <adtcore:objectReference adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/Z_FLIGHT_BOOKING"/> </adtcore:objectReferences> </objectSet> </objectSets> <checkVariant> <atc:name>ABAP_CLOUD_READINESS</atc:name> </checkVariant></atc:run>Paramètres de requête importants
| Paramètre | Description | Exemple |
|---|---|---|
| maximumVerdicts | Nombre max. de findings | 100, 500, 1000 |
| objectReference | Objet à vérifier (package, classe) | devck/Z_FLIGHT_BOOKING |
| checkVariant | Variante de vérification | ABAP_CLOUD_READINESS |
Exemple cURL
# Démarrer contrôle ATC pour un packagecurl -X POST \ "https://my-system.abap.eu10.hana.ondemand.com/sap/bc/adt/atc/runs" \ -u "CICD_USER:password" \ -H "Content-Type: application/vnd.sap.atc.run.v1+xml" \ -H "Accept: application/vnd.sap.atc.run.v1+xml" \ -d @atc_config.xml \ -o atc_results.xmlDéfinir des variantes de vérification personnalisées
Les variantes de vérification déterminent quels contrôles sont exécutés avec quelle priorité.
Variantes de vérification standard sur BTP
| Variante | Description | Recommandé pour |
|---|---|---|
| ABAP_CLOUD_READINESS | Vérifie compatibilité Cloud | Migration vers ABAP Cloud |
| DEFAULT | Tous les contrôles standard | Qualité générale |
| SAP_CP | Contrôles SAP Cloud Platform | Développement BTP |
Récupérer variante de vérification via API
# Interroger les variantes de vérification disponiblescurl -X GET \ "https://my-system.abap.eu10.hana.ondemand.com/sap/bc/adt/atc/customizing/variants" \ -u "CICD_USER:password" \ -H "Accept: application/vnd.sap.atc.customizing.v1+xml"Créer une variante de vérification personnalisée
Dans SAP BTP ABAP Environment, vous créez des variantes de vérification via l’application Fiori Maintain ATC Check Variants :
┌────────────────────────────────────────────────────────────────┐│ Variante de vérification: Z_CI_PIPELINE │├────────────────────────────────────────────────────────────────┤│ ││ Description: Variante de vérification pour pipeline CI/CD ││ ││ ┌────────────────────────────────────────────────────────────┐ ││ │ Check │ Priorité │ Actif │ ││ ├────────────────────────────────┼───────────┼──────────────┤ ││ │ SLIN_CHECK (Syntax Check) │ 1 │ ☑ │ ││ │ SEC_CHECK (Security) │ 1 │ ☑ │ ││ │ PERF_CHECK (Performance) │ 2 │ ☑ │ ││ │ CONV_CHECK (Conventions) │ 3 │ ☑ │ ││ │ CLOUD_CHECK (Cloud Readiness) │ 1 │ ☑ │ ││ │ UNIT_TEST (Unit Tests) │ 2 │ ☐ │ ││ └────────────────────────────────┴───────────┴──────────────┘ ││ ││ Paramétrage des priorités: ││ • Priorité 1 (Erreur) → Build interrompu ││ • Priorité 2 (Warning) → Build avec avertissement ││ • Priorité 3 (Info) → Seulement protocolé ││ │└────────────────────────────────────────────────────────────────┘Catégories de vérification en détail
" Les principales catégories de vérification pour ABAP Cloud:
" 1. Cloud Readiness Checks" - Utilisation d'APIs non libérées" - Accès DB directs (SELECT sur tables standard)" - Utilisation d'instructions Dynpro
" 2. Security Checks" - Risques d'injection SQL" - Cross-Site Scripting (XSS)" - Authority Checks manquants" - Identifiants en dur
" 3. Performance Checks" - Éviter SELECT *" - Boucles avec SELECT" - WHERE clauses manquantes" - LOOP AT sans alternative READ TABLE
" 4. Naming Convention Checks" - Préfixe Z/Y pour objets personnalisés" - Directives de nommage pour variables" - Attribution de packageConfiguration de l’exécution automatique
Processus ATC en deux étapes
L’API ATC fonctionne de manière asynchrone - vous démarrez une exécution et interrogez les résultats :
┌─────────────────────────────────────────────────────────────────┐│ Workflow API ATC │├─────────────────────────────────────────────────────────────────┤│ ││ 1. POST /sap/bc/adt/atc/runs ││ ├─ Request: Configuration de vérification ││ └─ Response: Run-ID (Location Header) ││ ││ 2. Polling: GET /sap/bc/adt/atc/runs/{run-id} ││ ├─ Status: running → attendre ││ └─ Status: finished → récupérer résultats ││ ││ 3. GET /sap/bc/adt/atc/runs/{run-id}/results ││ └─ Response: Findings en XML ││ │└─────────────────────────────────────────────────────────────────┘Script Bash complet pour exécution ATC
#!/bin/bash# run_atc.sh - Exécuter contrôle ATC sur BTP
set -e
# ConfigurationSYSTEM_URL="${ABAP_ENDPOINT}"USER="${ABAP_USER}"PASSWORD="${ABAP_PASSWORD}"PACKAGE="${1:-Z_FLIGHT_BOOKING}"CHECK_VARIANT="${2:-ABAP_CLOUD_READINESS}"MAX_VERDICTS="${3:-500}"
echo "=== Démarrage contrôle ATC ==="echo "Package: $PACKAGE"echo "Variante: $CHECK_VARIANT"
# 1. Démarrer l'exécution ATCcat > atc_request.xml << EOF<?xml version="1.0" encoding="UTF-8"?><atc:run xmlns:atc="http://www.sap.com/adt/atc" xmlns:adtcore="http://www.sap.com/adt/core" maximumVerdicts="$MAX_VERDICTS"> <objectSets> <objectSet kind="inclusive"> <adtcore:objectReferences> <adtcore:objectReference adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/$PACKAGE"/> </adtcore:objectReferences> </objectSet> </objectSets> <checkVariant> <atc:name>$CHECK_VARIANT</atc:name> </checkVariant></atc:run>EOF
# Démarrer l'exécution et extraire Location HeaderRESPONSE=$(curl -s -D - \ -X POST \ "$SYSTEM_URL/sap/bc/adt/atc/runs" \ -u "$USER:$PASSWORD" \ -H "Content-Type: application/vnd.sap.atc.run.v1+xml" \ -H "Accept: application/vnd.sap.atc.run.v1+xml" \ -d @atc_request.xml)
RUN_ID=$(echo "$RESPONSE" | grep -i "location:" | sed 's/.*runs\///' | tr -d '\r\n')
if [ -z "$RUN_ID" ]; then echo "::error::Échec du démarrage de l'exécution ATC" echo "$RESPONSE" exit 1fi
echo "Exécution ATC démarrée: $RUN_ID"
# 2. Attendre la fin (Polling)MAX_ATTEMPTS=60ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do STATUS_RESPONSE=$(curl -s \ -X GET \ "$SYSTEM_URL/sap/bc/adt/atc/runs/$RUN_ID" \ -u "$USER:$PASSWORD" \ -H "Accept: application/vnd.sap.atc.run.v1+xml")
STATUS=$(echo "$STATUS_RESPONSE" | grep -oP 'status="\K[^"]+' || echo "unknown")
echo "Status: $STATUS (Tentative $((ATTEMPT+1))/$MAX_ATTEMPTS)"
if [ "$STATUS" = "finished" ]; then break fi
sleep 5 ATTEMPT=$((ATTEMPT+1))done
if [ "$STATUS" != "finished" ]; then echo "::error::Timeout de l'exécution ATC" exit 1fi
# 3. Récupérer les résultatscurl -s \ -X GET \ "$SYSTEM_URL/sap/bc/adt/atc/runs/$RUN_ID/results" \ -u "$USER:$PASSWORD" \ -H "Accept: application/vnd.sap.atc.worklist.v1+xml" \ -o atc_results.xml
echo "=== Résultats ATC sauvegardés dans atc_results.xml ==="Évaluation et reporting des résultats
Format de réponse ATC
<?xml version="1.0" encoding="UTF-8"?><atc:worklist xmlns:atc="http://www.sap.com/adt/atc" xmlns:adtcore="http://www.sap.com/adt/core" timestamp="2026-02-15T10:30:00Z" usedCheckVariant="Z_CI_PIPELINE"> <objects> <object adtcore:uri="/sap/bc/adt/oo/classes/zcl_flight_booking" adtcore:name="ZCL_FLIGHT_BOOKING" adtcore:type="CLAS"> <findings> <finding checkId="CL_CI_CRITICAL_API_USE" checkTitle="Non-released API usage" messageId="001" messageTitle="Usage of non-released API detected" priority="1" location="/sap/bc/adt/oo/classes/zcl_flight_booking/source/main#start=45,10"> <atc:quickfixes count="1"/> </finding> <finding checkId="CL_CI_SEC_INJECTION" checkTitle="SQL Injection Risk" messageId="002" messageTitle="Potential SQL injection vulnerability" priority="1" location="/sap/bc/adt/oo/classes/zcl_flight_booking/source/main#start=78,5"> <atc:quickfixes count="0"/> </finding> <finding checkId="CL_CI_CONV_NAMING" checkTitle="Naming Convention" messageId="003" messageTitle="Variable naming does not follow convention" priority="3" location="/sap/bc/adt/oo/classes/zcl_flight_booking/source/main#start=12,8"> <atc:quickfixes count="1"/> </finding> </findings> </object> </objects> <statistics> <totalFindings>3</totalFindings> <findingsByPriority> <priority1>2</priority1> <priority2>0</priority2> <priority3>1</priority3> </findingsByPriority> </statistics></atc:worklist>Script Python pour analyse des résultats
import xml.etree.ElementTree as ETimport sysimport jsonfrom dataclasses import dataclass, asdictfrom typing import List
@dataclassclass Finding: check_id: str check_title: str message: str priority: int object_name: str location: str has_quickfix: bool
def parse_atc_results(xml_file: str) -> dict: tree = ET.parse(xml_file) root = tree.getroot()
ns = { 'atc': 'http://www.sap.com/adt/atc', 'adtcore': 'http://www.sap.com/adt/core" }
findings: List[Finding] = [] priority_counts = {1: 0, 2: 0, 3: 0}
for obj in root.findall('.//atc:object', ns): obj_name = obj.get('{http://www.sap.com/adt/core}name', 'Unknown')
for finding in obj.findall('.//atc:finding', ns): priority = int(finding.get('priority', 3)) priority_counts[priority] = priority_counts.get(priority, 0) + 1
quickfixes = finding.find('atc:quickfixes', ns) has_quickfix = quickfixes is not None and int(quickfixes.get('count', 0)) > 0
findings.append(Finding( check_id=finding.get('checkId', ''), check_title=finding.get('checkTitle', ''), message=finding.get('messageTitle', ''), priority=priority, object_name=obj_name, location=finding.get('location', ''), has_quickfix=has_quickfix ))
return { 'total': len(findings), 'errors': priority_counts.get(1, 0), 'warnings': priority_counts.get(2, 0), 'info': priority_counts.get(3, 0), 'findings': [asdict(f) for f in findings] }
def print_report(results: dict, error_threshold: int = 0, warning_threshold: int = 5): print("=" * 60) print("RAPPORT QUALITÉ ATC") print("=" * 60) print(f"Total Findings: {results['total']}") print(f" Erreurs (P1): {results['errors']}") print(f" Warnings (P2): {results['warnings']}") print(f" Info (P3): {results['info']}") print("=" * 60)
# Afficher findings groupés par priorité for priority in [1, 2, 3]: priority_findings = [f for f in results['findings'] if f['priority'] == priority] if priority_findings: print(f"\nFindings Priorité {priority}:") print("-" * 40) for f in priority_findings: print(f" [{f['check_id']}] {f['object_name']}") print(f" {f['message']}") quickfix = "✓ Quickfix disponible" if f['has_quickfix'] else "" print(f" {f['location']} {quickfix}")
print("\n" + "=" * 60)
# Vérifier les seuils exit_code = 0 if results['errors'] > error_threshold: print(f"::error::Trouvé {results['errors']} erreur(s) (seuil: {error_threshold})") exit_code = 1
if results['warnings'] > warning_threshold: print(f"::warning::Trouvé {results['warnings']} warning(s) (seuil: {warning_threshold})")
return exit_code
if __name__ == '__main__': if len(sys.argv) < 2: print("Usage: python parse_atc_results.py <xml_file> [--json]") sys.exit(1)
results = parse_atc_results(sys.argv[1])
if '--json' in sys.argv: print(json.dumps(results, indent=2)) else: exit_code = print_report(results) sys.exit(exit_code)Intégration avec GitHub/GitLab
Workflow GitHub Actions
name: Quality Gate ATC
on: push: branches: [ main, develop ] pull_request: branches: [ main ]
env: PACKAGE: Z_FLIGHT_BOOKING CHECK_VARIANT: ABAP_CLOUD_READINESS ERROR_THRESHOLD: 0 WARNING_THRESHOLD: 5
jobs: atc-check: name: Contrôle qualité ATC runs-on: ubuntu-latest
steps: - name: Checkout uses: actions/checkout@v4
- name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11"
- name: Créer configuration ATC run: | cat > atc_config.xml << 'EOF" <?xml version="1.0" encoding="UTF-8"?> <atc:run xmlns:atc="http://www.sap.com/adt/atc" xmlns:adtcore="http://www.sap.com/adt/core" maximumVerdicts="500"> <objectSets> <objectSet kind="inclusive"> <adtcore:objectReferences> <adtcore:objectReference adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/${{ env.PACKAGE }}"/> </adtcore:objectReferences> </objectSet> </objectSets> <checkVariant> <atc:name>${{ env.CHECK_VARIANT }}</atc:name> </checkVariant> </atc:run> EOF
- name: Démarrer exécution ATC id: start-atc run: | RESPONSE=$(curl -s -D - \ -X POST \ "${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs" \ -u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \ -H "Content-Type: application/vnd.sap.atc.run.v1+xml" \ -H "Accept: application/vnd.sap.atc.run.v1+xml" \ -d @atc_config.xml)
RUN_ID=$(echo "$RESPONSE" | grep -i "location:" | sed 's/.*runs\///' | tr -d '\r\n')
if [ -z "$RUN_ID" ]; then echo "::error::Échec démarrage exécution ATC" exit 1 fi
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT echo "Exécution ATC démarrée: $RUN_ID"
- name: Attendre fin ATC run: | RUN_ID="${{ steps.start-atc.outputs.run_id }}" MAX_ATTEMPTS=60
for i in $(seq 1 $MAX_ATTEMPTS); do STATUS=$(curl -s \ -X GET \ "${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs/$RUN_ID" \ -u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \ -H "Accept: application/vnd.sap.atc.run.v1+xml" \ | grep -oP 'status="\K[^"]+' || echo "unknown")
echo "Status: $STATUS (Tentative $i/$MAX_ATTEMPTS)"
if [ "$STATUS" = "finished" ]; then break fi
sleep 5 done
if [ "$STATUS" != "finished" ]; then echo "::error::Timeout exécution ATC" exit 1 fi
- name: Récupérer résultats ATC run: | RUN_ID="${{ steps.start-atc.outputs.run_id }}"
curl -s \ -X GET \ "${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs/$RUN_ID/results" \ -u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \ -H "Accept: application/vnd.sap.atc.worklist.v1+xml" \ -o atc_results.xml
- name: Analyser et évaluer résultats id: parse run: | python << 'PYTHON_SCRIPT" import xml.etree.ElementTree as ET import os
tree = ET.parse('atc_results.xml') root = tree.getroot() ns = {'atc': 'http://www.sap.com/adt/atc', 'adtcore': 'http://www.sap.com/adt/core'}
errors = warnings = info = 0
for finding in root.findall('.//atc:finding', ns): priority = int(finding.get('priority', 3)) if priority == 1: errors += 1 elif priority == 2: warnings += 1 else: info += 1
with open(os.environ['GITHUB_OUTPUT'], 'a') as f: f.write(f"errors={errors}\n") f.write(f"warnings={warnings}\n") f.write(f"info={info}\n") f.write(f"total={errors + warnings + info}\n")
print(f"Erreurs: {errors}, Warnings: {warnings}, Info: {info}")
# Vérifier Quality Gate if errors > int(os.environ.get('ERROR_THRESHOLD', 0)): print(f"::error::Quality Gate échoué: {errors} erreur(s) trouvée(s)") exit(1) PYTHON_SCRIPT
- name: Télécharger résultats ATC uses: actions/upload-artifact@v4 with: name: atc-results path: atc_results.xml
- name: Créer résumé if: always() run: | cat >> $GITHUB_STEP_SUMMARY << EOF ## Résultats Quality Gate ATC
| Métrique | Valeur | Seuil | |--------|-------|-----------| | Erreurs (P1) | ${{ steps.parse.outputs.errors }} | ${{ env.ERROR_THRESHOLD }} | | Warnings (P2) | ${{ steps.parse.outputs.warnings }} | ${{ env.WARNING_THRESHOLD }} | | Info (P3) | ${{ steps.parse.outputs.info }} | - | | **Total** | ${{ steps.parse.outputs.total }} | |
**Status:** ${{ steps.parse.outputs.errors == 0 && '✅ Réussi' || '❌ Échoué' }} EOFPipeline GitLab CI/CD
stages: - quality
variables: PACKAGE: Z_FLIGHT_BOOKING CHECK_VARIANT: ABAP_CLOUD_READINESS ERROR_THRESHOLD: "0"
atc-quality-gate: stage: quality image: python:3.11-slim before_script: - apt-get update && apt-get install -y curl script: # Démarrer exécution ATC - | RESPONSE=$(curl -s -D - \ -X POST \ "${ABAP_ENDPOINT}/sap/bc/adt/atc/runs" \ -u "${ABAP_USER}:${ABAP_PASSWORD}" \ -H "Content-Type: application/vnd.sap.atc.run.v1+xml" \ -H "Accept: application/vnd.sap.atc.run.v1+xml" \ -d "<atc:run xmlns:atc=\"http://www.sap.com/adt/atc\" xmlns:adtcore=\"http://www.sap.com/adt/core\" maximumVerdicts=\"500\"> <objectSets> <objectSet kind=\"inclusive\"> <adtcore:objectReferences> <adtcore:objectReference adtcore:uri=\"/sap/bc/adt/vit/wb/object_type/devck/object_name/${PACKAGE}\"/> </adtcore:objectReferences> </objectSet> </objectSets> <checkVariant> <atc:name>${CHECK_VARIANT}</atc:name> </checkVariant> </atc:run>")
RUN_ID=$(echo "$RESPONSE" | grep -i "location:" | sed 's/.*runs\///' | tr -d '\r\n') echo "ATC Run ID: $RUN_ID"
# Attendre la fin - | for i in $(seq 1 60); do STATUS=$(curl -s \ "${ABAP_ENDPOINT}/sap/bc/adt/atc/runs/${RUN_ID}" \ -u "${ABAP_USER}:${ABAP_PASSWORD}" \ -H "Accept: application/vnd.sap.atc.run.v1+xml" \ | grep -oP 'status="\K[^"]+' || echo "unknown")
echo "Tentative $i: Status = $STATUS" [ "$STATUS" = "finished" ] && break sleep 5 done
# Récupérer les résultats - | curl -s \ "${ABAP_ENDPOINT}/sap/bc/adt/atc/runs/${RUN_ID}/results" \ -u "${ABAP_USER}:${ABAP_PASSWORD}" \ -H "Accept: application/vnd.sap.atc.worklist.v1+xml" \ -o atc_results.xml
# Vérifier les résultats - | python3 << 'EOF" import xml.etree.ElementTree as ET import sys import os
tree = ET.parse('atc_results.xml') root = tree.getroot() ns = {'atc': 'http://www.sap.com/adt/atc'}
errors = sum(1 for f in root.findall('.//atc:finding', ns) if f.get('priority') == '1') print(f"Trouvé {errors} erreur(s)")
if errors > int(os.environ.get('ERROR_THRESHOLD', 0)): sys.exit(1) EOF artifacts: paths: - atc_results.xml reports: junit: atc_results.xml when: always rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == "main"Bonnes pratiques
| Aspect | Recommandation |
|---|---|
| Variante de vérification | Variante propre pour CI/CD avec priorités claires |
| Error-Threshold | 0 pour Priorité 1 (aucune erreur autorisée) |
| Warning-Threshold | Fixer de manière réaliste, réduire progressivement |
| Timeout | Max. 5 minutes pour grands packages |
| Quickfixes | Afficher dans rapport, ne pas appliquer automatiquement |
| Trend-Tracking | Protocoler les findings au fil du temps |
| Standards d’équipe | Coordonner la variante de vérification en équipe |
| Exception-Handling | Documenter les exceptions justifiées |
Dépannage
| Problème | Cause possible | Solution |
|---|---|---|
| 401 Unauthorized | Identifiants incorrects | Vérifier user/mot de passe |
| 403 Forbidden | Autorisation ATC manquante | Vérifier S_ATC_ADM |
| 404 Not Found | Package/variante inexistant | Vérifier noms |
| Timeout | Package trop grand | Diviser en packages plus petits |
| Aucun Finding | Variante de vérification vide | Activer checks dans variante |
| Run reste “running” | Système surchargé | Réessayer plus tard |
Ressources complémentaires
- ABAP Test Cockpit - Bases ATC et utilisation manuelle
- ABAP Unit Runner sur BTP - Exécuter automatiquement les tests unitaires
- CI/CD avec ABAP Cloud - Concepts de pipeline complets
- Stratégie Clean Core - Standards de qualité pour ABAP Cloud