Capturas tomadas en vivo · Código copiado de suites validadas · v0.8.5

SAPFX en imágenes: SAP GUI, SAP Fiori y API, mostrados en sistemas reales

SAPFX (paquete robotframework-sapfx) es un conjunto de bibliotecas de Robot Framework de código abierto para automatizar las pruebas de SAP. Esta página muestra lo que hace, pantalla por pantalla: cada captura procede de un sistema SAP real del laboratorio (ABAP Platform 1909 y 2023 en Docker, una aplicación SAP Fiori® Elements servida en local) y cada extracto de código está copiado de una suite validada en vivo, con su fecha y su resultado. No se inventa ninguna keyword: un control automático confronta cada ejemplo con su suite de origen y con la documentación de las keywords.

9
pruebas híbridas, en dos o tres canales
5
entornos mostrados: SAP GUI, SAP Fiori, WebGUI, API, SAP BTP
18
capturas de pantallas reales
30
extractos de código copiados de suites validadas
El núcleo de SAPFX

La fuerza de la hibridación: una prueba, dos o tres canales

Una prueba de SAPFX no está encerrada en un canal. Prepara por la API, actúa en la pantalla y verifica por un canal independiente, con las mismas reglas y en el mismo informe de Robot Framework. Las nueve pruebas siguientes se validaron en vivo en sistemas SAP de desarrollo; las tres primeras se reejecutaron el 5 de octubre de 2026 para esta página, y todas siguieron en verde.

Pantalla + API + visual

La pantalla y la API cuentan los mismos productos, y la pantalla queda sellada

El número de productos del modelo de demostración EPM se cuenta dos veces en el mismo sistema: con el botón «Number of Entries» de SE16 en SAP GUI y con el $count del servicio OData que proyecta la misma tabla. Ambos deben ser iguales; una diferencia delataría un servicio que filtra, un dato fantasma o un mandante cruzado. Después, la pantalla de selección que sirvió para el recuento se compara con una captura de referencia mediante una huella perceptual (Screen Should Match Baseline), con las zonas volátiles enmascaradas: el canal de píxeles ve lo que ni la API ni el scripting ven.

SAP GUI (SE16)ODataHuella visual

Prueba: Suite «cruce de API y pantalla sellada por una aserción visual»: 3/3 en A4H (release 754), validada el 17/07/2026 y reejecutada el 05/10/2026: «Productos EPM: 205 vía OData == 205 vía SE16».

tests/robot/cross_paradigm_api_visual.robot
Product Count Agrees Across API And GUI Channels
    # …
    ${gui_count}=    Count Table Entries    ${EPM_PRODUCTS_TABLE}
    Should Be True    ${gui_count} > 0
    ...    msg=Table ${EPM_PRODUCTS_TABLE} vide : données EPM absentes sur ce système ?
    ${api_count}=    Get Odata Count    ${EPM_PRODUCTS_PATH}    alias=a4h
    Should Be Equal As Integers    ${api_count}    ${gui_count}
    ...    msg=OData $count (${api_count}) ≠ SE16 ${EPM_PRODUCTS_TABLE} (${gui_count}).
    Log    Produits EPM : ${api_count} via OData == ${gui_count} via SE16.
# …
SE16 Product Screen Matches Its Visual Baseline
    # …
    Open Table In SE16    ${EPM_PRODUCTS_TABLE}
    Log Screenshot    Écran de sélection SE16 de ${EPM_PRODUCTS_TABLE} (source du compte GUI)
    Screen Should Match Baseline    ${VISUAL_BASELINE_NAME}
    ...    threshold=${VISUAL_THRESHOLD}    baseline_directory=${VISUAL_BASELINE_DIR}
    ...    mask_elements=auto    per_resolution=${True}
API + WebGUI + RFC

El mismo precio leído por tres canales y comparado entre ellos

Se descubre un producto en el sistema de destino (nunca fijado en el código) y luego se lee por el servicio OData, por la cuadrícula SE16 del WebGUI y por RFC_READ_TABLE. Los tres precios se comparan entre sí, no cada uno con un valor esperado: un valor común también pasaría si dos canales leyeran la misma copia obsoleta. La pantalla muestra 3,25 donde los protocolos devuelven 3.25: la notación decimal del usuario se lee en el sistema y luego se verifica con un ida y vuelta. Antes de cualquier lectura, cada canal demuestra su destino con su propio discriminante (release en el lado RFC, volumen del catálogo Gateway en el lado API, dirección alcanzada en el lado WebGUI), porque los dos sistemas del laboratorio anuncian el mismo identificador.

ODataWebGUI (SE16)RFC

Prueba: Suite «ciclo de vida de un producto EPM leído por tres canales»: 7/7 en la release 754 y 7/7 en la release 758 el 21/09/2026, reejecutada 7/7 en A4H el 05/10/2026. Solo lectura.

tests/robot/cross/cycle_vie_produit_epm_trois_canaux.robot
6. Assertion reine : les trois canaux rendent le même prix
    # …
    ${prix}=    The Three Channels Should Agree On The Price
    ...    ${API_RECORD}    ${WEBGUI_RECORD}    ${RFC_RECORD}
    ...    ${DECIMAL_NOTATION}
    ${devise}=    The Three Channels Should Agree On The Currency
    ...    ${API_RECORD}    ${WEBGUI_RECORD}    ${RFC_RECORD}
resources/page_objects/sepmra_prod_man.resource
Read Epm Products By Api
    # …
    ${projection}=    Set Variable
    ...    ${EPM_PRODUCT_API_ID_FIELD},${EPM_PRODUCT_API_PRICE_FIELD},${EPM_PRODUCT_API_CURRENCY_FIELD}
    ${chemin}=    Set Variable    ${EPM_PROD_MAN_SERVICE}/${EPM_PRODUCT_ENTITY_SET}
    IF    '${top}' == '${EMPTY}'
        ${entites}=    Get Odata Entities    ${chemin}    alias=${alias}
        ...    $filter=${critere}    $select=${projection}    $orderby=${EPM_PRODUCT_API_ID_FIELD}
# …
Read Epm Product By Webgui
    # …
    [Arguments]    ${product}    ${url}
    Open WebGui Data Browser    ${url}
    Display WebGui Table Contents With Filter    ${EPM_PRODUCT_TABLE}
    ...    ${EPM_PRODUCT_KEY_COLUMN}=${product}
    ${extrait}=    Extract Displayed WebGui Grid
    ...    key=${EPM_PRODUCT_KEY_COLUMN}
    ...    source=produits EPM (${EPM_PRODUCT_TABLE}) filtrés sur ${product}
    Table Extract Should Be Complete    ${extrait}
# …
Read Epm Product By Rfc
    # …
    [Arguments]    ${product}    ${alias}=${RFC_ALIAS}
    ${lignes}=    Read Business Records    ${EPM_PRODUCT_TABLE}
    ...    ${EPM_PRODUCT_COLUMNS}
    ...    filter=${EPM_PRODUCT_KEY_COLUMN} EQ '${product}'    alias=${alias}
Launchpad + RFC + HTTP

El mosaico muestra lo que cuenta la vista CDS

El mosaico «Approve Purchase Orders» del launchpad de SAP Fiori muestra un contador. La prueba lo obliga a actualizarse, demuestra que la respuesta de red corresponde realmente a la cifra mostrada y luego lo confronta con el número de pedidos pendientes contado por RFC en la vista CDS analítica estándar SEPM_I_PurchaseOrder, antes y después de la actualización. Sin redondeo ni tolerancia: una diferencia de una unidad hace fallar la prueba, que nombra los dos números.

Launchpad de SAP FioriRFCHTTP

Prueba: Suite «agregado de una vista CDS confrontado con el contador que muestra un mosaico del launchpad»: 6/6 el 29/09/2026, reejecutada 6/6 el 05/10/2026: «mosaico 19, vista CDS 19 antes y 19 después», respuesta de la actualización 28,5 ms después de la solicitud.

A4H, release 754Captura real
Launchpad de SAP Fiori de A4H: el mosaico Approve Purchase Orders muestra 19
Launchpad de SAP Fiori servido por A4H (SAPUI5 1.71.47): el mosaico «Approve Purchase Orders» muestra 19, el número que la vista CDS cuenta por RFC.A4H, release 754 · Captura del 5 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
Ver el extracto de la suite
tests/robot/cross/cds_tuile_flp_approbation_a4h.robot
2. Le compteur affiché égale l'agrégat de la vue CDS analytique standard (assertion reine)
    # …
    ${annotations}=    La Vue CDS Devrait Etre Analytique
    ${avant}=    Compter Les Commandes En Attente Par La Vue CDS
    ${tuile}=    Lire Le Compteur Frais De La Tuile D Approbation
    ${apres}=    Compter Les Commandes En Attente Par La Vue CDS
    La Mesure Devrait Etre Stable    ${avant}    ${apres}    ${tuile}
    Le Compteur De La Tuile Devrait Egaler    ${tuile}[number]    ${apres}
    ...    ${INTENT_TUILE_APPROBATION} contre ${VUE_CDS_ANALYTIQUE} au statut ${STATUT_EN_ATTENTE}
resources/page_objects/tuile_cds_approbation.resource
Lire Le Compteur Frais De La Tuile
    # …
    [Arguments]    ${intent}    ${budget}=${BUDGET_COMPTEUR_TUILE}
    ${tuile}=    Refresh Flp Tile Counter    ${intent}    timeout=${budget}
    Should Be Equal    ${tuile}[body_check]    matched
    ...    msg=La réponse du rafraîchissement de ${intent} n'est pas reliée à la valeur lue (${tuile}[body_check]) : rien n'établit que le compteur ${tuile}[value] vient de cette réponse.
    RETURN    ${tuile}
# …
Compter Les Commandes Par La Vue CDS
    # …
    [Arguments]    ${statut}
    ${lignes}=    Read Business Records    ${VUE_SQL_ANALYTIQUE}    ${COLONNE_MANDANT},${COLONNE_COMMANDE}
    ...    filter=${COLONNE_STATUT_GLOBAL} EQ '${statut}'    alias=${WF_RFC_ALIAS}
    ${nombre}=    Les Lignes Devraient Etre Des Commandes Du Mandant Servi    ${lignes}    ${VUE_SQL_ANALYTIQUE}
    RETURN    ${nombre}
SAP GUI + RFC

El rol de un Business Partner, añadido en pantalla y comprobado en la base de datos

El rol se añade en la transacción BP por su clave técnica (nunca por su etiqueta traducida) y luego la verdad se lee por RFC en la tabla BUT100 sobre la clave exacta, documento de modificación incluido. A continuación, el rol se retira por la pantalla y su desaparición se comprueba sobre la misma clave. El modo de modificación de la pantalla se comprueba por el hecho de que un campo sea modificable (Element Should Be Changeable), no por un título traducido.

SAP GUI (BP)RFC

Prueba: Suite «rol de negocio de un Business Partner asignado por la pantalla y luego retirado»: 7/7 en A4H el 28/09/2026, escritura bajo autorización explícita.

tests/robot/cross/bp_role_partenaire_commercial_a4h.robot
1. Attribuer puis retirer le rôle Prospect par l'écran : la liaison apparaît puis disparaît
    # …
    Ouvrir Le Partenaire    ${CAMPAIGN_PARTNER}
    Passer Le Partenaire En Modification
    Choisir Le Role Par Sa Cle    ${ROLE_PROSPECT}
    La Combo Des Roles Devrait Porter    ${ROLE_PROSPECT}
    ${ajout}=    Sauvegarder Le Partenaire
    Le Message Devrait Etre    ${ajout}    ${MSG_SAVED}
    La Liaison De Role Devrait Etre Ouverte    ${CAMPAIGN_PARTNER}    ${ROLE_PROSPECT}
    ${document_ajout}=    Un Document Devrait Journaliser L Ajout Du Role
    ...    ${CAMPAIGN_PARTNER}    ${ROLE_PROSPECT}    ${depart}
    Retirer Le Role Par L Ecran    ${ROLE_PROSPECT}
    ${retrait}=    Sauvegarder Le Partenaire
    Le Message Devrait Etre    ${retrait}    ${MSG_SAVED}
    Aucune Liaison De Role Ne Devrait Exister    ${CAMPAIGN_PARTNER}    ${ROLE_PROSPECT}
resources/page_objects/bp_business_partner.resource
Lire La Liaison De Role
    # …
    [Arguments]    ${numero}    ${role}
    ${lignes}=    Read Business Records    ${BP_ROLE_LINK_TABLE}    ${BP_ROLE_LINK_FIELDS}
    ...    filter=PARTNER EQ '${numero}' AND RLTYP EQ '${role}'    alias=${BP_RFC_ALIAS}
    RETURN    ${lignes}
SAP GUI + RFC

Un job planificado en pantalla, esperado y leído por RFC

Un job con un nombre único se define y se guarda en SM36 (campos designados por su etiqueta). Su ejecución se encuentra por RFC en el registro de jobs, se espera hasta el final sin ninguna pausa fija y después su spool se lee de dos formas independientes, por el paso del job y por el número de spool. El contenido que muestra SP01 corrobora la lectura RFC.

SAP GUI (SM36, SP01)RFC (XBP)

Prueba: Suite «job de fondo planificado por SM36, esperado, con su spool leído por dos vías»: 11/11 en A4H el 01/10/2026.

tests/robot/cross/job_arriere_plan_spool_a4h.robot
1. Job planifié par SM36, attendu par le journal, son spool lu par RFC (assertion reine)
    # …
    ${nom}=    Nom De Job Unique Du Run    S1
    ${constat}=    Planifier Un Job ABAP Par SM36    ${nom}    ${PROGRAM_WITH_SPOOL}    demarrage=immediat
    Le Message De Sauvegarde Devrait Nommer Le Job    ${constat}[message]    ${nom}
    Les Gestes De Planification Devraient Viser Les Champs Releves    ${constat}    ${nom}
    ...    ${PROGRAM_WITH_SPOOL}    immediat
    ${run}=    Retrouver Le Run Du Job    ${nom}
    ${ok}=    Evaluate    bool($run['jobcount']) and $run['scheduled_by'] == $SAP_USER
    Consigner Le Constat    job.run_by_unique_name    ${ok}
    ...    Get Background Job Run rend le run unique du nom, JOBCOUNT, propriétaire et mandant
    ${attente}=    Attendre La Fin Du Job    ${nom}    ${run}[jobcount]
    ${ok}=    Evaluate    $attente['state'] == 'done'
    Consigner Le Constat    wait.done    ${ok}
    ...    Wait For Background Job jobcount= rend done, statut F relu
    ${pas}=    Le Pas Du Job Devrait Porter Un Spool    ${nom}    ${run}    ${PROGRAM_WITH_SPOOL}
    ${par_pas}=    Read Job Spool    ${nom}    ${run}[jobcount]
    ${par_numero}=    Read Spool Request    ${pas}[spool_id]
resources/page_objects/background_job_spool.resource
Ouvrir La Definition D Un Job
    # …
    [Arguments]    ${nom}
    Go To Transaction    ${SM36_TCODE}
    L Ecran Devrait Etre    ${SM36_PROGRAM}    ${SM36_INITIAL_SCREEN}
    ${id_nom}=    Fill Field By Label    ${SM36_LABEL_JOB_NAME}    ${nom}
RFC + SAP GUI

Un IDoc de salida juzgado por su código, y su IDoc de entrada encontrado

El IDoc se crea por RFC, se envía y luego se espera hasta el estado 03, juzgado por su código y nunca por un texto. El IDoc de entrada que produce se encuentra por el TID tRFC (nunca por la marca de tiempo) y se espera hasta el estado 53. El monitor WE02, leído en pantalla, debe mostrar exactamente los estados que ha leído el canal RFC.

RFCSAP GUI (WE02)

Prueba: Suite «IDoc de salida ALE creado por RFC, enviado y juzgado por código, IDoc de entrada vinculado por el TID»: 12/12 en A4H el 01/10/2026, escritura bajo autorización explícita.

tests/robot/cross/idoc_sortant_ale_a4h.robot
1. Un IDoc sortant émis atteint le statut 03, jugé par son code, et son entrant n'est pas oublié
    # …
    Dispatch Idoc By Number    ${docnum}
    ${sortant}=    Wait For Idoc Status    ${docnum}    expected=success    timeout=${IDOC_WAIT}
    Should Be Equal    ${sortant}[status]    ${STATUS_OUTBOUND_PASSED_TO_PORT}
    Should Be Equal    ${sortant}[category]    success
    Idoc History Should Be    ${sortant}[history]    ${OUTBOUND_HISTORY}
    Should Not Be Empty    ${sortant}[history][-1][TID]
# …
2. L'entrant lié arrive à 53 et la valeur émise se retrouve dans la table métier
    # …
    ${sortant}=    Dispatch New Flight Customer Change    ${TEST_CUSTOMER}    ${email}
    ${tid}=    Set Variable    ${sortant}[history][-1][TID]
    Should Not Be Empty    ${tid}
    ${lien}=    Get Idoc Counterpart    ${sortant}[docnum]    timeout=${COUNTERPART_WAIT}
    Track Run Idoc    ${lien}[counterpart]
    Should Not Be Equal    ${lien}[counterpart]    ${sortant}[docnum]
    Should Be Equal    ${lien}[counterpart_direction]    ${DIRECTION_INBOUND}
    ${entrant}=    Wait For Idoc Status    ${lien}[counterpart]    expected=${STATUS_INBOUND_POSTED}
    ...    timeout=${IDOC_WAIT}
    Should Be Equal    ${entrant}[status]    ${STATUS_INBOUND_POSTED}
    Should Be Equal    ${entrant}[category]    success
    Idoc History Should Be    ${entrant}[history]    ${INBOUND_HISTORY}
    Should Be Equal    ${entrant}[history][0][TID]    ${tid}
# …
4. WE02 affiche, pour le sortant et pour l'entrant, les statuts que lit le RFC
    # …
    Open Idoc In Monitor    ${sortant}
    ${codes_sortant}=    Read Idoc Status Nodes
    Should Be Equal    ${codes_sortant}[0]    ${chaine}[outbound][status]
    Should Be Equal    ${codes_sortant}[0]    ${STATUS_OUTBOUND_PASSED_TO_PORT}
SAP GUI + RFC

Dónde existe realmente el rechazo de autorización

Una cuenta de prueba con el rol de visualización, creada por RFC (lista blanca de prefijos, marca obligatoria, nunca el mandante 000), intenta abrir la entrada de pedidos de venta EPM. El inicio se rechaza: el mensaje se juzga por su identidad (S#/E/077) y nunca por su texto, y el núcleo confirma la ausencia de la autorización de transacción con una comprobación para un usuario con nombre. Testigo positivo: SE16 sigue autorizada y su recuento de filas iguala el de RFC; contraprueba: T000 se rechaza. Hallazgo registrado como advertencia: en esta aplicación de demostración, un rol de «solo inicio» modifica la nota de un pedido, porque no existe ningún control al guardar. La prueba se pondrá en rojo el día en que aparezca un control.

SAP GUI (SEPM_SO)RFC (roles, núcleo)

Prueba: Suite «dónde existe realmente el rechazo de autorización en un pedido de venta EPM»: 11/11 en ABAP Platform 2023 (release 758) el 07/10/2026, 9/9 en modo de conformidad (hallazgos excluidos), escritura bajo autorización explícita.

ABAP Platform 2023, release 758Captura real
SAP GUI en ABAP Platform 2023: «You are not authorized to use transaction SEPM_SO» en la barra de estado, para un usuario de prueba con el rol de visualización
Se rechaza el inicio de SEPM_SO al usuario de prueba restringido: la barra de estado muestra el error y la prueba juzga su identidad, no su texto.ABAP Platform 2023, release 758 · Captura del 7 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
HTTP + RFC + SAP GUI

Un error provocado, una entrada en el registro, encontrada de nuevo en pantalla

Una llamada OData a un servicio inventado, con un nombre único por ejecución y probado ausente del registro y de los catálogos, se rechaza con 403 (/IWFND/MED/170). La suite lee por RFC el registro de errores de la Gateway y prueba una entrada nueva, ligada a la respuesta recibida por el identificador de transacción y servida en el mandante correcto, y luego la encuentra en pantalla. El registro agrupa los errores idénticos: la misma llamada repetida aumenta el contador de la línea existente. Contar las entradas antes y después no probaría nada, de ahí la prueba por URI y transacción.

HTTP (OData)RFCSAP GUI (registro de errores)

Prueba: Suite «supervisión de la Gateway FES: un servicio registrado, servido, y un error con nombre en el registro»: 7/7 en A4H (release 754) el 07/10/2026. Las entradas de registro que crea caducan a los 14 días.

A4H, release 754Captura real
Registro de errores de la Gateway en A4H: una sola línea /IWFND/MED170 con contador 2 y su contexto de error
Registro de errores de la Gateway: la misma llamada repetida sigue siendo una sola línea, con contador 2 y su contexto de error.A4H, release 754 · Captura del 7 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
Canal 1 · SapEccLibrary · 195 keywords

SAP GUI para Windows: leer, actuar, demostrar el destino

SapEccLibrary pilota SAP GUI para Windows mediante la API SAP GUI Scripting, en las pantallas de los sistemas SAP ECC y SAP S/4HANA®. Los identificadores técnicos de las pantallas viven en una capa de keywords de negocio: las pruebas hablan el lenguaje del negocio.

Cuadrículas ALV

Leer una cuadrícula ALV entera, y demostrarlo

Una cuadrícula ALV renderiza sus filas no cargadas como celdas vacías en lugar de lanzar un error: una lectura hueca tiene el número correcto de filas y supera los controles ingenuos. Read Full Grid desplaza la cuadrícula para materializar cada fila, y Count Blank Grid Rows rechaza una lectura hueca. Las columnas se leen por su identificador técnico, independiente del idioma.

Prueba: Suite «smoke test de sistema de los mandantes T000 por SE16»: 1/1 en A4H el 21/09/2026. Captura de la misma lectura sobre SCARR el 05/10/2026.

A4H, release 754Captura real
SAP GUI: cuadrícula ALV de la tabla SCARR en el Data Browser SE16, 18 filas
Cuadrícula ALV de SE16 sobre la tabla SCARR, leída entera por SapEccLibrary: 18 filas, ninguna fila vacía.A4H, release 754 · Captura del 5 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
tests/robot/ui/ecc/smoke_test_t000_se16.robot
La table des mandants répond avec au moins les mandants standard
    # …
    Display Table Contents    T000
    ${rows}=    Read Full Displayed Grid
    ${row_count}=    Get Length    ${rows}
    Should Be True    ${row_count} >= ${MIN_EXPECTED_CLIENTS}
    ...    msg=T000 should list at least ${MIN_EXPECTED_CLIENTS} clients (000 and 001), got ${row_count}
    ${blank_rows}=    Count Blank Grid Rows    ${rows}
    Should Be Equal As Integers    ${blank_rows}    0
    ...    msg=T000 read is incomplete: ${blank_rows} fully blank row(s) in a grid announcing ${row_count} row(s)
    FOR    ${row}    IN    @{rows}
        Should Not Be Empty    ${row}[MANDT]
        ...    msg=A T000 row is missing its MANDT value: ${row}
    END
Percepción

Ver la pantalla como un agente de IA: captura anotada y mapa numerado

Para un agente de IA, igual que para una persona que depura, SapEccLibrary hace legible la pantalla: Get Annotated Screenshot numera cada objetivo accionable en la imagen y Get Screen Map da su lista con la etiqueta legible, el identificador y el valor. El agente lee un número; la biblioteca actúa sobre un identificador verificado. Estas referencias sirven para el pilotaje interactivo, nunca en una suite entregada.

Prueba: Suite de captura de esta página: 4/4 en A4H el 05/10/2026.

A4H, release 754Captura real
SAP GUI: pantalla de selección SE16 de SNWD_PD, cada campo enmarcado y numerado
Captura anotada de la pantalla de selección de SE16 de la tabla SNWD_PD: 86 objetivos numerados, tomada por Get Annotated Screenshot.A4H, release 754 · Captura del 5 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
comms/captures-site/capture_site_gui.robot
Ecran De Selection SE16 Annote
    # …
    ${shot}=    Get Annotated Screenshot
    Ecrire Image    ${shot}[image]    gui-se16-annotated
    ${carte}=    Get Screen Map
    Create File    ${OUTPUT DIR}/gui-se16-annotated-legend.txt    ${carte}
Controles de SAP GUI

Table controls, árboles, listas desplegables: por título, por texto, por clave

Un table control de dynpro se lee por título de columna (Read Table Control), con sus casillas de verificación devueltas como indicador ABAP; un árbol SAP se lee nodo a nodo (Read Tree Nodes) y se selecciona por su texto; una lista desplegable se maneja por su clave técnica (Select Combo Box Entry By Key), y por tanto con independencia del idioma.

Prueba: Campaña SE11 cruzada con el diccionario: 7/7 el 05/09/2026. Registro de capacidades de SAP GUI: 21/21 en la release 754 el 07/09/2026, 10/10 en la release 758 el 08/09/2026.

A4H, release 754Captura real
SAP GUI: pestaña Fields de la transacción SE11 sobre la tabla SNWD_PD, table control de 26 campos
Table control de SE11, pestaña «Fields» de la tabla SNWD_PD: 26 campos leídos por título de columna.A4H, release 754 · Captura del 5 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
resources/page_objects/se11_dictionary_display.resource
Read Se11 Table Fields
    # …
    Click Element    ${SE11_TAB_FIELDS}
    Wait Until Busy Done
    ${rows}=    Read Table Control    ${SE11_TABLE_FIELDS_TC}
    RETURN    ${rows}
resources/page_objects/sapgui_capability_probes.resource
Lire Les Noeuds Du Menu Utilisateur
    # …
    ${noeuds}=    Read Tree Nodes    ${SM_USER_MENU_TREE}
    RETURN    ${noeuds}
# …
Selectionner Le Dossier Plain ABAP Par Texte
    # …
    ${cle}=    Select Tree Node By Text    ${SM_USER_MENU_TREE}    ${SM_TREE_PLAIN_ABAP_TEXT}    exact=True
    RETURN    ${cle}
# …
Choisir L Evenement Par Cle
    # …
    Select Combo Box Entry By Key    ${SM37_EVENT_COMBO}    ${cle}
Prueba del destino

Demostrar con qué sistema se habla, antes de cualquier escritura

Dos sistemas pueden anunciar el mismo identificador y el mismo nombre de host: es el caso de los dos contenedores del laboratorio. Get System Identity lee «System: Status», el kernel y los componentes instalados, y System Identity Should Be rechaza el destino si la release, el kernel o el mandante no son los esperados. Leído el 5 de octubre de 2026: A4H, mandante 001, release 754, kernel 777.

Prueba: Salvaguarda de destino de las campañas de escritura (Business Partner, jobs, IDoc), vista en acción rechazando el otro contenedor del laboratorio.

resources/page_objects/bp_business_partner.resource
La Cible SAP GUI Devrait Etre
    # …
    [Arguments]    ${release}    ${kernel}    ${client}
    ${identite}=    Get System Identity
    System Identity Should Be    identity=${identite}    basis_release=${release}
    ...    kernel_release=${kernel}    client=${client}
    RETURN    ${identite}
Canal 2 · SapFioriLibrary · 98 keywords

SAP Fiori, SAPUI5 y SAP GUI for HTML: controles, no identificadores DOM

SapFioriLibrary se apoya en la biblioteca Browser (Playwright). Designa los controles UI5 por su tipo, sus propiedades o su ruta de enlace, nunca por los identificadores DOM generados, y espera el reposo real de la página (Wait For Ui5 Idle) en lugar de una pausa fija. Cinco motores de resolución cubren también el WebGUI, los UI5 Web Components y las zonas no SAP de una página híbrida.

Launchpad

El launchpad de SAP Fiori: abrir por intent, leer los mosaicos

Una aplicación se abre por su intent semántico (Open Fiori App), la vía estable que sobrevive al tema, al idioma y a las reorganizaciones del catálogo. El contador de un mosaico dinámico se espera hasta que está realmente cargado (Wait For Flp Tile Counter) y luego se lee como un número: el mosaico se declara cargado mientras todavía muestra un valor de espera.

Prueba: Campañas del launchpad servido por un servidor ABAP: 20/20 en SAPUI5 1.71 y 22/22 en SAPUI5 1.120, el 25/08/2026. Captura del mosaico: véase la prueba híbrida anterior.

resources/page_objects/abap_flp.resource
Ouvrir L Application Par Intent
    # …
    [Arguments]    ${intent}
    Open Fiori App    ${intent}
    Attendre Le Fragment    ${intent}
    Wait For Ui5 Idle    settle=${ABAP_FLP_SETTLE}    timeout=${ABAP_FLP_IDLE_TIMEOUT}
    Wait Until Keyword Succeeds    60s    2s    L Application Ouverte Est    ${intent}
resources/page_objects/tuile_cds_approbation.resource
Lire Le Compteur Charge De La Tuile
    # …
    [Arguments]    ${intent}    ${budget}=${BUDGET_COMPTEUR_TUILE}
    ${tuile}=    Wait For Flp Tile Counter    ${intent}    timeout=${budget}
    RETURN    ${tuile}
RAP

La vista previa de Fiori Elements de un servicio RAP, sin aplicación desplegada

El servidor ABAP genera sobre la marcha la interfaz Fiori Elements de todo servicio RAP publicado. Build Fe Preview Path construye su dirección, uno de cuyos parámetros está ofuscado, y el navegador se autentica mediante una cabecera HTTP. Las fechas se introducen en el formato que calcula el tipo del enlace (Fill Ui5 Date) y después se vuelven a leer en el modelo.

Prueba: Suite «viaje RAP creado por Fiori Elements, de borrador a activo, rechazo y abandono»: 7/7 en la release 758 el 24/09/2026.

ABAP Platform 2023, release 758Captura real
Vista previa de SAP Fiori Elements del servicio RAP de viajes en ABAP Platform 2023, 4136 viajes
Vista previa de Fiori Elements del servicio RAP de referencia de los viajes: 4136 viajes listados.ABAP Platform 2023, release 758 · Captura del 5 de octubre de 2026Pantalla de una aplicación SAPUI5: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
resources/page_objects/rap_travel_fe_preview.resource
Ouvrir Le Navigateur Des Voyages
    # …
    New Browser    ${BROWSER}    headless=${RAP_TRAVEL_HEADLESS}
    New Context    ignoreHTTPSErrors=${True}    locale=${RAP_TRAVEL_LOCALE}
    ...    viewport=${RAP_TRAVEL_VIEWPORT}
    ...    httpCredentials={'username': '$RAP_TRAVEL_USER', 'password': '$RAP_TRAVEL_UI_PASSWORD'}
    Set Browser Timeout    ${RAP_TRAVEL_TIMEOUT}
    New Page    about:blank
    ${chemin}=    Build Fe Preview Path    ${RAP_TRAVEL_BINDING}    ${RAP_TRAVEL_SERVICE}
    ...    ${RAP_TRAVEL_ROOT_SET}    client=${RAP_TRAVEL_CLIENT}
    Set Suite Variable    ${RAP_TRAVEL_PREVIEW_URL}    ${RAP_TRAVEL_UI_URL}${chemin}
SAP GUI for HTML

El WebGUI: la cuadrícula leída por los identificadores de sus celdas

Una cuadrícula del WebGUI solo envía una página de filas, renumeradas a partir de 1: una lectura truncada está limpia y es indistinguible de una lectura completa. Read Webgui Grid lee cada celda por su SID (el mismo espacio de identificadores que el scripting de escritorio) y el total que publica la cuadrícula; la misma salvaguarda de completitud que en los demás canales rechaza una lectura amputada.

Prueba: Suite «extracción de una cuadrícula WebGUI a cinco formatos de archivo»: 8/8 en A4H el 15/09/2026.

A4H, release 754Captura real
SAP GUI for HTML: Data Browser SE16 sobre la tabla SCARR, 18 filas
SE16 en SAP GUI for HTML sobre la tabla SCARR: 18 filas leídas de 18 declaradas.A4H, release 754 · Captura del 5 de octubre de 2026Pantalla de un software de SAP: el logotipo de SAP y las marcas de SAP son propiedad de SAP SE.
resources/fiori_keywords.resource
Extract Displayed WebGui Grid
    # …
    [Arguments]    ${sid}=${EMPTY}    ${key}=${EMPTY}    ${source}=${EMPTY}
    ${grille}=    Read Webgui Grid    ${sid}
    ${nom}=    Set Variable If    '${source}' == '${EMPTY}'
    ...    grille WebGUI ${grille}[container]    ${source}
    ${extrait}=    Build Table Extract    ${grille}[rows]    columns=${grille}[columns]
    ...    headers=${grille}[headers]    declared_rows=${grille}[declared_rows]
    ...    source=${nom}    key=${key}
tests/robot/ui/fiori/extraction_grille_webgui.robot
    ${partiel}=    Extract Displayed WebGui Grid    key=${KEY_COLUMN}
    ...    source=${EXTRACTED_TABLE} plafonnée à ${OVERFLOW_HITS}
    Should Be True    ${partiel}[declared_rows] > ${partiel}[row_count]
    ...    msg=Le cas dangereux n'a PAS été provoqué : la grille a rendu ses ${partiel}[row_count] lignes en entier, donc cette contre-épreuve ne prouve rien. Monter ${OVERFLOW_HITS}.
    Should Be Equal As Integers    ${partiel}[blank_rows]    ${0}
    ...    msg=Ces lignes devraient être PROPRES : c'est ce qui rend le cas indétectable autrement que par le total déclaré.
    Should Be Equal    ${partiel}[complete]    ${False}
    ${erreur}=    Run Keyword And Expect Error    RELEVÉ REFUSÉ*
    ...    Table Extract Should Be Complete    ${partiel}
SAP BTP · SAP Build Work Zone

SAP BTP: un launchpad en la nube tras su proveedor de identidad

Un sitio SAP Build Work Zone en SAP BTP, protegido por un tenant de SAP Cloud Identity Services. SapFioriLibrary se conecta a él a través del proveedor de identidad, percibe un shell cuya barra está construida con UI5 Web Components y entra en la aplicación abierta en su iframe; SapApiLibrary abre el canal API del mismo sitio en OAuth2.

Alcance del frame

El shell y la aplicación, dos mundos estancos

Desde el shell, los controles de la aplicación son invisibles, y viceversa. La prueba lo demuestra con un testigo: el campo de búsqueda del shell, resuelto una vez en el shell y cero veces desde la aplicación. Sin esta estanqueidad, una prueba haría clic en el lugar equivocado y seguiría en verde.

Prueba: Misma campaña, escenario del alcance del frame: 9/9 el 24/08/2026.

tests/robot/ui/fiori/exploration_launchpad_workzone.robot
La portee de frame est etanche entre le shell et l application
    # …
    ${apps}=    Inventorier Les Applications Du Catalogue
    Ouvrir L Application Par Intent    ${apps}[0][intent]
    Entrer Dans L Application
    ${dans_l_app}=    Compter Le Champ De Recherche Du Shell
    ${composition_app}=    Lire La Composition De La Portee Courante
    Sortir De L Application
    ${sur_le_shell}=    Compter Le Champ De Recherche Du Shell
    ${composition_shell}=    Lire La Composition De La Portee Courante
    Should Be Equal As Integers    ${dans_l_app}    0
    ...    msg=Le champ de recherche du shell est résolu depuis l'application : la portée fuit.
    Should Be Equal As Integers    ${sur_le_shell}    1
    ...    msg=Le champ de recherche du shell n'est plus résolu après le retour au shell.
Canal API

El canal API del sitio, en OAuth2 mediante una clave de servicio

Una clave de servicio de la subcuenta abre el canal API en OAuth2 (client credentials) con Open Api Session. El reconocimiento clasifica cada rechazo por su estructura (Classify Http Response: ruta desconocida para el router de la plataforma, ruta ausente de una aplicación, autorización denegada, página de inicio de sesión servida con un 200). Estableció, en lugar de suponerlo, que una clave de servicio abre el backend de un servicio y no la interfaz de administración del sitio.

Prueba: Campaña «reconocimiento del canal API de un destino BTP»: 9/9 el 26/08/2026.

Capturas y campañas de agosto de 2026: el 5 de octubre de 2026, la cuenta de prueba de SAP BTP del laboratorio ya no respondía («The URL does not reference a valid account»), por lo que no se reejecutaron para esta página.

Canal 3 · SapApiLibrary · 149 keywords

OData v2/v4 y RFC/BAPI: probar sin pantalla

SapApiLibrary habla HTTP con la biblioteca estándar de Python (protocolo CSRF de SAP incluido) y RFC mediante pyrfc, que es opcional. Es el canal que prepara los datos, verifica un resultado sin pasar por la pantalla y lee la configuración de un sistema ABAP.

OData

El contrato de un servicio OData, sus etiquetas, sus lotes

El $metadata de un servicio se lee con sus etiquetas legibles (Get Odata Metadata, Find Odata Property By Label): el contrato se verifica en la fuente. Varias lecturas salen en un solo viaje de ida y vuelta $batch (Post Odata Batch), con cada operación juzgada por separado. Las mismas keywords valen para un Gateway OData v2, un servicio CAP en OData v4 y el entorno de pruebas de SAP Business Accelerator Hub.

Prueba: Suite del canal API: 8/8 en el Gateway de A4H y 4/4 en OData v4 el 19/08/2026, 5/5 en el entorno de pruebas de SAP Business Accelerator Hub el 23/08/2026.

resources/api_keywords.resource
Business Service Should Expose Entity Set
    # …
    [Arguments]    ${service}    ${entity_set}    ${alias}=${API_ALIAS}
    ${meta}=    Get Odata Metadata    ${service}    alias=${alias}
    Dictionary Should Contain Key    ${meta}[entity_sets]    ${entity_set}
    ...    msg=Le service ${service} ne publie pas l'ensemble d'entités ${entity_set}.
    RETURN    ${meta}[entity_sets][${entity_set}]
tests/robot/api/canal_api_odata.robot
Plusieurs Lectures Tiennent En Un Seul Aller Retour
    # …
    ${reponses}=    Read Business Entities In One Roundtrip    ${EPM_SHOP_SERVICE}
    ...    Products?$top=2    Products/$count    alias=a4h
    Length Should Be    ${reponses}    2
    FOR    ${reponse}    IN    @{reponses}
        Should Be True    ${reponse}[status] < 300    msg=Opération du lot en erreur : ${reponse}
    END
Escritura reversible

Crear, modificar, releer, eliminar: la desaparición demostrada en la entidad

La fábrica de datos de prueba crea una entidad, la modifica, la vuelve a leer y después la retira. La limpieza se demuestra en la propia entidad y no en un recuento que vuelve a su valor inicial: en un servicio con borradores, un borrador no entra en el $count, así que un recuento sin cambios no demuestra nada.

Prueba: Misma suite, vía OData v4: 4/4 el 19/08/2026.

tests/robot/api/canal_api_odata.robot
Les Donnees De Test Creees Sont Retirees A La Fin
    # …
    ${entite}=    Create Test Entity    ${TRAVEL_ENTITIES}    ${{ {'Description': 'Recette du canal API'} }}
    ...    alias=cap    track=${False}
    ${chemin}=    Build Draft Entity Path    ${TRAVEL_ENTITIES}    ${TRAVEL_KEY_FIELD}
    ...    ${entite}[${TRAVEL_KEY_FIELD}]
    Track Created Entity    ${chemin}    alias=cap
    Patch Odata    ${chemin}    ${{ {'Description': 'Recette du canal API, modifiee'} }}    alias=cap
    ${relue}=    Get Odata    ${chemin}    alias=cap
    Should Be Equal    ${relue}[Description]    Recette du canal API, modifiee
    ...    msg=La modification n'est pas relue : l'écriture n'est pas confirmée.
    Remove Created Test Data    alias=cap
    ${apres}=    Run Keyword And Ignore Error    Get Odata    ${chemin}    alias=cap
    Should Be Equal    ${apres}[0]    FAIL
    ...    msg=L'entité de test répond encore après le nettoyage : donnée laissée derrière.
RFC y BAPI

Tablas, BAPI juzgadas por tipo, rechazos nombrados por código

Read Rfc Table lee una tabla proyectada, filtrada y acotada. Call Bapi juzga una BAPI por el tipo de sus mensajes (E, A o X la hacen fallar), nunca por su texto traducido, y un rechazo esperado se comprueba por su código técnico (Rfc Should Fail With Code). Los jobs de fondo se esperan mediante un sondeo acotado del registro de jobs (Wait For Background Job).

Prueba: Suite del canal RFC y BAPI: 16/16 en la release 754 el 27/08/2026, 10/10 en la release 758 el 28/08/2026.

resources/rfc_keywords.resource
Read User Details
    # …
    [Arguments]    ${user}    ${alias}=${RFC_ALIAS}
    ${detail}=    Call Bapi    ${BAPI_USER_DETAIL}    alias=${alias}    USERNAME=${user}
    RETURN    ${detail}
tests/robot/api/canal_rfc_a4h.robot
Les Refus Se Classent Par Code Jamais Par Texte
    # …
    Reading A Missing Table Should Be Refused With Code    ${CODE_TABLE_ABSENTE}
    Reading A Missing Field Should Be Refused With Code    ${CODE_TABLE_SANS_DONNEES}
    Calling A Missing Function Module Should Be Refused With Code    ${CODE_MODULE_ABSENT}
    Calling With An Unknown Parameter Should Be Refused With Code    ${CODE_PARAMETRE_INVALIDE}
resources/rfc_keywords.resource
Read Business Records
    # …
    [Arguments]    ${table}    ${fields}    ${filter}=${EMPTY}    ${limit}=0
    ...    ${alias}=${RFC_ALIAS}
    ${lignes}=    Read Rfc Table    ${table}    ${fields}    alias=${alias}
    ...    options=${filter}    rowcount=${limit}
    RETURN    ${lignes}
Seguridad ABAP

La configuración de seguridad de un sistema ABAP, leída por RFC

Los parámetros de perfil se juzgan por su código de retorno antes que por su valor (Read Profile Parameters), porque un parámetro desconocido devuelve una cadena vacía indistinguible de un parámetro vacío. Profile Parameters Should Be Defined protege el inicio de una campaña, y Security Posture Should Not Have Drifted compara la postura con una referencia guardada en el repositorio. También se lee la superficie de ataque: cuentas realmente utilizables, servicios web servidos, cobertura del registro de auditoría. Solo lectura de principio a fin.

Prueba: Campañas de configuración de seguridad: 15/15 en la release 754 y 16/16 en la release 758 el 29/08/2026; superficie de ataque: 12/12 en la release 758 el 14/09/2026.

Alrededor de las bibliotecas

Grabadores, agentes de IA y documentación de las keywords

Las bibliotecas son autosuficientes. A su alrededor, el taller SAPFX añade lo necesario para escribir pruebas más rápido y mantenerlas. Sus diez herramientas, opcionales y bajo presupuesto, se presentan una por una en la página Herramientas del taller.

Agentes de IA y MCP

Agentes que exploran, escriben y reparan, bajo control

Cinco agentes (planificar, generar, reparar, verificar, documentar según el ISTQB) pilotan SAP a través del servidor MCP rf-mcp y los plugins de SAPFX, en Claude Code o GitHub Copilot. Aplican el método Spec-Test-Driven Development: la especificación se confronta con el sistema real, cada paso de una prueba se ejecuta antes de escribirse y la reparación nunca toca las aserciones. Los agentes y la capa MCP forman parte del taller SAPFX, no del paquete PyPI, que contiene las bibliotecas.

Prueba: El vídeo «Cómo pilotan SAP los agentes de IA» (8 min 20) los muestra en acción.

Documentación

La referencia de cada keyword, con sus argumentos

Cada keyword de las tres bibliotecas está documentada, con sus argumentos y sus ejemplos, en páginas de referencia en inglés: SapEccLibrary, SapFioriLibrary y SapApiLibrary, en la versión 0.8.5.

Prueba: También publicadas en GitHub Pages, con el repositorio público de las bibliotecas.

Cómo se ha hecho esta página

Capturas reales, código real, límites declarados

Capturas reales

Las pantallas SAP las fotografió el propio SAPFX (keywords de captura de las bibliotecas y después la biblioteca Browser) en los sistemas del laboratorio, el 5 de octubre de 2026, y el 29 de agosto de 2026 para SAP BTP, sin retoque salvo el recorte (y el logotipo de SAP, enmascarado en las pruebas de la cartografía); cada pie de imagen lleva su fecha. Muestran datos de demostración suministrados por SAP, ningún dato de cliente. El logotipo de SAP y las marcas de SAP visibles en estas pantallas son propiedad de SAP SE.

Código real

Cada extracto está copiado, línea por línea, de una suite validada en vivo cuyo nombre, resultado y fecha figuran bajo el extracto; «# …» marca un corte. Un control automático, ejecutado antes de cada publicación, rechaza una keyword que no existe en la versión 0.8.5 y una línea ausente de su suite de origen.

Límites declarados

Estas pruebas se ejecutan en sistemas SAP de desarrollo en contenedores, nunca en un sistema de cliente, y no miden ninguna ganancia de productividad. Los nombres de las keywords de negocio (en francés en estas suites) pertenecen a la capa de resources del laboratorio: son ejemplos que hay que adaptar a cada instalación, no un vocabulario universal.

Su caso

¿Un recorrido SAP que automatizar, en dos o tres canales?

Descríbanos el flujo: le diremos lo que SAPFX cubre hoy y lo que habría que construir. Servicios bajo presupuesto.

  • Un intercambio técnico, no comercial
  • Sus datos permanecen en Francia
Guía de inicio

o directamente por correo electrónico: