El Equipo de QA También Necesita Ayuda de IA

La Pregunta

“El equipo de desarrollo está creando una implementación para crear y consumir un InvoicePaymentReconciliationAdviceV01 y responder con un InvoicePaymentReconciliationStatusV01. Soy el gerente de QA. ¿Pueden ayudarme a desarrollar un plan de pruebas? Necesito verificar cada tipo de problema de datos imaginable ya que algunos de los mensajes se originan en otros sistemas, y la respuesta apropiada DEBE cumplir con la especificación antes de enviarse o serán rechazados.”

No “escríbeme algunas pruebas unitarias.” No “verifica el camino feliz.” Cada tipo de problema de datos imaginable — porque los mensajes que llegan de partes externas pueden ser cualquier cosa. Y las respuestas salientes que fallan la validación del esquema son rechazadas silenciosamente por la red. Este es un problema real de QA, y necesita una respuesta real.


Paso 1 — El Servidor MCP Identifica Ambos Mensajes

La IA consulta el Servidor ISO 20022 MCP de Beneficial Strategies para ambas definiciones de mensajes. El servidor los resuelve inmediatamente:

Mensaje ID Área de Negocio Rol
InvoicePaymentReconciliationAdviceV01 tsmt.053.001.01 TSMT Pagador → Beneficiario: atribuye pagos a cuotas de facturas
InvoicePaymentReconciliationStatusV01 tsmt.054.001.01 TSMT Beneficiario → Pagador: confirma o disputa la conciliación

Luego el servidor recupera la jerarquía completa de componentes para ambos mensajes, incluyendo el bloque de construcción clave ReconciliationList1 y cada campo requerido/opcional con su tipo, multiplicidad y restricciones.


Paso 2 — Dos Preguntas de Aclaración

Antes de generar el plan de pruebas, la IA pregunta:

“1. ¿Deben los casos de prueba cubrir fallos a nivel XML (XML malformado, espacio de nombres incorrecto, violaciones de esquema) además de fallos de datos a nivel de negocio?”

“2. Para la respuesta InvoicePaymentReconciliationStatus saliente — ¿deben los casos de prueba verificar que referencia correctamente el mensaje de Aviso originador, o simplemente que es internamente válido?”

Respuestas: Sí a ambas. Los fallos a nivel XML importan absolutamente ya que los mensajes provienen de sistemas externos. Y la trazabilidad de la respuesta — que el Estado referencia correctamente el Aviso — es un requisito central de conformidad.


Paso 3 — El Plan de Pruebas Completo Se Genera Automáticamente

Referencia de Estructura del Mensaje

classDiagram
    direction LR
    class InvoicePaymentReconciliationAdviceV01{
        ReconciliationCount Max15NumericText
        ItemCount Max15NumericText
        ControlSum DecimalNumber
    }
    InvoicePaymentReconciliationAdviceV01 *-- "1..1" BusinessLetter1 : Header
    InvoicePaymentReconciliationAdviceV01 *-- "1..*" ReconciliationList1 : ReconciliationList

    class ReconciliationList1{
        Date ISODate
        ItemCount Max15NumericText
        ControlSum DecimalNumber
        PaymentDate ISODate
        PaymentAmount CurrencyAndAmount
    }
    ReconciliationList1 *-- "1..1" QualifiedPartyIdentification1 : Recipient
    ReconciliationList1 *-- "1..1" QualifiedPartyIdentification1 : Advisor
    ReconciliationList1 *-- "1..1" PaymentIdentification1 : PaymentReference
    ReconciliationList1 *-- "1..1" PaymentMeans1 : PaymentMeans
    ReconciliationList1 *-- "1..1" PaymentTerms6 : PaymentTerms
    ReconciliationList1 *-- "1..*" FinancialItem1 : Item

    class InvoicePaymentReconciliationStatusV01{
        ReconciliationCount Max15NumericText
        ItemCount Max15NumericText
        ControlSum DecimalNumber
    }
    InvoicePaymentReconciliationStatusV01 *-- "1..1" BusinessLetter1 : Header
    InvoicePaymentReconciliationStatusV01 *-- "1..*" ReconciliationList1 : ReconciliationList
  

Categoría 1 — Fallos de Estructura XML y Espacio de Nombres

Estos fallos ocurren antes de que se ejecute cualquier lógica de negocio. Cada mensaje entrante debe superar primero este filtro.

# Caso de Prueba Condición de Entrada Comportamiento Esperado
1.1 XML malformado Etiqueta de cierre faltante Excepción del analizador; mensaje rechazado antes del procesamiento
1.2 Espacio de nombres incorrecto xmlns="urn:iso:std:iso:20022:tech:xsd:tsin.008.001.01" (tipo de mensaje incorrecto) Fallo de validación de esquema; rechazar con error de discrepancia de espacio de nombres
1.3 Espacio de nombres faltante Sin atributo xmlns en <Document> Fallo de validación de esquema
1.4 Elemento raíz incorrecto <InvcAssgnmtNtfctn> en lugar de <InvcPmtRcncltnAdvc> Fallo de validación de esquema
1.5 Documento vacío Solo <Document/> Bloques de construcción requeridos faltantes; rechazar
1.6 Discrepancia de codificación Archivo UTF-16 declarado como UTF-8 Excepción del analizador
1.7 BOM presente Marca de orden de bytes antes de la declaración XML Verificar que el analizador maneja o rechaza correctamente
1.8 Elementos adicionales Elemento desconocido dentro de <Hdr> Fallo de validación de esquema (modo estricto)

Categoría 2 — Fallos de Encabezado (BusinessLetter1)

El bloque de construcción Hdr es requerido (1..1). Cada fallo de campo aquí debe producir un rechazo claro.

# Caso de Prueba Condición de Entrada Comportamiento Esperado
2.1 Encabezado completamente faltante Sin elemento <Hdr> Esquema: elemento requerido faltante
2.2 LetterIdentifier faltante Sin <LttrIdr> dentro del Encabezado Esquema: campo requerido ausente
2.3 Fecha faltante Sin <Dt> en el Encabezado Esquema: campo requerido ausente
2.4 Formato de fecha inválido <Dt>2026-13-45</Dt> Esquema: violación de patrón de fecha
2.5 Fecha como texto libre <Dt>March 17 2026</Dt> Esquema: discrepancia de tipo
2.6 Originador faltante Sin parte <Orgtr> Esquema: parte requerida ausente
2.7 Destinatario Principal faltante Sin parte <PmryRcpt> Esquema: parte requerida ausente
2.8 Parte sin Nombre ni ID <Pty></Pty> Esquema: elemento de parte vacío
2.9 BIC malformado <AnyBIC>NOT-A-BIC</AnyBIC> Esquema: violación de patrón BIC ([A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?)

Categoría 3 — Fallos de Lista de Conciliación (ReconciliationList1)

El bloque de construcción RcncltnList es requerido (1..*) — al menos uno debe estar presente.

# Caso de Prueba Condición de Entrada Comportamiento Esperado
3.1 Sin Lista de Conciliación <RcncltnList> completamente faltante Esquema: elemento requerido ausente
3.2 Fecha faltante Sin <Dt> en la lista Esquema: campo requerido ausente
3.3 Fecha futura <Dt>2099-01-01</Dt> Regla de negocio: la fecha no debe ser futura (si aplica)
3.4 Destinatario faltante Sin <Rcpt> Esquema: parte requerida ausente
3.5 Asesor faltante Sin <Advsr> Esquema: parte requerida ausente
3.6 Referencia de Pago faltante Sin <PmtRef> Esquema: elemento requerido ausente
3.7 Medios de Pago faltantes Sin <PmtMeans> Esquema: elemento requerido ausente
3.8 Fecha de Pago faltante Sin <PmtDt> Esquema: elemento requerido ausente
3.9 Fecha de Pago anterior a la fecha de factura El pago precede a la factura que referencia Regla de negocio: violación cronológica
3.10 Términos de Pago faltantes Sin <PmtTerms> Esquema: elemento requerido ausente
3.11 Monto de Pago faltante Sin <PmtAmt> Esquema: elemento requerido ausente
3.12 Monto de Pago cero <PmtAmt Ccy="USD">0.00</PmtAmt> Regla de negocio: pago de valor cero
3.13 Monto de Pago negativo <PmtAmt Ccy="USD">-100.00</PmtAmt> Esquema o regla de negocio: monto negativo
3.14 Atributo de moneda faltante <PmtAmt>4750.00</PmtAmt> Esquema: atributo requerido Ccy ausente
3.15 Código de moneda inválido <PmtAmt Ccy="XXX">4750.00</PmtAmt> Regla de negocio: moneda no ISO-4217
3.16 Sin elementos de ítem <ItmCnt>0</ItmCnt> sin <Itm> Esquema: violación de mínimo 1..*
3.17 Discrepancia en recuento de ítems <ItmCnt>3</ItmCnt> pero solo 1 <Itm> presente Regla de negocio: fallo de integridad de recuento
3.18 Discrepancia en suma de control <CtrlSum>999.99</CtrlSum> pero los ítems suman a un valor diferente Regla de negocio: fallo de integridad de suma de control
3.19 Suma de control correcta Los montos suman exactamente a la suma de control Aprobado

Categoría 4 — Fallos de Ítem Financiero (FinancialItem1)

Cada <Itm> dentro de la lista de conciliación representa una factura que se empareja con un pago.

# Caso de Prueba Condición de Entrada Comportamiento Esperado
4.1 Contexto de Ítem faltante Sin <ItmCntxt> Esquema: elemento requerido ausente
4.2 Indicador de Crédito/Débito faltante Sin <CdtDbtInd> Esquema: elemento requerido ausente
4.3 Indicador de Crédito/Débito inválido <CdtDbtInd>MAYBE</CdtDbtInd> Esquema: violación de enumeración (solo CRDT o DBIT)
4.4 Monto Total faltante Sin bloque <TtlAmt> Esquema: elemento requerido ausente
4.5 Monto de Impuesto excede el Monto Gravable Total Impuesto > monto antes de impuestos Regla de negocio: cálculo de impuesto sin sentido
4.6 Monto Total inconsistente TtlTaxblAmt + TaxAmt ≠ TtlAmt Regla de negocio: fallo aritmético de montos
4.7 Discrepancia de moneda dentro del ítem TtlTaxblAmt Ccy="USD" pero TaxAmt Ccy="EUR" Regla de negocio: monedas mixtas dentro de un solo ítem
4.8 Discrepancia de moneda con el pago La moneda del ítem difiere de la moneda de PaymentAmount Regla de negocio: discrepancia de moneda en toda la lista
4.9 Monto Vencido excede el Monto Total Se debe más de lo que se facturó en total Regla de negocio: fallo de lógica de montos
4.10 Referencia a factura desconocida ID de FinancialDocumentReference no está en el sistema Regla de negocio: referencia no resoluble
4.11 Referencia de ítem duplicada La misma factura referenciada dos veces en una lista Regla de negocio: ítem duplicado

Categoría 5 — Fallos de Integridad a Nivel de Sobre

Estos contrastan los bloques de construcción entre sí.

# Caso de Prueba Condición de Entrada Comportamiento Esperado
5.1 Discrepancia en recuento de ítems de nivel superior <ItmCnt>5</ItmCnt> pero el total de ítems en todas las listas ≠ 5 Regla de negocio: integridad de recuento de sobre
5.2 Discrepancia en suma de control de nivel superior <CtrlSum> no coincide con la suma de todas las sumas de control de listas Regla de negocio: integridad de suma de sobre
5.3 Discrepancia en recuento de conciliaciones <RcncltnCnt>2</RcncltnCnt> pero solo 1 lista presente Regla de negocio: integridad de recuento
5.4 Múltiples listas, una inválida Primera lista válida, segunda lista con campo requerido faltante Manejo de fallo parcial: ¿rechazar todo el mensaje o fallo a nivel de lista?
5.5 Identificadores de lista duplicados Dos elementos <RcncltnList> con el mismo <Idr> Regla de negocio: violación de unicidad

Categoría 6 — Conformidad de Respuesta Saliente (tsmt.054.001.01)

El InvoicePaymentReconciliationStatus debe ser válido según el esquema antes de la transmisión. Estas pruebas verifican que la implementación produce una respuesta conforme.

# Caso de Prueba Condición de Activación Verificar en Respuesta
6.1 Confirmación de ruta feliz Aviso válido recibido y aceptado Espacio de nombres de respuesta = urn:iso:std:iso:20022:tech:xsd:tsmt.054.001.01; pasa XSD
6.2 Respuesta referencia el original Aviso válido recibido RelatedDocument en el encabezado de respuesta referencia el LetterIdentifier del Aviso original
6.3 Ítem disputado Un monto de ítem no coincide con lo esperado ValidationStatusInformation presente con código de estado apropiado en el ítem disputado
6.4 Totalmente disputado Todos los ítems disputados Todos los ítems llevan estado de disputa; no aceptados silenciosamente
6.5 Recuento de ítems de respuesta preciso 3 ítems en el Aviso <ItmCnt> de respuesta = 3
6.6 Suma de control de respuesta precisa Los ítems suman X <CtrlSum> de respuesta coincide
6.7 Respuesta enviada a la parte correcta El Aviso tiene Asesor A y Destinatario B <PmryRcpt> de respuesta es Asesor A (el remitente original)
6.8 Respuesta en la misma moneda El Aviso usó USD Todos los montos de respuesta en USD
6.9 Respuesta con espacio de nombres incorrecto Error en el serializador NO debe producir tsin.008 ni ningún otro espacio de nombres
6.10 Validación de esquema de respuesta Cualquier respuesta generada Ejecutar contra tsmt.054.001.01.xsd antes de la transmisión; fallo = no enviar

Categoría 7 — Casos Extremos y Condiciones de Límite

# Caso de Prueba Condición de Entrada Comportamiento Esperado
7.1 Longitudes máximas de campo Todos los campos Max35Text exactamente en 35 caracteres Aceptar
7.2 Exceder longitud de campo Campo Max35Text con 36 caracteres Esquema: violación de maxLength
7.3 Cadena vacía en texto requerido <Id></Id> Esquema: violación de minLength (usualmente 1)
7.4 Texto solo con espacios <Id> </Id> Esquema o regla de negocio: valor en blanco
7.5 Unicode en nombre de parte <Nm>株式会社</Nm> Aceptar (ISO 20022 es UTF-8)
7.6 Caracteres XML especiales sin escapar <Nm>AT&T</Nm> Fallo del analizador; debe ser &amp;
7.7 Ítem único, lista única Mensaje válido mínimo Aceptar; ItemCount = 1, ControlSum = monto del ítem
7.8 Mensaje grande 1000 ítems en 50 listas Rendimiento: sin tiempo de espera, recuento/suma correctos
7.9 Precisión del monto de pago <PmtAmt Ccy="JPY">4750.999</PmtAmt> Regla de negocio: JPY tiene 0 decimales
7.10 Suma de control cero con ítems <CtrlSum>0</CtrlSum> pero los ítems tienen montos Regla de negocio: fallo de integridad

Esqueleto de Arnés de Prueba C#

using System.Xml;
using System.Xml.Schema;

namespace Iso20022.Tsmt.Tests
{
    public class ReconciliationAdviceValidationTests
    {
        private const string AdviceNamespace =
            "urn:iso:std:iso:20022:tech:xsd:tsmt.053.001.01";
        private const string StatusNamespace =
            "urn:iso:std:iso:20022:tech:xsd:tsmt.054.001.01";

        // Load schema once for the test suite
        private static XmlSchemaSet LoadSchema(string xsdPath)
        {
            var schemas = new XmlSchemaSet();
            schemas.Add(null, xsdPath);
            schemas.Compile();
            return schemas;
        }

        // Validate any XML string against a compiled schema
        private static List<string> ValidateXml(string xml, XmlSchemaSet schemas)
        {
            var errors = new List<string>();
            var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema };
            settings.Schemas = schemas;
            settings.ValidationEventHandler += (_, e) => errors.Add(e.Message);

            using var reader = XmlReader.Create(new StringReader(xml), settings);
            while (reader.Read()) { }
            return errors;
        }

        // --- Category 1: XML Structure ---

        [Fact]
        public void MalformedXml_ShouldThrowParserException()
        {
            var xml = "<Document><InvcPmtRcncltnAdvc></Document>"; // unclosed element
            Assert.Throws<XmlException>(() =>
                XmlReader.Create(new StringReader(xml)).Read());
        }

        [Fact]
        public void WrongNamespace_ShouldFailValidation()
        {
            var xml = WrapInDocument(
                "urn:iso:std:iso:20022:tech:xsd:tsin.008.001.01",
                "<InvcAssgnmtNtfctn/>");
            var errors = ValidateXml(xml, LoadSchema("tsmt.053.001.01.xsd"));
            Assert.NotEmpty(errors);
        }

        // --- Category 3: ReconciliationList ---

        [Fact]
        public void ItemCountMismatch_ShouldFailBusinessRule()
        {
            var msg = BuildAdvice(declaredItemCount: 3, actualItems: 1);
            var result = MessageValidator.Validate(msg);
            Assert.Contains(result.Errors, e => e.Code == "ITEM_COUNT_MISMATCH");
        }

        [Fact]
        public void ControlSumMismatch_ShouldFailBusinessRule()
        {
            var msg = BuildAdvice(declaredControlSum: 999.99m, actualSum: 4750.00m);
            var result = MessageValidator.Validate(msg);
            Assert.Contains(result.Errors, e => e.Code == "CONTROL_SUM_MISMATCH");
        }

        [Fact]
        public void ZeroPaymentAmount_ShouldFailBusinessRule()
        {
            var msg = BuildAdvice(paymentAmount: 0m);
            var result = MessageValidator.Validate(msg);
            Assert.Contains(result.Errors, e => e.Code == "ZERO_PAYMENT_AMOUNT");
        }

        // --- Category 4: FinancialItem ---

        [Fact]
        public void InvalidCreditDebitCode_ShouldFailSchema()
        {
            var xml = BuildAdviceXml(creditDebitCode: "MAYBE");
            var errors = ValidateXml(xml, LoadSchema("tsmt.053.001.01.xsd"));
            Assert.NotEmpty(errors);
        }

        [Fact]
        public void AmountArithmeticFailure_TaxPlusPretaxNotEqualTotal()
        {
            var msg = BuildAdvice(taxableAmount: 4000m, taxAmount: 500m, totalAmount: 9999m);
            var result = MessageValidator.Validate(msg);
            Assert.Contains(result.Errors, e => e.Code == "AMOUNT_ARITHMETIC_FAILURE");
        }

        // --- Category 6: Outbound Response Conformance ---

        [Fact]
        public void GeneratedStatus_ShouldPassXsdValidation()
        {
            var advice = BuildValidAdvice();
            var status = StatusGenerator.GenerateFrom(advice);
            var xml = status.Serialize();
            var errors = ValidateXml(xml, LoadSchema("tsmt.054.001.01.xsd"));
            Assert.Empty(errors); // Must be empty — a non-conformant response is never sent
        }

        [Fact]
        public void GeneratedStatus_ShouldReferenceOriginalAdvice()
        {
            var advice = BuildValidAdvice(letterId: "ADVICE-2026-001");
            var status = StatusGenerator.GenerateFrom(advice);
            Assert.Equal("ADVICE-2026-001", status.Header.RelatedDocument.Identification);
        }

        [Fact]
        public void GeneratedStatus_RecipientShouldBeOriginalAdvisor()
        {
            var advice = BuildValidAdvice(advisorBic: "BSTRUSXX");
            var status = StatusGenerator.GenerateFrom(advice);
            Assert.Equal("BSTRUSXX", status.Header.PrimaryRecipient.Party.Id.AnyBic);
        }

        // --- Category 7: Edge Cases ---

        [Fact]
        public void MaxLengthField_ExactlyAtLimit_ShouldPass()
        {
            var xml = BuildAdviceXml(partyName: new string('A', 35));
            var errors = ValidateXml(xml, LoadSchema("tsmt.053.001.01.xsd"));
            Assert.Empty(errors);
        }

        [Fact]
        public void MaxLengthField_OneBeyondLimit_ShouldFail()
        {
            var xml = BuildAdviceXml(partyName: new string('A', 36));
            var errors = ValidateXml(xml, LoadSchema("tsmt.053.001.01.xsd"));
            Assert.NotEmpty(errors);
        }

        // Helper: wrap XML in a Document element with namespace
        private static string WrapInDocument(string ns, string inner) =>
            $"<Document xmlns=\"{ns}\">{inner}</Document>";
    }
}

¿Qué Acaba de Suceder?

El gerente de QA hizo una pregunta. El Servidor ISO 20022 MCP de Beneficial Strategies recuperó ambas especificaciones de mensajes en vivo, resolvió la jerarquía completa de campos incluyendo multiplicidades, tipos y restricciones, y la IA convirtió eso en:

Las únicas decisiones que tomó fueron si incluir pruebas a nivel XML y si verificar la trazabilidad de la respuesta.

Sin abrir PDFs de especificaciones. Sin ensamblar manualmente listas de campos. Sin casos de prueba omitidos porque alguien olvidó la precisión de moneda para JPY.

Eso es lo que una suscripción al Servidor MCP de Beneficial Strategies hace por su equipo de QA. Conozca más sobre los niveles de suscripción.