SaaS Platformu için API Test Framework'ü

Yıl 2025
Rol Senior Test Automation Engineer
Teknolojiler
PlaywrightTypeScriptPactJestPostgreSQLDocker Compose

Problem

Mikroservis mimarisine geçiş sürecindeki SaaS platformu, servisler arası entegrasyon hatalarından ciddi biçimde etkileniyordu. UI testleri production ortamında geçiyor, ancak servislerin birbirleriyle konuştuğu noktalarda beklenmedik 500 hataları ve veri tutarsızlıkları ortaya çıkıyordu.

Kök nedene bakıldığında:

  • Servis A’nın API şemasını değiştirmesi, Servis B’yi sessizce bozuyordu
  • Integration ortamı yoktu; ilk karşılaşma production’da oluyordu
  • GraphQL mutation’larının yan etkileri test edilmiyordu

Yaklaşım

Çözümü iki katmanda kurdum:

1. Contract Testing (Pact): Servisler arasındaki “sözleşmeleri” consumer tarafında tanımla, provider tarafında doğrula. Schema değişikliği olduğunda CI anında uyarı verir.

2. API Entegrasyon Testleri (Playwright + özel client): Gerçek HTTP istekleri, DB state doğrulaması, multi-step senaryolar.

Playwright’ı API testleri için tercih etmemin nedeni: zaten aşina olunan assertion API’si, built-in retry mekanizması ve UI testleriyle ortak fixture altyapısını paylaşabilmek.

// helpers/api-client.ts
import { APIRequestContext } from '@playwright/test';

export class ApiClient {
  constructor(
    private request: APIRequestContext,
    private baseURL: string
  ) {}

  async createPayment(payload: CreatePaymentDto) {
    const response = await this.request.post(`${this.baseURL}/payments`, {
      data: payload,
      headers: { 'Content-Type': 'application/json' },
    });
    expect(response.ok()).toBeTruthy();
    return response.json();
  }

  async getPaymentStatus(id: string) {
    const response = await this.request.get(`${this.baseURL}/payments/${id}`);
    return response.json();
  }
}

Çözüm

Contract test örneği — consumer (frontend) bakış açısı:

// contracts/payment-service.pact.ts
import { PactV3, MatchersV3 } from '@pact-foundation/pact';

const provider = new PactV3({
  consumer: 'FrontendApp',
  provider: 'PaymentService',
});

describe('Payment Service Contract', () => {
  it('ödeme oluşturma endpoint sözleşmesi', async () => {
    await provider
      .given('geçerli kullanıcı oturumu mevcut')
      .uponReceiving('yeni ödeme talebi')
      .withRequest({
        method: 'POST',
        path: '/payments',
        body: {
          amount: MatchersV3.number(100),
          currency: MatchersV3.string('TRY'),
          recipientId: MatchersV3.uuid(),
        },
      })
      .willRespondWith({
        status: 201,
        body: {
          id: MatchersV3.uuid(),
          status: MatchersV3.string('pending'),
          createdAt: MatchersV3.iso8601DateTime(),
        },
      });

    await provider.executeTest(async (mockServer) => {
      const client = new ApiClient(request, mockServer.url);
      const result = await client.createPayment({
        amount: 100,
        currency: 'TRY',
        recipientId: '550e8400-e29b-41d4-a716-446655440000',
      });
      expect(result.status).toBe('pending');
    });
  });
});

Docker Compose ile izole test ortamı — her CI run’ında temiz bir database:

# docker-compose.test.yml
services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: testdb
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "test"]
      interval: 2s
      retries: 5

Sonuç

  • Contract test kapsamı: 12 servis entegrasyonu
  • Yakalanan schema breaking change sayısı (ilk 3 ayda): 7
  • Ortalama hata tespit süresi (integration → deployment öncesi): 4 saatten 8 dakikaya
  • API test suite çalışma süresi: ~3 dakika (paralel)

Öğrendiklerim

  • Pact broker olmadan contract testing ölçeklenmez: İlk iterasyonda dosya bazlı contract paylaşımı yaptım. 4. servisde yönetilemez hale geldi. Pact Broker (ya da managed PactFlow) zorunluluk.
  • DB state temizliği ihmal edilmez: Test sıralaması fark etmemeli. Her test kendi verisini yaratıp temizliyorsa, paralel çalışma sorunsuz olur. Transaction rollback pattern burada işe yarıyor.
  • API ve UI testleri ayrı pipeline’da çalışmalı: API testleri çok daha hızlı. PR’larda API suite’i, main’de her ikisi çalıştırmak feedback döngüsünü hızlandırıyor.