Przejdź do głównej zawartości

Wzorce testowania integracyjnego

PRD: Kompleksowy system testowania integracyjnego

Wymagania: Walidacja interakcji serwisów, kontraktów API, transakcji bazodanowych i komunikacji kolejek wiadomości z niezawodnością >95% przy użyciu scenariuszy testowych generowanych przez AI.

Plan: Wykorzystaj Cursor i Claude Code z wyspecjalizowanymi serwerami MCP (baza danych, testowanie API, kolejka wiadomości) do tworzenia kompleksowych zestawów testów integracyjnych, które wychwytują błędy interakcji i zapewniają niezawodność systemu.

Todo:

  • Badanie serwerów MCP do testowania integracyjnego
  • Definicja strategii testowania interakcji serwisów
  • Implementacja wzorców testowania kontraktów
  • Tworzenie testów integracji bazodanowej
  • Konfiguracja testowania kolejek wiadomości
  • Budowa testów integracji wydajnościowej

Rewolucja testowania integracyjnego wspieranego przez AI

Dział zatytułowany „Rewolucja testowania integracyjnego wspieranego przez AI”

Testowanie integracyjne wykracza poza proste wywołania API do inteligentnej walidacji złożonych interakcji systemowych. AI pomaga odkrywać ukryte zależności, generować realistyczne scenariusze testowe i utrzymywać testy w miarę ewolucji architektury.

Testowanie w języku naturalnym

Prompt: “Przetestuj integrację serwisu płatności z obsługą timeoutów i scenariuszami rollback”

Wynik: Kompletny zestaw testów z mockami serwisów i wstrzykiwaniem błędów

Inteligencja kontraktów

AI analizuje schematy API i automatycznie generuje testy kontraktów zorientowane na konsumenta

Walidacja przepływu danych

Śledź spójność danych między serwisami, bazami danych i kolejkami wiadomości

Integracja wydajnościowa

Monitoruj czasy odpowiedzi, przepustowość i wykorzystanie zasobów między granicami serwisów

Przepływy pracy testowania integracyjnego w prawdziwych scenariuszach

Dział zatytułowany „Przepływy pracy testowania integracyjnego w prawdziwych scenariuszach”

Przepływ pracy 1: Testowanie integracji mikroserwisów

Dział zatytułowany „Przepływ pracy 1: Testowanie integracji mikroserwisów”

Scenariusz: Testowanie złożonego systemu przetwarzania zamówień e-commerce z wieloma zależnościami serwisów.

Okno terminala
# PRD: Testy integracji przetwarzania zamówień e-commerce
# Wymagania: Walidacja kompletnego przepływu zamówień z interakcjami serwisów
"Przeanalizuj naszą architekturę mikroserwisów i utwórz testy integracyjne:
Zaangażowane serwisy:
- Serwis zamówień (orkiestrator)
- Serwis użytkowników (autentyfikacja)
- Serwis inwentarza (zarządzanie stanem)
- Serwis płatności (rozliczenia)
- Serwis wysyłki (realizacja)
- Serwis powiadomień (komunikacja)
Potrzebne scenariusze testowe:
1. Ścieżka happy path: Kompletne przetwarzanie zamówienia
2. Niedobór inwentarza: Obsługa rollback
3. Niepowodzenie płatności: Anulowanie zamówienia
4. Niedostępność wysyłki: Aktualizacje statusu
5. Timeout serwisu: Aktywacja wyłącznika bezpieczeństwa
6. Częściowe awarie: Wzorce kompensacji
Wymagania:
- Testowanie kontraktów dla wszystkich granic serwisów
- Walidacja spójności transakcji
- Wydajność pod obciążeniem
- Testowanie propagacji błędów
- Walidacja monitorowania i alertów"

Scenariusz: Zapewnienie kompatybilności API między serwisami, które ewoluują niezależnie.

Okno terminala
# PRD: Testowanie kontraktów zorientowanych na konsumenta
# Plan: Użyj Pact.js ze scenariuszami kontraktów generowanymi przez AI
"Utwórz testy kontraktów dla naszego ekosystemu serwisów:
Relacje serwisów:
- OrderService (konsument) → UserService (dostawca)
- OrderService (konsument) → PaymentService (dostawca)
- NotificationService (konsument) → UserService (dostawca)
- InventoryService (konsument) → ProductService (dostawca)
Dla każdego kontraktu:
1. Generuj realistyczne scenariusze request/response
2. Uwzględnij warunki błędów i przypadki brzegowe
3. Testuj kompatybilność ewolucji schematu
4. Utwórz testy weryfikacji dostawcy
5. Skonfiguruj przepływ publikowania kontraktów
6. Dodaj wykrywanie zmian powodujących błędy
Skup się na:
- Walidacji tokenu autentyfikacji
- Spójności formatu danych
- Standardach odpowiedzi błędów
- Oczekiwaniach wydajnościowych"

Scenariusz: Testowanie złożonych transakcji bazodanowych i spójności danych w wielu tabelach i serwisach.

// Test integracji bazodanowej generowany przez AI
describe('Transakcja przetwarzania zamówienia', () => {
let db: Database;
let orderService: OrderService;
let inventoryService: InventoryService;
beforeEach(async () => {
db = await createTestDatabase();
orderService = new OrderService(db);
inventoryService = new InventoryService(db);
});
it('powinien utrzymać spójność podczas tworzenia zamówienia', async () => {
// AI generuje test z odpowiednią obsługą transakcji
const productId = 'prod-123';
const quantity = 5;
// Ustaw początkowy inwentarz
await inventoryService.setStock(productId, 10);
// Rozpocznij transakcję
const transaction = await db.beginTransaction();
try {
// Utwórz zamówienie
const order = await orderService.createOrder({
productId,
quantity,
userId: 'user-123'
}, transaction);
// Zaktualizuj inwentarz
await inventoryService.decrementStock(
productId,
quantity,
transaction
);
await transaction.commit();
// Sprawdź spójność
const finalStock = await inventoryService.getStock(productId);
expect(finalStock).toBe(5);
const savedOrder = await orderService.getOrder(order.id);
expect(savedOrder.status).toBe('confirmed');
} catch (error) {
await transaction.rollback();
throw error;
}
});
// AI dodaje scenariusz rollback
it('powinien wykonać rollback przy niewystarczającym inwentarzu', async () => {
const productId = 'prod-456';
await inventoryService.setStock(productId, 3);
await expect(async () => {
await db.transaction(async (trx) => {
await orderService.createOrder({
productId,
quantity: 5,
userId: 'user-789'
}, trx);
await inventoryService.decrementStock(productId, 5, trx);
});
}).rejects.toThrow('Niewystarczający inwentarz');
// Sprawdź czy nie wprowadzono zmian
const stock = await inventoryService.getStock(productId);
expect(stock).toBe(3);
});
});

Przepływ pracy 4: Testowanie integracji kolejek wiadomości

Dział zatytułowany „Przepływ pracy 4: Testowanie integracji kolejek wiadomości”

Scenariusz: Walidacja komunikacji sterowanej zdarzeniami między mikroserwisami z niezawodnym dostarczaniem wiadomości.

// Test integracji kolejki wiadomości generowany przez AI
describe('Przetwarzanie zamówień sterowane zdarzeniami', () => {
let messageQueue: MessageQueue;
let orderService: OrderService;
let paymentService: PaymentService;
let shippingService: ShippingService;
beforeEach(async () => {
messageQueue = await createTestMessageQueue();
// AI konfiguruje połączenia serwisów
orderService = new OrderService(messageQueue);
paymentService = new PaymentService(messageQueue);
shippingService = new ShippingService(messageQueue);
// Uruchom serwisy
await Promise.all([
orderService.start(),
paymentService.start(),
shippingService.start()
]);
});
it('powinien przetworzyć zamówienie przez cały pipeline', async () => {
// AI tworzy kompleksowy test przepływu zdarzeń
const orderId = 'order-123';
const orderCreatedPromise = waitForEvent(
messageQueue,
'order.created'
);
const paymentProcessedPromise = waitForEvent(
messageQueue,
'payment.processed'
);
const orderShippedPromise = waitForEvent(
messageQueue,
'order.shipped'
);
// Wyzwól tworzenie zamówienia
await orderService.createOrder({
id: orderId,
items: [{ productId: 'prod-1', quantity: 2 }],
total: 99.99
});
// Sprawdź łańcuch zdarzeń
const orderCreatedEvent = await orderCreatedPromise;
expect(orderCreatedEvent.data.orderId).toBe(orderId);
const paymentEvent = await paymentProcessedPromise;
expect(paymentEvent.data.orderId).toBe(orderId);
expect(paymentEvent.data.status).toBe('success');
const shippingEvent = await orderShippedPromise;
expect(shippingEvent.data.orderId).toBe(orderId);
expect(shippingEvent.data.trackingNumber).toBeDefined();
});
// AI dodaje test propagacji błędów
it('powinien elegancko obsłużyć niepowodzenie płatności', async () => {
// Ustaw serwis płatności do niepowodzenia
paymentService.mockPaymentGateway.failNext();
const orderFailedPromise = waitForEvent(
messageQueue,
'order.failed'
);
await orderService.createOrder({
id: 'order-fail-123',
total: 999.99
});
const failureEvent = await orderFailedPromise;
expect(failureEvent.data.reason).toBe('payment_failed');
expect(failureEvent.data.orderId).toBe('order-fail-123');
});
});

Scenariusz: Testowanie złożonych zapytań i mutacji GraphQL z zagnieżdżonymi relacjami danych.

// Test integracji GraphQL generowany przez AI
describe('Integracja API GraphQL', () => {
let app: Application;
let authService: AuthService;
let dataLoader: DataLoader;
beforeAll(async () => {
app = await createTestApp();
authService = app.get(AuthService);
dataLoader = app.get(DataLoader);
});
it('powinien efektywnie rozwiązywać zagnieżdżone zapytania', async () => {
// AI generuje test złożonych zapytań
const query = `
query GetUserWithOrders($userId: ID!) {
user(id: $userId) {
id
name
email
orders(limit: 10) {
id
total
items {
product {
id
name
price
}
quantity
}
shippingAddress {
street
city
country
}
}
}
}
`;
const response = await request(app)
.post('/graphql')
.send({
query,
variables: { userId: 'user-123' }
})
.set('Authorization', 'Bearer test-token');
expect(response.body.errors).toBeUndefined();
expect(response.body.data.user).toMatchObject({
id: 'user-123',
orders: expect.arrayContaining([
expect.objectContaining({
items: expect.arrayContaining([
expect.objectContaining({
product: expect.objectContaining({
id: expect.any(String),
name: expect.any(String)
})
})
])
})
])
});
// Sprawdź brak zapytań N+1
const queryCount = dataLoader.getQueryCount();
expect(queryCount).toBeLessThan(10); // Odpowiednio zbatchowane
});
});

Scenariusz: Wykorzystywanie prawdziwych wzorców ruchu produkcyjnego do walidacji zachowania integracji.

Testowanie oparte na ruchu

// Użycie Keploy do testowania prawdziwego ruchu
import { Keploy } from '@keploy/sdk';
describe('Odtwarzanie ruchu produkcyjnego', () => {
let keploy: Keploy;
beforeAll(async () => {
keploy = new Keploy({
mode: 'test',
path: './keploy-tests'
});
});
it('powinien obsłużyć przechwycone scenariusze produkcyjne', async () => {
// Keploy odtwarza przechwycony ruch
const results = await keploy.runCapturedTests({
service: 'payment-service',
environment: 'staging',
coverageThreshold: 0.9
});
expect(results.passed).toBe(results.total);
expect(results.coverage).toBeGreaterThan(0.9);
// Sprawdź brak regresji
results.tests.forEach(test => {
expect(test.responseMatches).toBe(true);
expect(test.latency).toBeLessThan(test.baseline * 1.1);
});
});
});
// Test rozproszonego śledzenia generowany przez AI
describe('Przepływ żądań między serwisami', () => {
let tracer: Tracer;
let services: ServiceMesh;
beforeEach(async () => {
tracer = createTestTracer();
services = await deployTestServices(tracer);
});
it('powinien utrzymać kontekst śledzenia między serwisami', async () => {
const traceId = generateTraceId();
// Wykonaj żądanie z kontekstem śledzenia
const response = await services.gateway.request({
path: '/api/checkout',
method: 'POST',
headers: {
'X-Trace-Id': traceId
},
body: {
cartId: 'cart-123'
}
});
//Zbierz spany śledzenia
const spans = await tracer.getSpans(traceId);
// AI generuje kompleksową walidację śledzenia
expect(spans).toContainEqual(
expect.objectContaining({
service: 'gateway',
operation: 'checkout.start'
})
);
expect(spans).toContainEqual(
expect.objectContaining({
service: 'cart-service',
operation: 'cart.validate'
})
);
expect(spans).toContainEqual(
expect.objectContaining({
service: 'payment-service',
operation: 'payment.process'
})
);
// Sprawdź timing i zależności
const gatewaySpan = spans.find(s => s.service === 'gateway');
const paymentSpan = spans.find(s => s.service === 'payment-service');
expect(paymentSpan.parentId).toBe(gatewaySpan.spanId);
expect(paymentSpan.startTime).toBeGreaterThan(gatewaySpan.startTime);
});
});
// Test wydajności integracji generowany przez AI
describe('Wydajność integracji serwisów', () => {
it('powinien obsłużyć równoczesne żądania między serwisami', async () => {
const loadTest = new LoadTest({
duration: '30s',
vus: 100, // Użytkownicy wirtualni
thresholds: {
'http_req_duration': ['p(95) < 500'], // 95% poniżej 500ms
'http_req_failed': ['rate < 0.01'], // Wskaźnik błędów poniżej 1%
}
});
await loadTest.run(async (vu) => {
// AI generuje realistyczną podróż użytkownika
const userId = `user-${vu.id}`;
// Logowanie
const authResponse = await vu.post('/auth/login', {
username: userId,
password: 'test123'
});
const token = authResponse.json('token');
// Przeglądaj produkty
const products = await vu.get('/products', {
headers: { Authorization: `Bearer ${token}` }
});
// Dodaj do koszyka
const product = products.json('products[0]');
await vu.post('/cart/add', {
productId: product.id,
quantity: 1
});
// Checkout
const order = await vu.post('/checkout', {
paymentMethod: 'test-card'
});
vu.check(order.status === 200, 'Checkout pomyślny');
});
const results = await loadTest.getResults();
expect(results.checks.passes).toBeGreaterThan(0.99);
expect(results.metrics.http_req_duration.p95).toBeLessThan(500);
});
});

Przykładowe prompty dla różnych scenariuszy integracji

Dział zatytułowany „Przykładowe prompty dla różnych scenariuszy integracji”

Niezależność testów

// Każdy test zarządza własnymi danymi testowymi
beforeEach(async () => {
testContext = await createIsolatedContext();
// Użyj unikalnych ID, osobnych baz danych, itp.
});

Mockowanie serwisów

// Konsekwentnie mockuj zewnętrzne zależności
const mockPaymentGateway = createMock({
responses: loadFromContract('payment-gateway-v2')
});

Spójność danych

// Sprawdź spójność danych między serwisami
expect(orderService.getOrder(id))
.toEqual(inventoryService.getOrderItems(id));

Propagacja błędów

// Testuj obsługę błędów między granicami
await expectErrorChain()
.from(paymentService)
.through(orderService)
.to(notificationService);

Przechwytywanie i odtwarzanie prawdziwego ruchu

  • Przechwytuje wywołania API produkcyjne
  • Generuje testy automatycznie
  • Utrzymuje spójność danych testowych
  • Dostarcza metryki pokrycia
Okno terminala
# Zainstaluj i przechwyć ruch
keploy record -c "npm start"
# Uruchom wygenerowane testy
keploy test -c "npm start"
# Pipeline CI zoptymalizowany przez AI do testów integracyjnych
name: Zestaw testów integracyjnych
on:
pull_request:
push:
branches: [main]
jobs:
integration-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
steps:
- uses: actions/checkout@v3
- name: Konfiguruj środowisko testowe
run: |
docker-compose -f docker-compose.test.yml up -d
npm run wait-for-services
- name: Uruchom testy integracyjne
run: |
npm run test:integration -- --coverage
env:
DATABASE_URL: postgres://test:test@localhost:5432/test
REDIS_URL: redis://localhost:6379
- name: Uruchom testy kontraktów
run: |
npm run test:contracts
npm run pact:publish
- name: Sprawdzenie regresji wydajności
run: |
npm run test:performance -- --compare-with main