Claude
Skills
Sign in
Back

integration-tester

Included with Lifetime
$97 forever

Design integration test plans with mock, contract, and end-to-end testing specifications to validate API integrations before go-live and after changes.

Design

What this skill does


# Integration Tester

Produce a complete integration test plan for a system integration. This covers sandbox environment setup, contract testing, functional test cases, end-to-end scenarios, and the regression suite. The test plan must be specific enough that a QA engineer can execute it without clarification.

## Test Scope and Strategy

Define what is being tested and what is out of scope:

**In scope**:
- API connector: authentication, endpoint calls, request formation, response parsing
- Data mapping: field transformations, lookup table translations, null handling
- Error handling: retry behavior, DLQ routing, alert triggering
- End-to-end flow: source record change → integration processing → destination record created/updated

**Out of scope**:
- Source system business logic (tested by source system owner)
- Destination system business logic (tested by destination system owner)
- Network infrastructure performance
- Load/performance testing (separate engagement if required)

**Test environments**:

| Environment | Source System | Destination System | Integration | Purpose |
|-------------|--------------|-------------------|-------------|---------|
| Development | Mock server | Mock server | Local | Developer unit testing |
| Integration Test | Sandbox | Sandbox | Deployed | Full integration testing |
| UAT | Sandbox | UAT | Deployed | Business acceptance testing |
| Production | Production | Production | Deployed | Smoke test post-deployment only |

## Mock Server Design

For source or destination systems without a sandbox, build a mock server.

**Mock server tool selection**: WireMock (Java), Nock (Node.js), or MockServer (Docker). Choose based on the team's language stack.

**Mock endpoint definitions**:

For each API endpoint, define a mock that returns realistic test data:

```json
GET /policies?status=active&limit=100
Response 200:
{
  "data": [
    {
      "policy_id": "test-policy-001",
      "policy_number": "TEST-POL-2026-001",
      "client_id": "client-001",
      "effective_date": "2026-01-15",
      "premium_amount": 1250.00,
      "status_code": "A",
      "lob_code": "AU",
      "producer_npi": "1234567890",
      "notes": "Test policy for integration testing",
      "created_at": "2026-01-15T09:00:00-05:00",
      "modified_at": "2026-01-15T09:00:00-05:00"
    }
  ],
  "next_page_token": null,
  "has_more": false
}
```

**Error scenario mocks**:

| Scenario | Mock Configuration |
|----------|-------------------|
| Rate limit | Return 429 with `Retry-After: 5` on every 5th request |
| Service unavailable | Return 503 for 3 consecutive requests, then 200 |
| Auth failure | Return 401 when using any token other than the test token |
| Not found | Return 404 when record ID starts with "notfound-" |
| Validation failure | Return 400 with field error when premium_amount is negative |
| Duplicate | Return 409 when policy_number is "DUPLICATE-001" |

## Contract Tests

Contract tests verify the integration assumes the correct API shape. Run against both the mock and the real sandbox.

**Contract test suite**:

```typescript
describe('Source API Contract', () => {
  describe('GET /policies', () => {
    it('returns array in data field', async () => {
      const response = await apiClient.getPolicies();
      expect(Array.isArray(response.data)).toBe(true);
    });
    
    it('policy has required fields', async () => {
      const response = await apiClient.getPolicies({ limit: 1 });
      const policy = response.data[0];
      expect(policy).toHaveProperty('policy_id');
      expect(policy).toHaveProperty('policy_number');
      expect(policy).toHaveProperty('client_id');
      expect(policy).toHaveProperty('effective_date');
      expect(policy).toHaveProperty('premium_amount');
      expect(policy).toHaveProperty('status_code');
      expect(policy).toHaveProperty('lob_code');
    });
    
    it('effective_date is ISO 8601 date format', async () => {
      const response = await apiClient.getPolicies({ limit: 1 });
      const date = response.data[0].effective_date;
      expect(date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
    });
    
    it('premium_amount is a number', async () => {
      const response = await apiClient.getPolicies({ limit: 1 });
      expect(typeof response.data[0].premium_amount).toBe('number');
    });
    
    it('pagination: next_page_token present when has_more is true', async () => {
      // Only meaningful if source has > limit records
      const response = await apiClient.getPolicies({ limit: 1 });
      if (response.has_more) {
        expect(response.next_page_token).toBeTruthy();
      }
    });
  });
  
  describe('Authentication', () => {
    it('returns 401 with invalid credentials', async () => {
      const badClient = createApiClient({ apiKey: 'invalid-key' });
      await expect(badClient.getPolicies()).rejects.toThrow(/401/);
    });
    
    it('token is refreshed before expiry', async () => {
      // Set token to expire in 30 seconds, wait 25 seconds, make a request
      // Verify a new token was acquired without a 401
      // [Implementation specific to auth mechanism]
    });
  });
});
```

**Run contract tests against real sandbox**: After running against mocks, run the same contract test suite against the actual sandbox API. Any failure indicates the API has changed from what the integration assumes — fix the integration before proceeding.

## Functional Test Cases

**Happy path test cases**:

| # | Test Case | Input | Expected Result | Verification |
|---|-----------|-------|-----------------|-------------|
| F-01 | Sync new policy | POST new policy to source sandbox | Policy created in destination with all mapped fields correct | GET policy from destination API, compare all mapped fields |
| F-02 | Sync policy update | Update premium_amount in source | Destination policy premium updated within 1 sync cycle | GET policy from destination, verify PremiumAmount updated |
| F-03 | Sync policy cancellation | Change status to "C" in source | Destination policy status changed to "Cancelled" | GET policy from destination, verify status |
| F-04 | LOB code translation: all codes | Create policy with each lob_code value | Each code mapped to correct destination LineOfBusiness | One test per LOB code |
| F-05 | Status code translation: all codes | Create policy with each status_code | Each code mapped correctly | One test per status code |
| F-06 | Producer lookup: known NPI | Policy with valid producer_npi | ProducerId set to correct GUID in destination | Verify ProducerId matches expected |
| F-07 | Producer lookup: unknown NPI | Policy with NPI not in mapping table | ProducerId set to null, unknown NPI logged | Verify null ProducerId + log entry |
| F-08 | Notes truncation | Notes field with 5000 characters | Notes truncated to 4000 chars, truncation logged | Verify destination notes length, verify log entry |
| F-09 | Null premium handling | Policy with null premium_amount | PremiumAmount set to 0.00 | Verify PremiumAmount = 0 |
| F-10 | Full pagination | Source has 250 policies | All 250 policies synced (3 pages of 100) | COUNT destination policies = 250 |

**Error handling test cases**:

| # | Test Case | Input | Expected Result | Verification |
|---|-----------|-------|-----------------|-------------|
| E-01 | Rate limit: single 429 | Mock returns 429 once, then 200 | Request retries successfully after Retry-After delay | Log shows retry; request succeeds |
| E-02 | Rate limit: exhausted retries | Mock returns 429 five times | Request sent to DLQ after 5 attempts | DLQ entry exists with AttemptCount = 5 |
| E-03 | Service unavailable: transient | Mock returns 503 twice, then 200 | Request retries and succeeds | Log shows retries; request succeeds |
| E-04 | Validation failure | Send policy with negative premium | Record sent to DLQ with ErrorCode = VALIDATION_FAILED | DLQ entry exists; error category = Permanent |
| E-05 | Duplicate record | Submit same policy_number twice | Second submiss

Related in Design