---
title: 'Erişilebilirlik Testi'
source: 'https://academia.sh/tr/kurslar/islevsel-olmayan-test/erisilebilirlik-testi'
course: 'İşlevsel Olmayan Test'
language: tr
updated: '2026-08-17T18:10:52+00:00'
license: 'CC BY-SA 4.0'
---

# Erişilebilirlik Testi

Otomatik denetimin kapsama payının ölçülmesi: ölçütlerin karar kaynağına göre ayrılması, küçük bir öge ağacı üzerinde gerçekten koşan bir denetçinin yanlış alarm ve kaçırma sayıları ve eşiği yükseltmenin hiçbir kazanç getirmediği bir denetimde elle doğrulamanın zorunlu alanı.

Dört ders sistemi kötüye kullanan bir istemciyi varsaydı. Aynı sorunun bir başka yüzü,
sistemi **kullanamayan** bir okuyucudur: ekranı görmeyen, fareyi kullanmayan ya da metni
büyüterek okuyan biri için ödünç ekranı çalışıyor mu?

Bu sorunun ölçütleri, arayüz tarafındaki karşılıkları ve otomatik denetleyicinin kural
sınıfları Frontend Kalitesi kursunda kuruldu; burada tekrarlanmaz. Bu dersin sorusu bir
test sorusudur ve **erişilebilirlik denetiminin** kendisini ölçer: **kapsama payı**.
Ölçüt kümesinin kaçı bir programa yaptırılabilir, kaçı
elle doğrulanmak zorundadır ve otomatik denetimin kendi yanlış alarm ile kaçırma oranı
nedir? Ölçüm, tarayıcı çıktısı üzerinden değil, küçük bir belge modeli üzerinde yapılacak.

## Belge Modeli ve Bilinen Kusurlar

Ödünç ekranının öge ağacı sekiz kusur taşıyor; kusurların yeri elle doğrulanmıştır.

```js
// belge.mjs — odunc ekraninin oge agaci ve elle dogrulanmis kusur listesi
export const BELGE = {
  tur: "sayfa", baslik: "Odunc Islemleri", dil: null, cocuk: [
    { tur: "bolum", ad: "gezinme", cocuk: [
      { tur: "baglanti", hedef: "/katalog", metin: "Katalog" },
      { tur: "baglanti", hedef: "/odunc", metin: "Odunc" },
    ] },
    { tur: "bolum", ad: "ana", cocuk: [
      { tur: "baslik", duzey: 1, metin: "Odunc Islemleri" },
      { tur: "baslik", duzey: 3, metin: "Rafta Bekleyenler" },
      { tur: "liste", cocuk: [
        { tur: "satir", cocuk: [
          { tur: "metin", metin: "Kum Saati" },
          { tur: "eylem", kimlik: "al-1", metin: "", simge: "sepet", boyut: 40, odaklanabilir: true },
        ] },
        { tur: "satir", cocuk: [
          { tur: "metin", metin: "Rafta Kalan" },
          { tur: "eylem", kimlik: "al-2", metin: "Al", boyut: 40, odaklanabilir: true },
        ] },
      ] },
      { tur: "alan", kimlik: "uye-no", tip: "metin", etiket: null },
      { tur: "metin", metin: "Ceza: 30", renk: "#8a8a8a", zemin: "#ffffff" },
      { tur: "eylem", kimlik: "gecmis", metin: "Gecmis", boyut: 40, odaklanabilir: true,
        edilgen: true, renk: "#9b9b9b", zemin: "#ffffff" },
    ] },
  ],
};

// Elle dogrulanmis kusurlar: olcut kodu, yer ve kisa gerekce.
// Edilgen "gecmis" eylemi karsitlik esiginden muaftir; listede yoktur.
export const GERCEK = [
  ["D1", "al-1", "sepet simgeli eylemin adi bos"],
  ["D2", "uye-no", "uye numarasi alaninin etiketi yok"],
  ["D3", "baslik 3", "birinci duzeyden ucuncu duzeye atlaniyor"],
  ["D5", "sayfa", "belge dil bildirimi tasimiyor"],
  ["D7", "Ceza: 30", "ceza metninin karsitligi esigin altinda"],
  ["D9", "-", "gecikme yalniz renk degisimiyle bildiriliyor"],
  ["D10", "-", "iki ayri islemi yapan eylem ayni adi tasiyor"],
  ["D11", "-", "odak sirasi gorsel sirayla uyusmuyor"],
];

export function* gez(d = BELGE) {
  yield d;
  for (const c of d.cocuk ?? []) yield* gez(c);
}
```

## Ölçütlerin Karar Kaynağı

Bir ölçütün otomatikleştirilip otomatikleştirilemeyeceğini belirleyen şey ölçütün önemi
değil, **kararın nereden okunduğudur**. Dört kaynak var: ağaçtan doğrudan okunan bir
bildirim, bildirilen değerlerden hesaplanan bir sayı, içeriğin ne anlattığına bağlı bir
niyet ve zaman içindeki bir etkileşim dizisi. İlk ikisi bir programa yaptırılabilir,
son ikisi yaptırılamaz.

```js
// denetci.mjs — olcut kumesi, karar kaynaklari ve agactan karar verilebilen denetimler
import { gez } from "./belge.mjs";

// karar kaynagi: agac | hesap (ikisi otomatik) | niyet | dizi (ikisi elle)
export const OLCUT = [
  ["D1", "eylem adi bos", "agac", 90], ["D2", "alan etiketsiz", "agac", 90],
  ["D3", "baslik duzeyi atlanmis", "agac", 70], ["D4", "kimlik yineleniyor", "agac", 90],
  ["D5", "dil bildirimi yok", "agac", 90], ["D6", "eylem odak almiyor", "agac", 90],
  ["D7", "karsitlik esigin altinda", "hesap", 60], ["D8", "dokunma hedefi kucuk", "hesap", 50],
  ["D9", "bildirim yalniz renkle", "niyet", 0], ["D10", "eylem adi anlamsiz", "niyet", 0],
  ["D11", "odak sirasi gorsel siraya uymuyor", "niyet", 0],
  ["D12", "pencereden klavyeyle cikilamiyor", "dizi", 0],
  ["D13", "degisim duyurusunun zamanlamasi", "dizi", 0],
  ["D14", "buyutulmus metinde icerik kaybi", "dizi", 0],
];

const kanal = (c) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
const isik = (h) => {
  const [r, g, b] = [1, 3, 5].map((i) => kanal(parseInt(h.slice(i, i + 2), 16) / 255));
  return 0.2126 * r + 0.7152 * g + 0.0722 * b;
};
export const karsitlik = (on, arka) => {
  const [a, b] = [isik(on), isik(arka)].sort((x, y) => y - x);
  return (a + 0.05) / (b + 0.05);
};

export function denetle(belge) {
  const bulgu = [], kimlikler = [];
  let onceki = 0;
  for (const d of gez(belge)) {
    if (d.tur === "sayfa" && !d.dil) bulgu.push({ olcut: "D5", yer: "sayfa" });
    if (d.kimlik) kimlikler.push(d.kimlik);
    if (d.tur === "baslik") {
      if (onceki && d.duzey > onceki + 1) bulgu.push({ olcut: "D3", yer: `baslik ${d.duzey}` });
      onceki = d.duzey;
    }
    if (d.tur === "eylem") {
      if (!d.metin) bulgu.push({ olcut: "D1", yer: d.kimlik });
      if (!d.odaklanabilir) bulgu.push({ olcut: "D6", yer: d.kimlik });
      if (d.boyut < 24) bulgu.push({ olcut: "D8", yer: d.kimlik });
    }
    if (d.tur === "alan" && !d.etiket) bulgu.push({ olcut: "D2", yer: d.kimlik });
    if (d.renk && d.zemin && karsitlik(d.renk, d.zemin) < 4.5)
      bulgu.push({ olcut: "D7", yer: d.kimlik ?? d.metin, oran: karsitlik(d.renk, d.zemin).toFixed(2) });
  }
  const yineleyen = kimlikler.filter((k, i) => kimlikler.indexOf(k) !== i);
  for (const k of new Set(yineleyen)) bulgu.push({ olcut: "D4", yer: k });
  return bulgu;
}
```

**IO13 (varsayım):** karar kaynağı sınıflandırması ve elle doğrulanmış kusur listesi
doğrudur. Kapsama payı bu iki listeye görelidir; ölçüt kümesi genişletildiğinde pay değişir.

## Kapsama Payı ve Bulgular

```js
// olcum.mjs — kapsama payi, bulgular ve esik taramasi
import { BELGE, GERCEK } from "./belge.mjs";
import { OLCUT, denetle } from "./denetci.mjs";

const OTOMATIK = ["agac", "hesap"];
const oto = OLCUT.filter(([, , k]) => OTOMATIK.includes(k));
console.log(`${OLCUT.length} olcut; karar kaynagina gore dagilim:`);
for (const k of ["agac", "hesap", "niyet", "dizi"]) {
  const n = OLCUT.filter(([, , x]) => x === k).length;
  console.log(`  ${k.padEnd(7)}${String(n).padStart(3)}  %${((100 * n) / OLCUT.length).toFixed(0)}`);
}
console.log(`kapsama payi: ${oto.length}/${OLCUT.length} = %${((100 * oto.length) / OLCUT.length).toFixed(0)}`);

const puan = Object.fromEntries(OLCUT.map(([k, , , p]) => [k, p]));
const ad = Object.fromEntries(OLCUT.map(([k, a]) => [k, a]));
const gercekKume = new Set(GERCEK.map(([k, y]) => `${k}|${y}`));
const anahtar = (b) => `${b.olcut}|${b.yer}`;
const bulgu = denetle(BELGE);
const dogru = bulgu.filter((b) => gercekKume.has(anahtar(b))).length;
console.log(`\n${bulgu.length} bulgu, ${GERCEK.length} elle dogrulanmis kusur, otomatik bulunan ${dogru}` +
  ` = %${((100 * dogru) / GERCEK.length).toFixed(0)}`);
for (const b of bulgu) {
  console.log(`  ${b.olcut}  ${ad[b.olcut].padEnd(26)}${String(b.yer).padEnd(11)}` +
    `${String(puan[b.olcut]).padStart(3)}  gercek: ${gercekKume.has(anahtar(b)) ? "evet" : "hayir"}` +
    `${b.oran ? `  (oran ${b.oran})` : ""}`);
}

console.log(`\n${"esik".padStart(4)}${"kalan".padStart(7)}${"yanlis alarm".padStart(14)}${"kacirma".padStart(9)}${"maliyet w=5".padStart(12)}`);
for (const e of [50, 60, 70, 90]) {
  const k = bulgu.filter((b) => puan[b.olcut] >= e);
  const ya = k.filter((b) => !gercekKume.has(anahtar(b))).length;
  const kac = GERCEK.length - k.filter((b) => gercekKume.has(anahtar(b))).length;
  console.log(`${String(e).padStart(4)}${String(k.length).padStart(7)}${String(ya).padStart(14)}${String(kac).padStart(9)}${String(ya + 5 * kac).padStart(12)}`);
}
const otomatikKod = oto.map(([k]) => k);
const elle = GERCEK.filter(([k]) => !otomatikKod.includes(k));
console.log(`\nhicbir esikte gorunmeyen ${elle.length} kusur (elle dogrulama alani):`);
for (const [k, , g] of elle) console.log(`  ${k}  ${g}`);
```

```
14 olcut; karar kaynagina gore dagilim:
  agac     6  %43
  hesap    2  %14
  niyet    3  %21
  dizi     3  %21
kapsama payi: 8/14 = %57

6 bulgu, 8 elle dogrulanmis kusur, otomatik bulunan 5 = %63
  D5  dil bildirimi yok         sayfa       90  gercek: evet
  D3  baslik duzeyi atlanmis    baslik 3    70  gercek: evet
  D1  eylem adi bos             al-1        90  gercek: evet
  D2  alan etiketsiz            uye-no      90  gercek: evet
  D7  karsitlik esigin altinda  Ceza: 30    60  gercek: evet  (oran 3.45)
  D7  karsitlik esigin altinda  gecmis      60  gercek: hayir  (oran 2.78)

esik  kalan  yanlis alarm  kacirma maliyet w=5
  50      6             1        3          16
  60      6             1        3          16
  70      4             0        4          20
  90      3             0        5          25

hicbir esikte gorunmeyen 3 kusur (elle dogrulama alani):
  D9  gecikme yalniz renk degisimiyle bildiriliyor
  D10  iki ayri islemi yapan eylem ayni adi tasiyor
  D11  odak sirasi gorsel sirayla uyusmuyor
```

İki oran ayrı şeyleri söylüyor. **Kapsama payı %57**, ölçüt kümesinin bir programa
yaptırılabilen bölümüdür ve belgeden bağımsızdır. **Bulunan kusur oranı %63**, bu belgedeki
sekiz kusurun beşinin otomatik denetimle yakalandığını söyler ve belgeye bağlıdır: kusurlar
başka bir dağılıma düşseydi bu oran değişirdi. İkinci sayı birinciden türetilemez.

Tek yanlış alarm karşıtlık hesabından geldi. Edilgen bir eylemin metin karşıtlığı eşiğin
altında, ama edilgen denetimler bu eşikten muaftır ve denetçi bunu bilmiyor. Hesaplanan
ölçütlerin ortak sorunu budur: sayı doğru, kural doğru, **bağlam eksik**.

## Eşiği Yükseltmek Neden İşe Yaramıyor

Eşik taraması önceki üç dersten farklı bir sonuç veriyor. Orada eşiği yükseltmek yanlış
alarmları düşürürken bazı gerçek kusurları kaçırıyordu ve arada bir en uygun nokta vardı.
Burada eşiği yükseltmek tek bir yanlış alarmı düşürüyor, karşılığında iki gerçek kusuru
kaçırıyor; maliyet monoton olarak artıyor. En düşük maliyet, taramanın **en alt** ucundadır.

Tablonun yanlış alarm sütunu **yanlış kalma**, kaçırma sütunu **yanlış geçme** sayısıdır;
burada yanlış geçme hiçbir eşikte üçün altına inmiyor.
Nedeni tablonun son üç satırındadır: kaçırılan üç kusur hiçbir eşikte görünmüyor, çünkü
onlara karşılık gelen ölçütlerin puanı yok — programa yaptırılamıyorlar. **Kaçırma burada
eşik seçiminin sonucu değil, yöntemin yapısal sınırıdır.** Bir gecikmenin yalnız renk
değişimiyle bildirilmesi, aynı adı taşıyan iki eylemin ayrı işler yapması ve odak sırasının
görsel sırayla uyuşmaması: üçü de ağaçta hiçbir bildirim eksikliği bırakmaz.

Bu yüzden bu denetimin eşiği bir puan değildir. **Eşik ve kaynağı** şöyle yazılır: yayın,
otomatik denetimden sıfır bulgu **ve** elle doğrulama listesindeki altı ölçütün
işaretlenmiş olması koşuluna bağlanır. Eşiğin kaynağı bu ölçümdür — sekiz kusurdan üçünün
otomatik denetimde hiç görünmemesi, yalnız otomatik denetime dayanan bir kapının üç gerçek
kusurla yeşil döneceğini gösterir.

## Denetimin Bedeli

Koşumdan bağımsız bedel üç yerdedir. Otomatik yan ucuzdur: bir ağaç dolaşımı, on dört
öge, sıfır süreç, sıfır istek; her değişiklikte koşturulabilir.

Elle doğrulama yanı ucuz değildir ve bedeli **ekran başına ölçüt sayısıyla** ölçülür: altı
ölçüt, her ekran için ayrı ayrı. Ödünç sisteminin ekran sayısı arttıkça bu sayı doğrusal
büyür ve otomatik denetimin aksine sürüm başına yeniden ödenir.

Üçüncü bedel sınıflandırmanın bakımıdır. Ölçütün karar kaynağı değişebilir: bugün niyet
gerektiren bir kontrol, belge modeline yeni bir bildirim eklendiğinde ağaçtan okunabilir
hâle gelir. Sınıflandırma güncellenmezse kapsama payı olduğundan düşük görünür ve elle
doğrulama listesi gereğinden uzun kalır.

**Kararın sahibi:** otomatik bulgu yayımı durdurur; elle doğrulama listesi bir kontrol
kaydıdır ve işaretlenmemiş bir ölçüt yayını durdurmaz, yalnız yayının hangi ölçütler
sınanmadan çıktığını kayda geçirir.

## Özet

- Bir ölçütün otomatikleştirilebilirliğini belirleyen şey kararın kaynağıdır: ağaçtan
  okunan bildirim ve hesaplanan değer otomatiktir, niyet ve etkileşim dizisi değildir.
- On dört ölçütün sekizi otomatik denetlenebilir (kapsama payı %57); bu belgedeki sekiz
  kusurun beşi otomatik bulundu (%63). İki oran ayrı şeyleri ölçer ve biri diğerinden
  türetilemez.
- Tek yanlış alarm hesaplanan bir ölçütten geldi: edilgen bir denetimin karşıtlığı eşiğin
  altındaydı ama o denetim eşikten muaftı — sayı doğru, bağlam eksikti.
- Kaçan üç kusur hiçbir eşikte görünmedi; kaçırma burada eşik seçiminin değil yöntemin
  sonucudur ve eşiği yükseltmek maliyeti tek yönde artırır.
- Eşik bir puan değil bir koşuldur: sıfır otomatik bulgu **ve** altı elle doğrulama
  ölçütünün işaretlenmesi. Kaynağı, yalnız otomatik denetime dayanan bir kapının üç gerçek
  kusurla yeşil döneceği ölçümüdür.
- Bedel: otomatik yan bir ağaç dolaşımı kadar ucuz, elle yan ekran başına altı ölçüt kadar
  pahalı ve her sürümde yeniden ödeniyor.

## Sonraki Adım

Bu denetim tek bir belge modeli üzerinde koştu ve tek bir sonuç verdi. Oysa aynı ödünç
ekranı her okuyucuda aynı ağacı üretmez: farklı oluşturma motorları aynı bildirimi farklı
yorumlar, farklı ekran genişlikleri farklı düzen kurar, farklı giriş biçimleri farklı
etkileşim sırası dayatır. Buraya kadarki bütün ölçümler tek bir ortamda yapıldı ve o
ortamın temsil ettiği kullanıcı payı hiç sorulmadı. Sonraki ders ortam eksenlerini bir
matrise açar, matrisin hangi alt kümesinin koşulacağını iki ayrı ölçütle seçer ve seçimin
kapsadığı payı sayar.
