Install
$ agentstack add skill-proffesor-for-testing-agentic-qe-enterprise-integration-testing ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Enterprise Integration Testing
Browser engine
UI-level enterprise integration checks (SAP Fiori launchpad smoke tests, admin UI validation) should use the qe-browser fleet skill. RFC/BAPI/IDoc/OData/SOAP testing continues to use the dedicated qe-soap-tester, qe-sap-rfc-tester, qe-sap-idoc-tester, and qe-odata-contract-tester agents. See .claude/skills/qe-browser/SKILL.md.
When testing enterprise integrations or SAP-connected systems:
- MAP the end-to-end flow (web -> API -> middleware -> backend -> response)
- IDENTIFY integration points and protocols (REST, SOAP, RFC, IDoc, OData, EDI)
- SELECT the right agent for each integration type
- TEST each integration boundary with contract and data validation
- VALIDATE cross-system data consistency (SAP WMS middleware)
- EXERCISE enterprise error handling (compensation, retry, alerting)
- GATE releases with enterprise-specific quality criteria
Agent Selection Guide:
- SAP RFC/BAPI calls ->
qe-sap-rfc-tester - SAP IDoc flows ->
qe-sap-idoc-tester - OData/Fiori services ->
qe-odata-contract-tester - SOAP/ESB endpoints ->
qe-soap-tester - Message broker flows ->
qe-message-broker-tester - Middleware routing/transformation ->
qe-middleware-validator - Authorization / SoD conflicts ->
qe-sod-analyzer
Critical Success Factors:
- Enterprise testing is cross-system: no system is tested in isolation
- Data consistency across systems is the primary quality signal
- Environment access and test data are the biggest bottlenecks
Quick Reference Card
When to Use
- Testing SAP-connected enterprise systems (S/4HANA, ECC, BW)
- Validating end-to-end business processes (Order-to-Cash, Procure-to-Pay)
- Testing middleware/ESB integrations (IIB, MuleSoft, SAP PI/PO)
- Cross-system data reconciliation (SAP WMS CRM)
- Enterprise release readiness assessment
Enterprise Integration Types
| Integration | Protocol | Agent | Typical Use | |-------------|----------|-------|-------------| | SAP RFC/BAPI | RFC | qe-sap-rfc-tester | Real-time SAP function calls | | SAP IDoc | ALE/EDI | qe-sap-idoc-tester | Asynchronous document exchange | | SAP OData | REST/OData | qe-odata-contract-tester | Fiori apps, external APIs | | SOAP/ESB | SOAP/HTTP | qe-soap-tester | Legacy service integration | | Message Broker | AMQP/JMS | qe-message-broker-tester | Async messaging (MQ, Kafka) | | Middleware | Various | qe-middleware-validator | Routing, transformation | | Authorization | SAP Auth | qe-sod-analyzer | SoD conflicts, role testing |
Critical Test Scenarios
| Scenario | Must Test | Example | |----------|----------|---------| | E2E Order Flow | Full order lifecycle | Web order -> SAP Sales Order -> WMS Pick -> Ship -> Invoice | | Data Consistency | Cross-system match | SAP inventory = WMS inventory | | IDoc Processing | Inbound/outbound | Purchase order IDoc -> SAP PO creation | | Authorization | SoD compliance | User cannot create AND approve PO | | Error Recovery | Compensation | Failed payment -> reverse inventory reservation | | Master Data Sync | Replication accuracy | Material master in SAP = Product in WMS |
Tools
- SAP: SAP GUI, Transaction codes (SE37, WE19, SEGW), Eclipse ADT
- Middleware: IBM IIB/ACE, MuleSoft, SAP PI/PO/CPI
- Testing: SoapUI, Postman, qe-browser (via Vibium for Fiori/web UIs), custom harnesses
- Monitoring: SAP Solution Manager, Splunk, Dynatrace
- Data: SAP LSMW, SECATT, eCATT
Agent Coordination
qe-sap-rfc-tester: SAP RFC/BAPI function module testingqe-sap-idoc-tester: IDoc inbound/outbound processing validationqe-odata-contract-tester: OData service contract and Fiori app testingqe-soap-tester: SOAP/WSDL contract validation and WS-Securityqe-message-broker-tester: Message broker flows, DLQ, orderingqe-middleware-validator: ESB routing, transformation, EIP patternsqe-sod-analyzer: Segregation of Duties and authorization testing
E2E Enterprise Flow Testing
Order-to-Cash Flow
describe('Order-to-Cash E2E Flow', () => {
it('processes web order through SAP to warehouse fulfillment', async () => {
// Step 1: Create order via web API
const webOrder = await api.post('/orders', {
customerId: 'CUST-1000',
items: [{ materialNumber: 'MAT-500', quantity: 10 }],
shippingAddress: { city: 'Portland', state: 'OR' }
});
expect(webOrder.status).toBe(201);
const webOrderId = webOrder.body.orderId;
// Step 2: Verify SAP Sales Order created via middleware
const sapOrder = await sapClient.call('BAPI_SALESORDER_GETLIST', {
CUSTOMER_NUMBER: 'CUST-1000',
SALES_ORGANIZATION: '1000'
});
const matchingSapOrder = sapOrder.find(o => o.PURCHASE_ORDER_NO === webOrderId);
expect(matchingSapOrder).toBeDefined();
const sapOrderId = matchingSapOrder.SD_DOC;
// Step 3: Verify WMS received pick instruction
const wmsPickTask = await wmsApi.get(`/pick-tasks?externalRef=${sapOrderId}`);
expect(wmsPickTask.status).toBe(200);
expect(wmsPickTask.body.status).toBe('PENDING');
// Step 4: Complete pick in WMS
await wmsApi.post(`/pick-tasks/${wmsPickTask.body.taskId}/complete`, {
pickedItems: [{ sku: 'MAT-500', quantity: 10, location: 'A-01-03' }]
});
// Step 5: Verify SAP delivery created (via IDoc confirmation)
await waitFor(async () => {
const delivery = await sapClient.call('BAPI_DELIVERYPROCESSING_GETLIST', {
SALES_ORDER: sapOrderId
});
return delivery.length > 0 && delivery[0].DELVRY_STATUS === 'C';
}, { timeout: 30000, interval: 3000 });
// Step 6: Verify invoice posted in SAP
await waitFor(async () => {
const invoice = await sapClient.call('BAPI_BILLINGDOC_GETLIST', {
REFDOCNUMBER: sapOrderId
});
return invoice.length > 0;
}, { timeout: 30000, interval: 3000 });
});
});
Procure-to-Pay Flow
describe('Procure-to-Pay E2E Flow', () => {
it('creates purchase requisition through to vendor payment', async () => {
// Step 1: Create Purchase Requisition
const prResult = await sapClient.call('BAPI_PR_CREATE', {
PRHEADER: { PR_TYPE: 'NB', CTRL_IND: '' },
PRHEADERX: { PR_TYPE: 'X' },
PRITEMS: [{ MATERIAL: 'MAT-RAW-100', QUANTITY: 500, UNIT: 'EA', PLANT: '1000' }]
});
expect(prResult.NUMBER).toBeDefined();
const prNumber = prResult.NUMBER;
// Step 2: Verify PR triggers sourcing (ME57 equivalent)
const sourcingResult = await sapClient.call('BAPI_PR_GETDETAIL', {
NUMBER: prNumber
});
expect(sourcingResult.PRITEM[0].PREQ_NO).toBe(prNumber);
// Step 3: Create Purchase Order from PR
const poResult = await sapClient.call('BAPI_PO_CREATE1', {
POHEADER: { COMP_CODE: '1000', DOC_TYPE: 'NB', VENDOR: 'VEND-500' },
POITEMS: [{ PO_ITEM: '00010', MATERIAL: 'MAT-RAW-100', QUANTITY: 500, PLANT: '1000' }]
});
expect(poResult.PO_NUMBER).toBeDefined();
// Step 4: Verify PO IDoc sent to vendor
const idocStatus = await sapClient.call('IDOC_STATUS_READ', {
DOCNUM: poResult.IDOC_NUMBER
});
expect(idocStatus.STATUS).toBe('03'); // Successfully sent
});
});
SAP-Specific Testing Patterns
RFC/BAPI Testing
describe('SAP RFC/BAPI Testing', () => {
it('validates BAPI return structure and error handling', async () => {
// Test with valid input
const result = await sapClient.call('BAPI_MATERIAL_GETDETAIL', {
MATERIAL: 'MAT-EXIST'
});
expect(result.RETURN.TYPE).not.toBe('E');
expect(result.MATERIAL_GENERAL_DATA.MATL_DESC).toBeDefined();
// Test with invalid material
const errorResult = await sapClient.call('BAPI_MATERIAL_GETDETAIL', {
MATERIAL: 'MAT-NONEXIST'
});
expect(errorResult.RETURN.TYPE).toBe('E');
expect(errorResult.RETURN.MESSAGE).toContain('does not exist');
});
it('handles BAPI commit correctly', async () => {
const createResult = await sapClient.call('BAPI_SALESORDER_CREATEFROMDAT2', {
ORDER_HEADER_IN: {
DOC_TYPE: 'OR',
SALES_ORG: '1000',
DISTR_CHAN: '10',
DIVISION: '00'
},
ORDER_PARTNERS: [{ PARTN_ROLE: 'AG', PARTN_NUMB: 'CUST-1000' }],
ORDER_ITEMS_IN: [{ MATERIAL: 'MAT-500', TARGET_QTY: 10 }]
});
// Must call BAPI_TRANSACTION_COMMIT to persist
await sapClient.call('BAPI_TRANSACTION_COMMIT', { WAIT: 'X' });
// Verify order exists after commit
const getResult = await sapClient.call('BAPI_SALESORDER_GETDETAIL', {
SALESDOCUMENT: createResult.SALESDOCUMENT
});
expect(getResult.ORDER_HEADER_OUT.SD_DOC_CAT).toBe('C');
});
});
IDoc Testing
describe('SAP IDoc Processing', () => {
it('validates inbound IDoc creates correct SAP document', async () => {
// Send IDoc via middleware
const idocPayload = {
IDOCTYP: 'ORDERS05',
MESTYP: 'ORDERS',
SNDPOR: 'SAPEXT',
SNDPRT: 'LS',
SNDPRN: 'EXTERN',
RCVPOR: 'SAPSI1',
RCVPRT: 'LS',
RCVPRN: 'SAPCLNT100',
segments: {
E1EDK01: { BELNR: 'EXT-PO-001' },
E1EDK14: [{ QUESSION: '001', ORGID: '1000' }],
E1EDP01: [{ POSEX: '000010', MENGE: '100', MENEE: 'EA', MATNR: 'MAT-500' }]
}
};
const idocNumber = await middlewareClient.sendIDoc(idocPayload);
// Wait for IDoc processing in SAP
await waitFor(async () => {
const status = await sapClient.call('IDOC_STATUS_READ', { DOCNUM: idocNumber });
return status.STATUS === '53'; // Application document posted successfully
}, { timeout: 60000, interval: 5000 });
// Verify SAP document was created
const sapDoc = await sapClient.call('BAPI_SALESORDER_GETLIST', {
PURCHASE_ORDER_NO: 'EXT-PO-001'
});
expect(sapDoc).toHaveLength(1);
});
it('handles IDoc error status correctly', async () => {
// Send IDoc with invalid material
const idocPayload = buildIdocPayload({ materialNumber: 'INVALID-MAT' });
const idocNumber = await middlewareClient.sendIDoc(idocPayload);
await waitFor(async () => {
const status = await sapClient.call('IDOC_STATUS_READ', { DOCNUM: idocNumber });
return ['51', '56'].includes(status.STATUS); // Error statuses
}, { timeout: 60000 });
const status = await sapClient.call('IDOC_STATUS_READ', { DOCNUM: idocNumber });
expect(status.STATUS_TEXT).toContain('Material');
});
});
OData Service Testing
describe('SAP OData Service Testing', () => {
it('validates OData entity CRUD operations', async () => {
// CREATE
const createResponse = await odataClient.post('/sap/opu/odata/sap/API_SALES_ORDER_SRV/A_SalesOrder', {
SalesOrderType: 'OR',
SalesOrganization: '1000',
DistributionChannel: '10',
OrganizationDivision: '00',
SoldToParty: 'CUST-1000'
});
expect(createResponse.status).toBe(201);
const salesOrder = createResponse.body.d.SalesOrder;
// READ with $expand
const readResponse = await odataClient.get(
`/sap/opu/odata/sap/API_SALES_ORDER_SRV/A_SalesOrder('${salesOrder}')?$expand=to_Item`
);
expect(readResponse.status).toBe(200);
expect(readResponse.body.d.SalesOrder).toBe(salesOrder);
// READ collection with $filter
const listResponse = await odataClient.get(
`/sap/opu/odata/sap/API_SALES_ORDER_SRV/A_SalesOrder?$filter=SoldToParty eq 'CUST-1000'&$top=10`
);
expect(listResponse.status).toBe(200);
expect(listResponse.body.d.results.length).toBeGreaterThan(0);
});
it('validates OData $metadata contract', async () => {
const metadata = await odataClient.get(
'/sap/opu/odata/sap/API_SALES_ORDER_SRV/$metadata'
);
expect(metadata.status).toBe(200);
const parsedMetadata = parseEdmx(metadata.body);
expect(parsedMetadata.entityTypes).toContain('A_SalesOrder');
expect(parsedMetadata.entityTypes).toContain('A_SalesOrderItem');
// Validate required properties exist
const salesOrderType = parsedMetadata.getEntityType('A_SalesOrder');
expect(salesOrderType.properties).toContain('SalesOrder');
expect(salesOrderType.properties).toContain('SalesOrderType');
expect(salesOrderType.navigationProperties).toContain('to_Item');
});
});
Fiori Launchpad Testing
describe('Fiori Launchpad App Testing', () => {
it('validates Fiori tile loads and displays correct data', async () => {
await page.goto(`${fioriLaunchpadUrl}#SalesOrder-manage`);
// Wait for OData call to complete
await page.waitForResponse(resp =>
resp.url().includes('API_SALES_ORDER_SRV') && resp.status() === 200
);
// Verify smart table loaded with data
const tableRows = await page.locator('table tbody tr');
expect(await tableRows.count()).toBeGreaterThan(0);
// Verify filter bar is functional
await page.fill('[data-sap-ui="filterField-SalesOrder"]', '1000000');
await page.click('[data-sap-ui="btnGo"]');
await page.waitForResponse(resp =>
resp.url().includes("$filter=SalesOrder eq '1000000'")
);
});
});
Cross-System Data Validation
describe('Cross-System Data Consistency', () => {
it('SAP inventory matches WMS inventory', async () => {
const materials = ['MAT-100', 'MAT-200', 'MAT-300'];
for (const material of materials) {
// Get SAP stock
const sapStock = await sapClient.call('BAPI_MATERIAL_STOCK_REQ_LIST', {
MATERIAL: material,
PLANT: '1000'
});
const sapQuantity = parseFloat(sapStock.TOTAL_STOCK);
// Get WMS inventory
const wmsInventory = await wmsApi.get(`/inventory/${material}`);
const wmsQuantity = wmsInventory.body.availableQuantity;
expect(wmsQuantity).toBe(sapQuantity);
}
});
it('customer master data is consistent across systems', async () => {
const customerId = 'CUST-1000';
const sapCustomer = await sapClient.call('BAPI_CUSTOMER_GETDETAIL', {
CUSTOMERNO: customerId
});
const crmCustomer = await crmApi.get(`/customers/${customerId}`);
const wmsCustomer = await wmsApi.get(`/customers/${customerId}`);
// Core fields must match
expect(crmCustomer.body.name).toBe(sapCustomer.CUSTOMER_GENERAL_DATA.NAME);
expect(wmsCustomer.body.name).toBe(sapCustomer.CUSTOMER_GENERAL_DATA.NAME);
expect(crmCustomer.body.taxId).toBe(sapCustomer.CUSTOMER_GENERAL_DATA.TAX_NUMBER);
});
it('order status is synchronized across all systems', async () => {
const orderId = 'ORD-SYNC-TEST';
// Create order and wait for propagation
await api.post('/orders', { orderId, customerId: 'CUST-1000', items: [{ sku: 'MAT-100', qty: 5 }] });
await sleep(10000); // Allow for async propagation
const webStatus = (await api.get(`/orders/${orderId}`)).body.status;
const sapStatus = (await sapClient.call('BAPI_SALESORDER_GETDETAIL', {
SALESDOCUMENT: orderId
})).ORDER_HEADER_OUT.DOC_STATUS;
const wmsStatus = (await wmsApi.get(`/orders/${orderId}`)).body.status;
// All systems should reflect same logical status
expect(mapSapStatus(sapStatus)).toBe(webStatus);
expect(mapWmsStatus(wmsStatus)).toBe(webStatus);
});
});
Enterprise Test Data Management
describe('Enterprise Test Data Strategy', () => {
// Master data setup - reusable across test suites
const masterDataFixture = {
async setup() {
// Create customer in SAP (source of truth)
const customer = await sapClient.call('BAPI_CUSTOMER_CREATE', {
PI_COPYREFERENCE: { SALESORG: '1000', DISTR_CHAN: '10' },
PI_PERSONALDATA: { FIRSTNAME: 'Test', LASTNAME: `Customer-${Date.now()}` }
});
await sapClient.call('BAPI_TRANSACTION_COMMIT', { WAIT: 'X' });
// Wait for replication to downstream systems
await waitFor(async () => {
const wms = await wmsApi.get(`/cu
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [proffesor-for-testing](https://github.com/proffesor-for-testing)
- **Source:** [proffesor-for-testing/agentic-qe](https://github.com/proffesor-for-testing/agentic-qe)
- **License:** MIT
- **Homepage:** https://agentic-qe.dev/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.