Performans ve Yük Testi (Performance & Load Testing)

Performansı nasıl test edersiniz, darboğazları (Bottlenecks) nasıl bulursunuz ve yük altında kararlılığı nasıl sağlarsınız


Performance Testing

📍 Buradasınız:

[✓] Makale 1: QA Temelleri (QA Fundamentals)
[✓] Makale 2: QA Pratiği (QA Practice)
[✓] Makale 3: QA için Veri Yapıları ve Algoritmalar (DSA for QA)
[✓] Makale 4: Otomasyon Çerçeveleri (Automation Frameworks)
[✓] Makale 5: Sürekli Entegrasyon (CI/CD)
[✓] Makale 6: Test Tasarım Teknikleri (Test Design Techniques)
[→] Makale 7: Performans Testi (Performance Testing) ← Şu an okuyorsunuz
[ ] Makale 8: Apple'da Hayalinizdeki İşi Elde Etmek (Landing Your Dream Job)

İlerleme: %87 ✨


Uygulamanız dizüstü bilgisayarınızda mükemmel çalışıyor. Ama 10.000 kullanıcı aynı anda giriş yaptığında ne olur? Veritabanı 10 milyon kayda ulaştığında? API saniyede 1.000 istek aldığında?

Performans Testine (Performance Testing) hoş geldiniz — Senior QA’yı Middle’dan ayıran kritik bir beceri.

Gerçek bir Apple Software Quality Engineer iş ilanından:

“Performans testi ve analizi deneyimi (Experience with performance testing and analysis)”

Bu makalede öğrenecekleriniz:

  • Performans metriklerini anlama
  • Yük testi (Load Testing) ve stres testi (Stress Testing) yapma
  • JMeter, K6, Gatling kullanma
  • Darboğazları (Bottlenecks) bulma ve analiz etme
  • Performans testlerini CI/CD’ye entegre etme

📋 İçindekiler

  1. Performans Testi Türleri (Performance Testing Types)
  2. Temel Performans Metrikleri (Key Performance Metrics)
  3. JMeter: Endüstri Standardı (Industry Standard)
  4. K6: Modern JavaScript Yaklaşımı (Modern JavaScript Approach)
  5. Gatling: Scala Gücü (The Power of Scala)
  6. Gerçek Dünya Senaryoları (Real-World Scenarios)
  7. Sonuç Analizi ve Darboğaz Bulma (Bottleneck Analysis)
  8. CI/CD’de Performans Testi (Performance Testing in CI/CD)
  9. En İyi Uygulamalar (Best Practices)
  10. Mülakat Soruları (Interview Questions)

🎯 Performans Testi Türleri

1. Yük Testi (Load Testing)

Amaç: Sistemin beklenen yük altında nasıl davrandığını kontrol etmek

Örnek:

  • Normal: 1.000 eşzamanlı kullanıcı
  • Black Friday: 50.000 eşzamanlı kullanıcı

Sorular:

  • Sistem planlanan yükü kaldırabilecek mi?
  • Normal yük altında response time nedir?
// K6 Load Test Örneği
import http from 'k6/http';
import { sleep, check } from 'k6';

export const options = {
    stages: [
        { duration: '2m', target: 100 },  // 100 kullanıcıya çık
        { duration: '5m', target: 100 },  // 100 kullanıcıda kal
        { duration: '2m', target: 0 },    // 0'a düş
    ],
    thresholds: {
        http_req_duration: ['p(95)<500'], // %95 istek 500ms altında
        http_req_failed: ['rate<0.01'],   // <%1 hata
    },
};

export default function() {
    const res = http.get('https://api.example.com/products');
    
    check(res, {
        'status is 200': (r) => r.status === 200,
        'response time < 500ms': (r) => r.timings.duration < 500,
    });
    
    sleep(1);
}

2. Stres Testi (Stress Testing)

Amaç: Sistemin kırılma noktasını bulmak

Senaryo: Sistem çökene kadar yükü kademeli olarak artırın

Sorular:

  • Sistem ne zaman bozulmaya başlar?
  • Çöküşten sonra nasıl toparlanır?
  • Hangi bileşenler önce başarısız olur?
// K6 Stress Test
export const options = {
    stages: [
        { duration: '2m', target: 100 },   // Normal yük
        { duration: '5m', target: 200 },   // Kırılma noktası civarı
        { duration: '2m', target: 300 },   // Kapasitenin üstünde
        { duration: '5m', target: 400 },   // Çok üstünde
        { duration: '10m', target: 0 },    // Toparlanma
    ],
};

export default function() {
    const res = http.get('https://api.example.com/products');
    
    check(res, {
        'status is not 500': (r) => r.status !== 500,
    });
    
    sleep(1);
}

3. Ani Artış Testi (Spike Testing)

Amaç: Ani trafik artışlarına tepkiyi kontrol etmek

Örnek:

  • Reklam kampanyası başladı
  • Viral sosyal medya paylaşımı
  • Ani indirim (Flash Sale) başladı
// K6 Spike Test
export const options = {
    stages: [
        { duration: '10s', target: 100 },  // Normal
        { duration: '1m', target: 2000 },  // SPIKE!
        { duration: '3m', target: 2000 },  // Spike'ı tut
        { duration: '10s', target: 100 },  // Normale dön
        { duration: '3m', target: 100 },   // Toparlanma
    ],
};

4. Dayanıklılık Testi (Soak/Endurance Testing)

Amaç: Uzun süreli yük altında kararlılığı kontrol etmek

Bulduğu sorunlar:

  • Bellek sızıntıları (Memory Leaks)
  • Veritabanı bağlantı sızıntıları (Connection Leaks)
  • Disk alanı sorunları
  • Log dosyası büyümesi
// K6 Soak Test - saatlerce çalışır
export const options = {
    stages: [
        { duration: '2m', target: 400 },    // Ramp up
        { duration: '3h56m', target: 400 }, // ~4 saat kal
        { duration: '2m', target: 0 },      // Ramp down
    ],
};

📊 Temel Performans Metrikleri

1. Yanıt Süresi (Response Time)

Tanım: İstek gönderilmesinden yanıt alınmasına kadar geçen süre

Metrikler:

  • Ortalama Yanıt Süresi (Average Response Time) - ortalama süre
  • Medyan (50. yüzdelik / p50) - isteklerin yarısı daha hızlı
  • 90. yüzdelik (p90) - isteklerin %90’ı daha hızlı
  • 95. yüzdelik (p95) - isteklerin %95’i daha hızlı
  • 99. yüzdelik (p99) - isteklerin %99’u daha hızlı

Neden yüzdelikler (Percentiles) ortalamadan önemli:

Örnek:
9 istek: her biri 100ms
1 istek: 10.000ms (timeout)

Ortalama: 1.090ms (kötü görünüyor)
95. yüzdelik: 100ms (kullanıcıların %95'i için gerçekten iyi)

Hedef değerler:

İşlem TürüHedef
Sayfa Yükleme< 2 saniye
API GET< 200ms
API POST< 500ms
Arama< 1 saniye
Veritabanı Sorgusu< 100ms

2. İş Hacmi (Throughput)

Tanım: Birim zamanda istek sayısı

Metrikler:

  • Saniyede istek (Requests per second, RPS)
  • Saniyede işlem (Transactions per second, TPS)
  • Dakikada sayfa (Pages per minute)

Örnek:

İyi: 1000 RPS ile 200ms response time
Kötü: 1000 RPS ile 5000ms response time

3. Hata Oranı (Error Rate)

Tanım: Başarısız isteklerin yüzdesi

Hedef değerler:

  • Production: < %0.1 (%99.9 başarı)
  • Staging: < %1
  • Kritik API’ler: < %0.01 (%99.99 başarı)

Hata türleri:

  • 4xx hataları (istemci hataları)
  • 5xx hataları (sunucu hataları)
  • Timeout’lar
  • Bağlantı hataları

4. Eşzamanlı Kullanıcılar (Concurrent Users)

Tanım: Aynı anda aktif kullanıcı sayısı

Farkı anlamak önemli:

Toplam Kullanıcılar (Total Users): 10.000
Aktif Kullanıcılar (Active Users): 3.000 (şu an çevrimiçi)
Eşzamanlı Kullanıcılar (Concurrent Users): 500 (ŞU AN istek yapıyor)

Hesaplama formülü:

Eşzamanlı Kullanıcılar = (Toplam Kullanıcılar × Kullanım Yüzdesi) / Düşünme Süresi (Think Time)

5. Apdex Skoru

Tanım: Uygulama Performans İndeksi (0 ile 1 arası)

Formül:

Apdex = (Memnun + (Tolere Eden / 2)) / Toplam Örnekler

Burada:
- Memnun: Response Time ≤ T
- Tolere Eden: T < Response Time ≤ 4T
- Hayal Kırıklığına Uğramış: Response Time > 4T

Örnek:

T = 500ms (hedef)

100 istek:
- 70 tanesi 500ms altında (Memnun)
- 20 tanesi 500ms-2000ms arası (Tolere Eden)
- 10 tanesi 2000ms üstünde (Hayal Kırıklığına Uğramış)

Apdex = (70 + 20/2) / 100 = 0.8 (İyi)

Derecelendirme:

  • 1.0 - 0.94 = Mükemmel
  • 0.93 - 0.85 = İyi
  • 0.84 - 0.70 = Orta
  • 0.69 - 0.50 = Kötü
  • < 0.50 = Kabul Edilemez

🔨 JMeter: Endüstri Standardı (Industry Standard)

Neden JMeter?

Avantajlar (Advantages):

  • ✅ Endüstri standardı (Industry Standard) - 20+ yıl
  • ✅ Geniş topluluk (Large Community)
  • ✅ Test oluşturma için GUI
  • ✅ Çoklu protokol desteği (Multi-protocol Support)
  • ✅ Ücretsiz ve açık kaynak (Free and Open Source)

Dezavantajlar (Disadvantages):

  • ❌ Java tabanlı - ağır (Heavy)
  • ❌ GUI, CI/CD için uygun değil
  • ❌ Dik öğrenme eğrisi (Steep Learning Curve)

Temel Kurulum

# JMeter'ı İndirin
wget https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.tgz
tar -xzf apache-jmeter-5.6.3.tgz
cd apache-jmeter-5.6.3/bin

# GUI'yi Çalıştırın
./jmeter

# CLI'da Çalıştırın (CI/CD için)
./jmeter -n -t test-plan.jmx -l results.jtl -e -o report/

Basit Test Oluşturma

Test Plan Yapısı:

Test Plan
├── Thread Group (Kullanıcılar)
│   ├── HTTP Request (API çağrısı)
│   ├── HTTP Header Manager
│   ├── JSON Assertions
│   └── Response Time Assertions
├── Listeners (Sonuçlar)
│   ├── View Results Tree
│   ├── Summary Report
│   └── Aggregate Report

Örnek: API Load Test

Thread Group Ayarları:

Number of Threads: 100
Ramp-up Period: 60 saniye
Loop Count: 10

HTTP Request:

Server: api.example.com
Port: 443
Protocol: https
Method: GET
Path: /api/v1/products

Assertions:

// Response Code
Response Code: 200

// Response Time
Response Time: <= 500ms

// JSON Body
$.data.length > 0

⚡ K6: Modern JavaScript Yaklaşımı (Modern JavaScript Approach)

Neden K6?

Avantajlar (Advantages):

  • ✅ JavaScript - QA için tanıdık sözdizimi (Familiar Syntax)
  • ✅ CLI-first - CI/CD için mükemmel (Great for CI/CD)
  • ✅ Hafif ve hızlı (Lightweight and Fast)
  • ✅ Yerleşik JSON çıktıları (Built-in JSON Output)
  • ✅ Bulut entegrasyonu (Cloud Integration)

Dezavantajlar (Disadvantages):

  • ❌ GUI yok (No GUI)
  • ❌ JMeter’dan daha az protokol desteği
  • ❌ Görece yeni - 2017

Kurulum

# macOS
brew install k6

# Linux
sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6

# Windows
choco install k6

# Docker
docker pull grafana/k6

Temel Test

simple-test.js:

import http from 'k6/http';
import { sleep, check } from 'k6';

export const options = {
    vus: 10,        // Sanal Kullanıcılar
    duration: '30s', // Test süresi
};

export default function() {
    const res = http.get('https://api.example.com/products');
    
    check(res, {
        'status is 200': (r) => r.status === 200,
        'response time < 200ms': (r) => r.timings.duration < 200,
    });
    
    sleep(1);
}

Çalıştır:

k6 run simple-test.js

İleri Seviye: Senaryolar

multi-scenario.js:

import http from 'k6/http';
import { sleep } from 'k6';

export const options = {
    scenarios: {
        // Senaryo 1: Ürünleri gezin
        browse: {
            executor: 'constant-vus',
            vus: 50,
            duration: '5m',
            exec: 'browseProducts',
        },
        
        // Senaryo 2: Arama
        search: {
            executor: 'ramping-vus',
            startVUs: 0,
            stages: [
                { duration: '2m', target: 20 },
                { duration: '5m', target: 20 },
                { duration: '2m', target: 0 },
            ],
            exec: 'searchProducts',
        },
        
        // Senaryo 3: Ödeme (ağır işlem)
        checkout: {
            executor: 'constant-arrival-rate',
            rate: 10,
            timeUnit: '1s',
            duration: '5m',
            preAllocatedVUs: 50,
            exec: 'checkoutFlow',
        },
    },
    
    thresholds: {
        'http_req_duration{scenario:browse}': ['p(95)<500'],
        'http_req_duration{scenario:search}': ['p(95)<1000'],
        'http_req_duration{scenario:checkout}': ['p(95)<2000'],
        'http_req_failed': ['rate<0.01'],
    },
};

export function browseProducts() {
    http.get('https://api.example.com/products');
    sleep(1);
}

export function searchProducts() {
    http.get('https://api.example.com/products/search?q=laptop');
    sleep(2);
}

export function checkoutFlow() {
    // Giriş
    const loginRes = http.post('https://api.example.com/auth/login', {
        email: 'test@example.com',
        password: 'pass123',
    });
    
    const token = loginRes.json('token');
    
    // Sepete ekle
    http.post('https://api.example.com/cart', 
        JSON.stringify({ productId: 123, quantity: 1 }),
        { headers: { 'Authorization': `Bearer ${token}` } }
    );
    
    // Ödeme
    http.post('https://api.example.com/checkout',
        JSON.stringify({ paymentMethod: 'card' }),
        { headers: { 'Authorization': `Bearer ${token}` } }
    );
    
    sleep(3);
}

Özel Metrikler

import http from 'k6/http';
import { Trend, Counter } from 'k6/metrics';

// Özel metrikler
const loginDuration = new Trend('login_duration');
const checkoutErrors = new Counter('checkout_errors');

export default function() {
    const start = Date.now();
    const res = http.post('https://api.example.com/login', {...});
    const duration = Date.now() - start;
    
    loginDuration.add(duration);
    
    if (res.status !== 200) {
        checkoutErrors.add(1);
    }
}

CI/CD’de K6

GitHub Actions:

name: Performance Tests

on: [push]

jobs:
  k6-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run K6 test
        uses: grafana/k6-action@v0.3.1
        with:
          filename: performance-tests/load-test.js
          flags: --out json=results.json
      
      - name: Upload results
        uses: actions/upload-artifact@v3
        with:
          name: k6-results
          path: results.json

🎯 Gatling: Scala Gücü (The Power of Scala)

Neden Gatling?

Avantajlar (Advantages):

  • ✅ Çok yüksek performans (Very High Performance)
  • ✅ Mükemmel raporlar (Excellent Reports) - sektörün en iyisi
  • ✅ HTTP/WebSocket için harika (Great for HTTP/WebSocket)
  • ✅ Yeniden kullanılabilir simülasyon kodu (Reusable Simulation Code)

Dezavantajlar (Disadvantages):

  • ❌ Scala - programlama geçmişi olmayan QA için zor (Difficult for non-programmers)
  • ❌ Daha az protokol desteği (Fewer Protocols)
  • ❌ JMeter’dan daha küçük topluluk (Smaller Community)

Kurulum

# İndir
wget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.10.3/gatling-charts-highcharts-bundle-3.10.3-bundle.zip
unzip gatling-charts-highcharts-bundle-3.10.3-bundle.zip
cd gatling-charts-highcharts-bundle-3.10.3

# Recorder'ı çalıştır (senaryo kaydetmek için)
./bin/recorder.sh

# Simülasyonu çalıştır
./bin/gatling.sh

Temel Simülasyon

BasicSimulation.scala:

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class BasicSimulation extends Simulation {
  
  val httpProtocol = http
    .baseUrl("https://api.example.com")
    .acceptHeader("application/json")
    .userAgentHeader("Gatling Performance Test")
  
  val scn = scenario("Basic Load Test")
    .exec(
      http("Get Products")
        .get("/api/products")
        .check(status.is(200))
        .check(jsonPath("$.data").exists)
        .check(responseTimeInMillis.lte(500))
    )
    .pause(1)
  
  setUp(
    scn.inject(
      rampUsers(100).during(60.seconds) // 60 saniyede 100 kullanıcı
    ).protocols(httpProtocol)
  ).assertions(
    global.responseTime.max.lt(5000),
    global.successfulRequests.percent.gt(95)
  )
}

🔍 Gerçek Dünya Senaryoları (Real-World Scenarios)

Senaryo 1: E-ticaret Kara Cuma (Black Friday)

Gereksinimler (Requirements):

  • Normal: 5.000 eşzamanlı kullanıcı (Concurrent Users)
  • Kara Cuma: 100.000 eşzamanlı kullanıcı
  • 0:00’da ani yük artışı (Spike) bekleniyor

Test Stratejisi (Testing Strategy):

// K6 Black Friday Simülasyonu
export const options = {
    stages: [
        // Gece yarısı öncesi: normal trafik
        { duration: '30m', target: 5000 },
        
        // Gece yarısı spike!
        { duration: '2m', target: 100000 },
        
        // Tepe noktasını tut
        { duration: '1h', target: 100000 },
        
        // Kademeli düşüş
        { duration: '30m', target: 50000 },
        { duration: '1h', target: 20000 },
        { duration: '2h', target: 5000 },
    ],
    
    thresholds: {
        'http_req_duration{critical:yes}': ['p(99)<1000'], // Kritik sayfalar
        'http_req_duration{critical:no}': ['p(99)<5000'],  // Kritik olmayanlar
        'http_req_failed': ['rate<0.1'],                   // %0.1 hata oranı OK
    },
};

Senaryo 2: API Rate Limiting

Gereksinimler:

  • API limiti: kullanıcı başına dakikada 1000 istek
  • Rate limiting’in çalıştığını doğrulama gerekiyor
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
    scenarios: {
        // Normal kullanım - başarılı olmalı
        normal: {
            executor: 'constant-arrival-rate',
            rate: 900,                    // 900 req/dak (limitin altında)
            timeUnit: '1m',
            duration: '5m',
            preAllocatedVUs: 50,
            exec: 'normalRequest',
        },
        
        // Aşırı kullanım - rate limited olmalı
        excessive: {
            executor: 'constant-arrival-rate',
            rate: 1500,                   // 1500 req/dak (limitin üstünde!)
            timeUnit: '1m',
            duration: '5m',
            preAllocatedVUs: 100,
            exec: 'excessiveRequest',
        },
    },
};

export function normalRequest() {
    const res = http.get('https://api.example.com/data');
    check(res, {
        'normal request succeeds': (r) => r.status === 200,
    });
}

export function excessiveRequest() {
    const res = http.get('https://api.example.com/data');
    check(res, {
        'excessive request rate limited': (r) => r.status === 429,
        'has retry-after header': (r) => r.headers['Retry-After'] !== undefined,
    });
}

📈 Sonuç Analizi ve Darboğaz Bulma (Bottleneck Analysis)

Performans Test Raporlarını Okuma (Reading Performance Test Reports)

Analiz edilecek temel bölümler (Key Sections):

  1. Özet İstatistikler (Summary Statistics)
İstekler (Requests): 10.000
Süre (Duration): 5 dakika
Başarı Oranı (Success Rate): %98.5
Ort. Yanıt Süresi (Avg Response Time): 450ms
p95 Yanıt Süresi: 850ms
p99 Yanıt Süresi: 2.150ms
Max Yanıt Süresi: 5.200ms

Yorumlama (Interpretation):

  • ✅ %98.5 başarı oranı (iyi, > %99 ideal)
  • ✅ Ortalama 450ms (çoğu API için kabul edilebilir)
  • ⚠️ p99 2.15s (kullanıcıların %1.5’i > 2s bekliyor)
  • ❌ Max 5.2s (araştırılmalı!)
  1. Yanıt Süresi Dağılımı (Response Time Distribution)
0-100ms:    %15 (1.500 istek)
100-300ms:  %45 (4.500 istek)
300-500ms:  %25 (2.500 istek)
500-1000ms: %10 (1.000 istek)
1000-2000ms: %3 (300 istek)
2000ms+:     %2 (200 istek) ← Araştır!
  1. Hata Dağılımı (Error Distribution)
200 OK:        9.850 (%98.5)
400 Bad Request:  50 (%0.5)
429 Rate Limit:   75 (%0.75)
500 Server Error: 20 (%0.2) ← Kritik!
504 Timeout:       5 (%0.05) ← Kritik!

Yaygın Darboğaz Desenleri (Common Bottleneck Patterns)

Desen 1: Kademeli Performans Düşüşü (Gradual Degradation)

Belirti:

Dakika 1: p95 = 300ms
Dakika 2: p95 = 350ms
Dakika 3: p95 = 450ms
Dakika 4: p95 = 650ms
Dakika 5: p95 = 950ms

Olası Nedenler:

  • Bellek sızıntısı
  • Bağlantı havuzu serbest bırakılmıyor
  • Önbellek temizlenmiyor
  • Veritabanı sorgu planları bozuluyor

Desen 2: Ani Hata Artışı

Belirti:

Dakika 1-3: %0 hata
Dakika 4: %15 hata (500 Internal Server Error)
Dakika 5: %35 hata

Olası Nedenler:

  • Thread havuzu tükendi
  • Veritabanı bağlantı havuzu doldu
  • Bellek sınırları aşıldı
  • Circuit breaker açıldı

Desen 3: İki Modlu Response Time

Belirti:

İsteklerin %80'i: 100-200ms
İsteklerin %20'si: 5000-6000ms

Kademeli dağılım yok!

Olası Nedenler:

  • Cache hit vs cache miss
  • Read replica gecikmesi
  • Cold start (serverless)
  • DNS sorunları

✅ En İyi Uygulamalar (Best Practices)

1. Küçük Başlayın, Ölçeklendirin (Start Small, Scale Up)

Yanlış yaklaşım (Wrong Approach):

// Bunu yapmayın!
export const options = {
    vus: 10000,          // Çok fazla çok hızlı
    duration: '10s',
};

Doğru yaklaşım:

// Bunu yapın!
export const options = {
    stages: [
        { duration: '2m', target: 10 },    // Küçük başla
        { duration: '5m', target: 50 },    // Kademeli artış
        { duration: '10m', target: 100 },  // Hedef yük
        { duration: '5m', target: 200 },   // Zorla
        { duration: '5m', target: 0 },     // Ramp down
    ],
};

2. Gerçekçi Düşünme Süresi Kullanın

Yanlış:

export default function() {
    http.get('/api/products');
    http.post('/api/cart', {...});
    http.post('/api/checkout', {...});
    // Duraklamalar yok - gerçekçi değil!
}

Doğru:

export default function() {
    http.get('/api/products');
    sleep(randomBetween(2, 5));  // Kullanıcı ürünleri okuyor
    
    http.post('/api/cart', {...});
    sleep(randomBetween(1, 3));  // Kullanıcı sepeti inceliyor
    
    http.post('/api/checkout', {...});
    sleep(randomBetween(5, 10)); // Kullanıcı ödeme formunu dolduruyor
}

function randomBetween(min, max) {
    return Math.random() * (max - min) + min;
}

3. Sistem Kaynaklarını İzleyin

Testler sırasında izleyin:

# CPU kullanımı
top

# Bellek
free -h

# Disk I/O
iostat -x 1

# Ağ
iftop

# Uygulama logları
tail -f /var/log/application.log

# Veritabanı bağlantıları
watch 'psql -c "SELECT count(*) FROM pg_stat_activity;"'

4. Production Benzeri Ortamda Test Edin

Kontrol Listesi:

  • Aynı sunucu özellikleri (CPU, RAM, disk)
  • Aynı ağ gecikmesi
  • Aynı veritabanı boyutu
  • Aynı harici bağımlılıklar
  • Aynı yük dengeleyici yapılandırması
  • Aynı CDN/önbellekleme katmanı

❓ Mülakat Soruları ve Cevapları (Interview Questions and Answers)

Soru 1: “Yük Testi (Load Testing) ile Stres Testi (Stress Testing) arasındaki fark nedir?”

İyi Cevap (Good Answer):

“Yük Testi (Load Testing), sistemin beklenen yük koşullarında iyi performans gösterip göstermediğini doğrular — örneğin e-ticaret sitemizin normal işlemlerde 10.000 eşzamanlı kullanıcıyı kaldırıp kaldırmadığını test etmek gibi. Stres Testi (Stress Testing), kırılma noktasını bulmak için sistemi sınırlarının ötesine iter — sistem başarısız olana kadar yükü artırmaya devam ederiz, sonra nasıl bozulduğunu ve toparlandığını gözlemleriz. Yük testi doğrulama içindir; stres testi sınırları bulmak içindir.”

Soru 2: “Performans testi (Performance Testing) sırasında hangi metrikleri izlersiniz?”

İyi Cevap (Good Answer):

“Beş temel metriğe odaklanıyorum: Yanıt Süresi (Response Time) — özellikle p95 ve p99 yüzdelikler, sadece ortalama değil; İş Hacmi (Throughput) — saniyede istek; Hata Oranı (Error Rate) — %1’in altında olmalı; Kaynak Kullanımı (Resource Utilization) — CPU, bellek, disk I/O; ve Eşzamanlı Kullanıcılar (Concurrent Users). Ayrıca ödeme tamamlama süresi veya arama gecikmesi gibi özel iş metriklerini de izliyorum.”

Soru 3: “Performans testlerini (Performance Tests) CI/CD’ye nasıl entegre edersiniz?”

İyi Cevap (Good Answer):

“Katmanlı bir yaklaşım kullanıyorum: Her PR’da bariz gerileyişleri (Regressions) yakalamak için hızlı duman testleri (Smoke Tests), gerçekçi senaryolarla gece yük testleri (Load Tests), bellek sızıntıları (Memory Leaks) için haftalık soak testler. Otomatik eşikler (Thresholds) ayarlıyorum — p95 yanıt süresi 500ms’yi aşarsa veya hata oranı %1’in üzerine çıkarsa, pipeline başarısız olur. Sonuçlar Slack’e gönderilir ve tarihsel karşılaştırma için saklanır.”

Soru 4: “Yük testi (Load Test) sırasında yanıt sürelerinin (Response Times) kademeli olarak arttığını fark ettiniz. Neyi araştırırsınız?”

İyi Cevap (Good Answer):

“Kademeli bozulma (Gradual Degradation) genellikle kaynak sızıntılarına (Resource Leaks) işaret eder. Şunları kontrol ederdim: bellek kullanımını sızıntılar (Memory Leaks) için, veritabanı bağlantı havuzunu (Connection Pool) bağlantıların serbest bırakılıp bırakılmadığı için, sorgu yürütme sürelerini bozulan planlar için ve uygulama günlüklerini (Logs) uyarılar için. Ayrıca önbelleklemenin (Caching) çalışıp çalışmadığını da doğrulardım — belki önbellek doluyor veya eviction bozuk.”


🎯 Temel Çıkarımlar (Key Takeaways)

Performans Testi Türleri Özeti (Performance Testing Types Summary)

Tür (Type)Amaç (Purpose)Süre (Duration)Yük Deseni (Load Pattern)
Yük (Load)Beklenen yükü doğrulama10-60 dakSabit (Steady)
Stres (Stress)Kırılma noktasını bulma30-60 dakArtan (Increasing)
Ani Yük (Spike)Ani artışları yönetme5-15 dakAni tepeler (Sudden Peaks)
Dayanıklılık (Soak)Bellek sızıntılarını bulma4-24 saatSabit (Steady)

Araç Karşılaştırması (Tool Comparison)

Araç (Tool)En İyi (Best For)Öğrenme Eğrisi (Learning Curve)CI/CD Hazır (CI/CD Ready)
JMeterKarmaşık protokollerOrta (Medium)⚠️ CLI gerekli
K6Modern web uygulamalarıKolay (Easy)✅ Doğal
GatlingYüksek performansZor (Hard)✅ Doğal

📍 Sırada Ne Var?

Yarın - FİNAL!

🍎 Makale 8: Apple’da Hayalinizdeki İşi Elde Etmek

  • Apple iş gereksinimlerinin analizi
  • FAANG için özgeçmiş optimizasyonu
  • GitHub portföy rehberi
  • Mülakat süreci (4 tur)
  • Maaş müzakeresi ($140K-$200K+)
  • Apple’da ilk 90 gün

Bu, öğrendiğimiz her şeyin doruk noktası!


💡 Son Tavsiye

Performance testing tek seferlik bir aktivite değildir:

Hafta 1: Temel testler
Hafta 2-4: Geliştirme
Hafta 4: Performance regresyon kontrolü
Hafta 5: Load test
Hafta 6: Stress test
Hafta 8: Soak test
Production: Sürekli izleme

Geliştirme döngünüzün bir parçası yapın, sonradan düşünülen bir şey değil!


Bu makale faydalı oldu mu? 👏

Sorularınız mı var? Yorumlarda sormaktan çekinmeyin!


Yazar: AAnnayev — Senior SDET

Etiketler: #PerformanceTesting #LoadTesting #JMeter #K6 #Gatling #QA #SDET