İçeriğe geç
academia.sh

Ders 23 / 27

Uçtan Uca Testler

Gerçek tarayıcıda çalışan testlerin kapsadığı risk, akışın durum makinesi olarak modellenmesi ve doğrulanması, bekleme ile veri yalıtımı kararları ve bu testlerin neden az sayıda tutulduğu.

İçindekiler

Bileşen testi bileşenin kendi ağacıyla sınırlıdır. Ölçüm listesinin sunucudan gelmesi, adresin güncellenmesi, formun gönderilmesi ve listenin yenilenmesi o sınırın dışında kalır. Parçalar tek tek doğru çalışırken akışın bir yerinde kopması olağandır: yapı çıktısında bir modül düşmüştür, yönlendirme kuralı değişmiştir, sunucunun döndürdüğü alan adı istemcinin beklediğinden farklıdır.

Uçtan uca test bu boşluğu kapatır. Uygulamayı gerçek bir tarayıcıda başlatır, gerçek girdi olayları gönderir ve kullanıcının gördüğünü doğrular.

Kapsanan Risk

Testi bir tarayıcı sürücüsü yürütür: tarayıcıyı denetim altında başlatan, adrese giden, tıklama ve tuş olayı üreten, belgeyi ve erişilebilirlik ağacını okuyabilen bir program. Sürücünün ürettiği olaylar uygulamanın gördüğü açıdan gerçek kullanıcı olaylarıdır.

Bu düzenek, başka hiçbir test türünün göremediği bir risk kümesini kapsar. Yapı çıktısının gerçekten çalışır olması — geliştirme kipinde geçen bir kod, üretim yapısında ağaç sarsmayla düşmüş bir dışa aktarım yüzünden kırılabilir. Yönlendirme ve derin bağlantı. Sunucu ile istemci arasındaki veri sözleşmesi. Oturum ve çerez davranışı. Güvenlik başlıklarının gerçekten uygulanması: İçerik Güvenlik Politikası dersinde yazılan politika, ancak gerçek bir tarayıcı betiği reddettiğinde sınanmış olur.

Bedeli de aynı ölçüde büyüktür. Bir uçtan uca test, bir bileşen testinin yüzlerce katı sürer. Başarısız olduğunda hangi katmanın kusurlu olduğunu söylemez; tanı için ayrı bir çalışma gerekir. Ve dış dünyaya bağlı olduğu için kırılganlığa açıktır — beşinci ders bunun nedenlerini sayacaktır.

Akışı Önce Modellemek

Uçtan uca test yazmanın verimli yolu, akışı adım listesi olarak değil durum makinesi olarak düşünmektir. Web’in Temelleri ve HTML kursunda ayrıştırıcı için kullanılan aynı kavram burada arayüz akışına uygulanır: sonlu sayıda durum, durumlar arası olaylarla tanımlı geçişler.

Kuzey Yamaç arayüzünün ölçüm girişi akışı şu durumları taşır: sayfa boşta, liste yükleniyor, liste hazır, form açık, gönderiliyor, liste hatası.

// akis.mjs — olcum girisi akisinin durum makinesi
export const GECISLER = {
  bosta: { 'sayfa-acildi': 'listeYukleniyor' },
  listeYukleniyor: { 'liste-geldi': 'listeHazir', 'istek-basarisiz': 'listeHatasi' },
  listeHazir: { 'yeni-olcum': 'formAcik', 'suzgec-degisti': 'listeYukleniyor' },
  formAcik: { 'gonder': 'gonderiliyor', 'iptal': 'listeHazir' },
  gonderiliyor: { 'kayit-alindi': 'listeYukleniyor', 'dogrulama-hatasi': 'formAcik' },
  listeHatasi: {},
};

export function senaryoyuYurut(gecisler, baslangic, adimlar) {
  let durum = baslangic;
  const izleme = [durum];
  for (const adim of adimlar) {
    const sonraki = gecisler[durum]?.[adim];
    if (sonraki === undefined) {
      throw new Error(`'${durum}' durumunda '${adim}' adimi tanimli degil`);
    }
    durum = sonraki;
    izleme.push(durum);
  }
  return { durum, izleme };
}

export function ulasilabilir(gecisler, baslangic) {
  const gorulen = new Set([baslangic]);
  const kuyruk = [baslangic];
  while (kuyruk.length > 0) {
    const su = kuyruk.shift();
    for (const hedef of Object.values(gecisler[su] ?? {})) {
      if (gorulen.has(hedef)) continue;
      gorulen.add(hedef);
      kuyruk.push(hedef);
    }
  }
  return gorulen;
}

export function kurtarilamayanlar(gecisler, guvenliDurum) {
  return Object.keys(gecisler).filter(
    (d) => d !== guvenliDurum && !ulasilabilir(gecisler, d).has(guvenliDurum),
  );
}

ulasilabilir fonksiyonu, Veri Yapıları kursundaki enine aramanın doğrudan uygulanmasıdır: geçiş tablosu bir çizgedir, durumlar düğüm, olaylar kenardır.

Model kurulduğunda iki tür doğrulama yazılabilir. Birincisi senaryo doğrulamasıdır: belirli bir adım dizisi beklenen durum izini üretmeli. İkincisi model doğrulamasıdır: tablonun kendisi hakkında her senaryoda doğru kalması gereken önermeler.

// akis.test.mjs
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { GECISLER, senaryoyuYurut, ulasilabilir, kurtarilamayanlar } from './akis.mjs';

test('mutlu yol: olcum girilir ve liste yenilenir', () => {
  const { izleme } = senaryoyuYurut(GECISLER, 'bosta', [
    'sayfa-acildi', 'liste-geldi', 'yeni-olcum', 'gonder', 'kayit-alindi', 'liste-geldi',
  ]);
  assert.deepEqual(izleme, [
    'bosta', 'listeYukleniyor', 'listeHazir', 'formAcik',
    'gonderiliyor', 'listeYukleniyor', 'listeHazir',
  ]);
});

test('gecersiz olcum formda kalir', () => {
  const { durum } = senaryoyuYurut(GECISLER, 'bosta', [
    'sayfa-acildi', 'liste-geldi', 'yeni-olcum', 'gonder', 'dogrulama-hatasi',
  ]);
  assert.equal(durum, 'formAcik');
});

test('tanimsiz adim acik hatayla durur', () => {
  assert.throws(
    () => senaryoyuYurut(GECISLER, 'bosta', ['sayfa-acildi', 'gonder']),
    /'listeYukleniyor' durumunda 'gonder' adimi tanimli degil/,
  );
});

test('her durum baslangictan ulasilabilir', () => {
  const gorulen = ulasilabilir(GECISLER, 'bosta');
  assert.deepEqual([...gorulen].sort(), Object.keys(GECISLER).sort());
});

test('her durumdan listeHazir durumuna donulebilir', () => {
  assert.deepEqual(kurtarilamayanlar(GECISLER, 'listeHazir'), []);
});
node --test akis.test.mjs

Aşağıdaki çıktıdan sayaç satırlarının bir bölümü ve başarısızlık gövdesindeki yığıt satırları çıkarılmıştır.

✔ mutlu yol: olcum girilir ve liste yenilenir (0.529625ms)
✔ gecersiz olcum formda kalir (0.05425ms)
✔ tanimsiz adim acik hatayla durur (0.130791ms)
✔ her durum baslangictan ulasilabilir (0.068625ms)
✖ her durumdan listeHazir durumuna donulebilir (0.719375ms)
ℹ tests 5
ℹ pass 4
ℹ fail 1
✖ her durumdan listeHazir durumuna donulebilir
  AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
  + actual - expected
  + [
  +   'listeHatasi'
  + ]
  - []

Model, henüz tek satır arayüz kodu çalıştırılmadan bir tasarım boşluğu buldu: liste isteği başarısız olduğunda ulaşılan durumdan geri dönüş yoktur. Kullanıcı hata ekranında sıkışır. Düzeltme geçiş tablosuna bir kenar eklemektir:

// akis.mjs — GECISLER tablosunun duzeltilmis hali; yalnizca son satir degisti
export const GECISLER = {
  bosta: { 'sayfa-acildi': 'listeYukleniyor' },
  listeYukleniyor: { 'liste-geldi': 'listeHazir', 'istek-basarisiz': 'listeHatasi' },
  listeHazir: { 'yeni-olcum': 'formAcik', 'suzgec-degisti': 'listeYukleniyor' },
  formAcik: { 'gonder': 'gonderiliyor', 'iptal': 'listeHazir' },
  gonderiliyor: { 'kayit-alindi': 'listeYukleniyor', 'dogrulama-hatasi': 'formAcik' },
  listeHatasi: { 'yeniden-dene': 'listeYukleniyor' },
};
✔ mutlu yol: olcum girilir ve liste yenilenir (0.539167ms)
✔ gecersiz olcum formda kalir (0.060417ms)
✔ tanimsiz adim acik hatayla durur (0.140833ms)
✔ her durum baslangictan ulasilabilir (0.073041ms)
✔ her durumdan listeHazir durumuna donulebilir (0.3595ms)
ℹ tests 5
ℹ suites 0
ℹ pass 5
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 35.845583

Modelin değeri iki yönlüdür. Test yazarken hangi senaryoların gerçekten farklı olduğunu gösterir — mutlu yol ile doğrulama hatası yolu farklı geçişler kullanır, iki ayrı testtir. Ve tabloda eksik kalan geçiş, arayüzde eksik kalan bir düğmedir.

Adımlar, Bekleme ve Veri

Tarayıcıda çalışan testin her adımı iki parçadan oluşur: bir kullanıcı eylemi ve o eylemin gözlemlenebilir sonucu. Sonuç doğrulanmadan bir sonraki eyleme geçilirse test, uygulamadan hızlı çalışmaya başlar ve zamanlamaya bağımlı hâle gelir.

Bekleme bu yüzden sabit süreyle yapılmaz. Sabit bekleme iki türlü yanlıştır: yavaş bir koşumda yetmez, hızlı bir koşumda boşa harcanır. Doğru biçim koşula göre beklemedir — “ölçüm tablosunda en az bir satır görünene kadar, en çok şu kadar süre bekle”. Koşulun kendisi önceki dersteki ölçütle kurulur: role ve ada göre bulunan bir öge.

Test verisinin yalıtımı ikinci kuraldır. Paylaşılan bir hesabın üzerinde çalışan iki test birbirinin verisini görür; biri ölçüm eklerken diğerinin sayım doğrulaması bozulur. Her koşum kendi istasyonunu ve kendi ölçümlerini kurar, sonunda temizler.

Giriş akışı ayrı bir karardır. Kimlik doğrulamayı her testte arayüzden geçirmek her teste birkaç saniye ekler ve giriş ekranı değiştiğinde tüm paketi düşürür. Oturumu doğrudan kurmak — belirteci ya da çerezi arayüzü kullanmadan yerleştirmek — bu maliyeti kaldırır. Giriş akışının kendisi ayrıca ve bir kez sınanır.

Ağ tarafında iki seçenek vardır. Gerçek arka uca bağlanmak sözleşme uyuşmazlığını yakalar ama yavaştır ve arka ucun durumuna bağımlıdır. Yanıtları sabitlemek testi hızlı ve belirlenimci yapar ama sözleşme kaymasını göremez. Yaygın çözüm ikisini bölmektir: birkaç akış gerçek arka uçla, geri kalanı sabitlenmiş yanıtlarla.

Ne Kadar Uçtan Uca

Test paketinin şekli bir bütçe sorunudur. Birim ve bileşen testleri saniyeler içinde geri bildirim verir ve kusurun yerini gösterir; uçtan uca testler dakikalar sürer ve yalnız “bir yerde bozuldu” der. Bu yüzden çoğunluk alta, azınlık üste konur.

Seçim ölçütü kapsam yüzdesi değil, başarısızlığın bedelidir. Kuzey Yamaç arayüzünde üç akış bu ölçütü karşılar: ölçüm listesinin yüklenip süzülmesi, yeni ölçümün girilip kaydedilmesi ve liste isteği başarısız olduğunda kurtarma. Kalan her şey daha ucuz bir katmanda sınanabiliyorsa orada sınanır.

Özet

  • Uçtan uca test yapı çıktısını, yönlendirmeyi, veri sözleşmesini, oturumu ve güvenlik başlıklarını birlikte kapsar; hiçbir alt katman bu kümeyi göremez.
  • Akışı durum makinesi olarak modellemek hangi senaryoların farklı olduğunu gösterir; geçiş tablosu üzerinde enine aramayla ulaşılabilirlik ve kurtarılabilirlik doğrulanabilir.
  • Model, hata durumundan geri dönüş bulunmadığını arayüz kodu çalıştırılmadan bildirdi; eksik geçiş arayüzde eksik bir düğmeye karşılık gelir.
  • Her adım bir eylem ve gözlemlenebilir bir sonuçtan oluşur; bekleme sabit süreyle değil koşulla yapılır.
  • Her koşum kendi verisini kurar, oturumu arayüzden geçmeden kurar ve akışların bir bölümünü gerçek arka uçla, kalanını sabitlenmiş yanıtlarla sınar.

Sonraki Adım

Uçtan uca test akışın işlediğini doğrular: satır göründü, kayıt alındı, hata ekranından dönüldü. Doğrulamadığı şey, o satırların nasıl göründüğüdür. Bir biçem kuralı yanlış kapsayıcıya uygulandığında, bir aralık değeri iki katına çıktığında ya da bir düğme görünmez hâle geldiğinde akış testleri geçmeyi sürdürür — çünkü öge ağaçta durur ve tıklanabilir. Sonraki ders bu boşluğu kapatan yöntemi, iki görüntüyü piksel piksel karşılaştıran gerileme testini ele alır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat