Test Düzenekleri, Geçici Ortamlar ve Kapsam
Yalıtılmış test düzenekleri oluşturun ve testlerinizin betiğin hangi dallarını gerçekten çalıştırdığını ölçün.
Test Düzenekleri, Geçici Ortamlar ve Kapsam, CoddyKit'te ücretsiz bir DevOps Bootcamp dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, DevOps Bootcamp öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DevOps Bootcamp kursu toplamda 4 dersten oluşur.
Test Düzenekleri ve Yalıtım Neden Önemlidir
Bash betiklerini sınarken en büyük risk yan etkilerdir: sınamalarınızın gerçek dosyaları, gerçek veritabanlarını veya gerçek sistem durumunu yanlışlıkla değiştirmesi. Bilgisayarınızda başarılı olan ancak üretim verilerini bozan bir sınama, hiç sınama olmamasından daha kötüdür.
Çözüm, gerçek koşulları hiçbir gerçek şeye dokunmadan yansıtan denetimli ve kullanımdan sonra atılabilen test düzenekleridir. İyi test düzenekleri şunları sağlar:
- Yeniden üretilebilirlik — sınamalar her çalıştırmada aynı sonucu üretir
- Yalıtım — sınamalar birbirini veya ana makineyi etkilemez
- Güvenlik — yıkıcı işlemler yalnızca atılabilir verileri etkiler
- Hız — kesinlikle gerekmedikçe ağ çağrıları veya ağır G/Ç yapılmaz
Bash sınamalarında test düzenekleri genellikle bilinen dosyalarla doldurulmuş geçici dizinlerden, $PATH'in başına yerleştirilmiş sahte çalıştırılabilir dosyalardan ve sınama süreciyle sınırlı ortam değişkenlerinden oluşur.
Geçici Dizinler Oluşturma ve Temizleme
Sınama başına geçici dizin kullanmak için standart kalıp, /tmp içinde benzersiz bir dizin oluşturan ve yolunu yazdıran mktemp -d komutunu kullanır. Yolu saklar ve kabuk çıktığında, hata durumunda bile dizini otomatik olarak kaldırmak için bir trap kaydedersiniz.
Dosya sistemine dokunan her sınama dosyasında bu iki satırlık deyim bulunmalıdır:
#!/usr/bin/env bash
set -euo pipefail
# Create an isolated temp directory
TMPDIR=$(mktemp -d)
# Always clean up, even if the script exits early or errors out
trap 'rm -rf "$TMPDIR"' EXIT
echo "Working in: $TMPDIR"
# Simulate creating fixture files
mkdir -p "$TMPDIR/project/{src,tests,logs}"
echo 'version=1.2.3' > "$TMPDIR/project/.env"
echo 'Hello fixture' > "$TMPDIR/project/src/main.sh"
ls -R "$TMPDIR/project"
echo 'Temp dir will be removed automatically on exit'Test Dizin Ağacını Yapılandırma
İyi yapılandırılmış bir test düzeneği, sınanan betiğinizin gerçekten beklediği dizin düzenini yansıtır. Bunu minyatür bir sahte proje kökü olarak düşünebilirsiniz. Test düzeneği kurulum işlevi bu düzeni her sınamadan önce oluşturur, temizleme işlemi de kaldırır.
Temel uygulamalar:
- Sınama çerçevenizin her sınamadan önce çağırdığı bir
setup()işlevi kullanın - Hata durumunda bile her sınamadan sonra çalışan bir
teardown()veyacleanup()kullanın - Test düzeneği dosyalarını en küçük boyutta tutun; yalnızca betiğin gerçekten okuduğu dosyaları ekleyin
- Hataların tanılanmasını kolaylaştırmak için test düzeneği dosyalarını açıklayıcı biçimde adlandırın
#!/usr/bin/env bash
# fixture_helpers.bash — source this from your test files
FIXTURE_ROOT=''
setup_fixture() {
FIXTURE_ROOT=$(mktemp -d)
# Build the directory tree the deploy script expects
mkdir -p "$FIXTURE_ROOT"/{dist,config,logs}
echo '{"version":"2.0"}' > "$FIXTURE_ROOT/config/app.json"
echo 'console.log("app")' > "$FIXTURE_ROOT/dist/index.js"
touch "$FIXTURE_ROOT/logs/.gitkeep"
export FIXTURE_ROOT
echo "[setup] Fixture ready at $FIXTURE_ROOT"
}
teardown_fixture() {
if [[ -n "$FIXTURE_ROOT" && -d "$FIXTURE_ROOT" ]]; then
rm -rf "$FIXTURE_ROOT"
echo '[teardown] Fixture removed'
fi
}
# Self-test
setup_fixture
ls "$FIXTURE_ROOT"
teardown_fixtureSahte PATH ile Çalıştırılabilir Dosyaları Taklit Etme
Birçok Bash betiği curl, aws, docker veya git gibi harici araçları çağırır. Sınamalarda gerçek hizmetlere bağlanmak istemezsiniz; bu nedenle bu araçları sahte çalıştırılabilir dosyalarla değiştirirsiniz.
Teknik basittir:
- Test düzeneğinizin içinde geçici bir
bin/dizini oluşturun - Gerçek araçlarla aynı adlara sahip küçük kabuk betiklerini buraya yazın
- Sınanan betiğinizi çağırmadan önce bu dizini
$PATH'in önüne ekleyin
$PATH soldan sağa arandığı için sahte dosya kazanır. Gerçek ikili dosya hiçbir zaman çağrılmaz.
#!/usr/bin/env bash
set -euo pipefail
FIXTURE=$(mktemp -d)
trap 'rm -rf "$FIXTURE"' EXIT
# Create a fake 'curl' that records calls and returns canned data
FAKE_BIN="$FIXTURE/bin"
mkdir -p "$FAKE_BIN"
cat > "$FAKE_BIN/curl" << 'SCRIPT'
#!/usr/bin/env bash
# Log every argument for later inspection
echo "curl $*" >> "$FIXTURE_BIN_LOG"
# Return a canned HTTP 200 response body
echo '{"status":"ok","id":42}'
SCRIPT
chmod +x "$FAKE_BIN/curl"
# Export the log path so the fake can find it
export FIXTURE_BIN_LOG="$FIXTURE/curl_calls.log"
# Prepend fake bin directory to PATH
export PATH="$FAKE_BIN:$PATH"
# Now any call to 'curl' hits our fake
curl -s https://api.example.com/health
curl -X POST https://api.example.com/deploy
echo '--- Recorded curl calls ---'
cat "$FIXTURE_BIN_LOG"Komut Çıktısını Yakalama ve Doğrulama
Bir test düzeneği ancak betiğinizin ne yaptığını doğrulayabiliyorsanız kullanışlıdır. Standart kalıplar şunlardır:
- Standart çıktıyı/hata çıktısını
$()veya süreç ikamesiyle değişkenlere yakalayın - Sahte ikili dosyaların yazdığı günlük dosyalarını inceleyin
- Çıkış kodlarını
$?veya koşullu mantıkla açıkça denetleyin - Belirli dosyaların oluşturulduğunu, değiştirildiğini veya olduğu gibi bırakıldığını doğrulayın
Küçük ve odaklanmış doğrulama yardımcıları yazmak, sınamalarınızı okunabilir kılar ve bir şeyler ters gittiğinde kesin hata mesajları almanızı sağlar.
#!/usr/bin/env bash
set -euo pipefail
# Minimal assertion helpers
assert_eq() {
local desc="$1" expected="$2" actual="$3"
if [[ "$expected" == "$actual" ]]; then
echo "PASS: $desc"
else
echo "FAIL: $desc"
echo " expected: $expected"
echo " actual: $actual"
return 1
fi
}
assert_file_exists() {
local desc="$1" file="$2"
if [[ -f "$file" ]]; then
echo "PASS: $desc"
else
echo "FAIL: $desc — file not found: $file"
return 1
fi
}
assert_contains() {
local desc="$1" needle="$2" haystack="$3"
if [[ "$haystack" == *"$needle"* ]]; then
echo "PASS: $desc"
else
echo "FAIL: $desc — '$needle' not found in output"
return 1
fi
}
# Demo usage
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
echo 'hello world' > "$TMPDIR/greeting.txt"
OUT=$(cat "$TMPDIR/greeting.txt")
assert_eq 'file content matches' 'hello world' "$OUT"
assert_file_exists 'greeting file created' "$TMPDIR/greeting.txt"
assert_contains 'output has hello' 'hello' "$OUT"Sınamalarda Ortam Değişkenlerinin Kapsamı
Beti̇kler genellikle $HOME, $CONFIG_PATH veya $DATABASE_URL gibi ortam değişkenlerinden okur. Sınamalarda gerçek ortamı kirletmeden bunların üzerine yazmanız gerekir.
En güvenli yaklaşım, sınanan betiği yalnızca açıkça ayarladığınız değişkenleri içeren bir alt kabukta çalıştırmaktır. env komutu ortamı temizleyip yalnızca ihtiyacınız olanları yeniden eklemenizi sağlar:
env -i VAR=val ./script.sh— tamamen temiz ortam(export VAR=val; ./script.sh)— alt kabuk, üst ortamı ve üzerine yazdığınız değerleri devralır
Alt kabukları kullanmak, betik $IFS, $PWD veya başka bir genel durumu değiştirse bile bu değişikliklerin sınama çalıştırıcınıza geri sızmamasını sağlar.
#!/usr/bin/env bash
set -euo pipefail
FIXTURE=$(mktemp -d)
trap 'rm -rf "$FIXTURE"' EXIT
# Write a tiny script under test that reads env vars
cat > "$FIXTURE/deploy.sh" << 'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
ENV_NAME=${DEPLOY_ENV:-unknown}
CFG=${CONFIG_DIR:-/etc/app}
echo "Deploying to $ENV_NAME using config from $CFG"
SCRIPT
chmod +x "$FIXTURE/deploy.sh"
echo '--- Test 1: staging env ---'
# Run in a clean subshell with explicit vars
(
export DEPLOY_ENV=staging
export CONFIG_DIR="$FIXTURE/config"
"$FIXTURE/deploy.sh"
)
echo '--- Test 2: production env ---'
(
export DEPLOY_ENV=production
export CONFIG_DIR=/etc/prod-config
"$FIXTURE/deploy.sh"
)
echo '--- Test 3: defaults ---'
# No env vars set — script should use its own defaults
env -i PATH="$PATH" "$FIXTURE/deploy.sh"Bash Kapsamı İçin kcov'a Giriş
Kapsam şu soruyu yanıtlar: Betiğimin hangi satırlarını (ve dallarını) sınamalar gerçekten çalıştırdı? Yüksek kapsam sayısı doğruluğu garanti etmez; ancak düşük kapsam, büyük olasılıkla hatalar barındıran sınanmamış yolları ortaya çıkarır.
Bash kapsamı için temel araç kcov'dur. Betiği PTRACE (Linux) veya dtrace (macOS) kullanarak işletim sistemi düzeyinde araçlandırır; bu nedenle kaynak kodunuzda değişiklik yapmanız gerekmez. Kapsanmayan satırları kırmızı, kapsanan satırları yeşil gösteren bir HTML raporu üretir.
Temel kullanım:
kcov --include-path=./src coverage-out/ ./src/myscript.sh- Sonuçları incelemek için bir tarayıcıda
coverage-out/index.htmldosyasını açın - Sürekli tümleştirmede, makine tarafından okunabilir yüzdeyi almak için
coverage-out/myscript.sh/coverage.jsondosyasını ayrıştırın
Not: kcov ayrıca yüklenmelidir (macOS'ta brew install kcov, Ubuntu 20.04+ üzerinde apt install kcov).
kcov'u Gerçek Bir Betik Üzerinde Çalıştırma
Burada dağıtıma hazır bir betiği, onu çalıştıran bir sınamayı ve kapsamı ölçen kcov çağrısını gösteren uçtan uca bir örnek yer alıyor. Çıktı dizininin sınama başına olduğuna dikkat edin; böylece daha sonra birden çok sınama çalıştırmasının sonuçlarını birleştirebilirsiniz.
#!/usr/bin/env bash
# This demo shows the *structure* of a kcov workflow.
# It will not run kcov itself (not guaranteed to be installed),
# but the script under test and test runner are fully runnable.
set -euo pipefail
FIXTURE=$(mktemp -d)
trap 'rm -rf "$FIXTURE"' EXIT
# 1. Script under test
cat > "$FIXTURE/process.sh" << 'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
INPUT="$1"
if [[ ! -f "$INPUT" ]]; then
echo "ERROR: file not found" >&2
exit 1
fi
LINE_COUNT=$(wc -l < "$INPUT")
if (( LINE_COUNT == 0 )); then
echo "WARNING: file is empty"
else
echo "Processed $LINE_COUNT lines"
fi
SCRIPT
chmod +x "$FIXTURE/process.sh"
# 2. Happy path test (exercises line 6 and 11)
echo -e 'one\ntwo\nthree' > "$FIXTURE/data.txt"
OUT=$("$FIXTURE/process.sh" "$FIXTURE/data.txt")
echo "Happy path: $OUT"
# 3. Empty file test (exercises line 9)
touch "$FIXTURE/empty.txt"
OUT=$("$FIXTURE/process.sh" "$FIXTURE/empty.txt")
echo "Empty file: $OUT"
# 4. Missing file test (exercises line 5-6)
if ! OUT=$("$FIXTURE/process.sh" "$FIXTURE/missing.txt" 2>&1); then
echo "Missing file (expected error): $OUT"
fi
# To measure coverage, wrap each call with kcov:
# kcov --include-path="$FIXTURE" "$FIXTURE/cov/happy" "$FIXTURE/process.sh" ...
# kcov --merge "$FIXTURE/cov/all" "$FIXTURE/cov/happy" "$FIXTURE/cov/empty"Birden Çok Sınama Çalıştırmasının Kapsamını Birleştirme
Tek bir sınama nadiren tüm dalları kapsar. Her birini kendi kapsam çıktı dizininde çalıştırdığınız birden çok sınama yürütür ve ardından bunları birleştirirsiniz. kcov'un --merge seçeneği birden çok çalıştırmayı tek ve birleşik bir raporda toplar.
Bir sürekli tümleştirme iş hattındaki tipik kalıp:
- A sınamasını çalıştırın → çıktıyı
cov/test_a/konumuna yazın - B sınamasını çalıştırın → çıktıyı
cov/test_b/konumuna yazın - Birleştirin →
kcov --merge cov/all/ cov/test_a/ cov/test_b/ - Son yüzdeyi almak için
cov/all/<script>/coverage.jsondosyasını ayrıştırın
Ayrıca bir asgari eşik uygulayabilir ve kapsam bunun altına düşerse sürekli tümleştirme derlemesini başarısız kılabilirsiniz:
#!/usr/bin/env bash
# extract_coverage.sh — parse kcov JSON and fail below threshold
set -euo pipefail
MIN_COVERAGE=80 # percent
COV_JSON="${1:-coverage-out/myscript.sh/coverage.json}"
if [[ ! -f "$COV_JSON" ]]; then
echo "ERROR: coverage JSON not found at $COV_JSON" >&2
exit 1
fi
# kcov JSON contains a key like: "percent_covered": "87.50"
PERCENT=$(grep -oP '"percent_covered":\s*"\K[0-9.]+' "$COV_JSON")
PERCENT_INT=${PERCENT%%.*} # truncate decimal
echo "Coverage: ${PERCENT}% (minimum: ${MIN_COVERAGE}%)"
if (( PERCENT_INT < MIN_COVERAGE )); then
echo "FAIL: coverage ${PERCENT}% is below threshold ${MIN_COVERAGE}%" >&2
exit 1
fi
echo "PASS: coverage threshold met"Dal Kapsamı ve Satır Kapsamı
Karşılaşacağınız iki temel kapsam ölçütü vardır:
- Satır kapsamı — bu satır hiç çalıştırıldı mı? Kolayca yanıltılabilir: tek bir sınama birçok satıra dokunurken önemli koşullu yolları atlayabilir.
- Dal kapsamı — her
if,caseve&&/||ifadesinin her dalı seçildi mi? Çok daha güçlü bir göstergedir. Her kararın hem doğru hem de yanlış tarafı için sınamalar gerekir.
kcov her ikisini de raporlar. Temel çıkarım şudur: %100 satır kapsamı, %100 dal kapsamı anlamına gelmez. Şu betiği düşünün: boş olmayan bir dosyayla yapılan tek bir sınama her satırı kapsar; ancak boş dosya dalına (aşağıdaki 9. satır) hiçbir zaman ulaşılmaz:
#!/usr/bin/env bash
# Illustrates line vs branch coverage gap
set -euo pipefail
check_file() {
local f="$1"
if [[ -f "$f" ]]; then # branch A (true) OR branch B (false)
local lines
lines=$(wc -l < "$f")
if (( lines > 0 )); then # branch C (true) OR branch D (false)
echo "File has $lines lines"
else
echo "File is empty" # branch D — unreached if only tested with non-empty file
fi
else
echo "File missing" # branch B — unreached if only tested with existing file
fi
}
# Only one test: covers lines 5-10 (4 of 6 branches)
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
echo 'data' > "$TMPDIR/sample.txt"
check_file "$TMPDIR/sample.txt"
# To reach 100% branch coverage you also need:
# check_file "/nonexistent/path"
# check_file "$TMPDIR/empty.txt" (after: touch "$TMPDIR/empty.txt")Fikstürleri ve Kapsam Ölçümünü Sürekli Tümleştirmeye Eklemek
Her şeyi bir araya getirdiğinizde, Bash projeleri için sağlam bir sürekli tümleştirme hattı; fikstür kurulumunu, kcov ile sınamaların çalıştırılmasını, birleştirmeyi ve eşik denetimini tek bir betikte birleştirir. Bu betik, sürekli tümleştirmenin giriş noktası olur — her şeyi çalıştırmak için tek bir komut.
Sürekli tümleştirme sınama çalıştırıcısı için tasarım ilkeleri:
- Her sınama durumu
setup_fixtureişlevini çağırır vetraparacılığıylateardown_fixtureişlevini kaydeder - Sınanan betik, sahte
$PATHve kapsamı sınırlandırılmış ortam değişkenleriyle çağrılır - kcov her çağrıyı sarmalar ve çıktıyı numaralandırılmış bir alt dizine yazar
- Tüm sınamalardan sonra kcov birleştirme yapar ve eşik betiği derlemeye izin verip vermeyeceğine karar verir
- Herhangi bir sınama veya kapsam denetimi başarısız olursa sürekli tümleştirme çalıştırıcısı sıfır olmayan bir çıkış koduyla sonlanır
#!/usr/bin/env bash
# ci_runner.sh — full fixture + coverage pipeline entry point
set -euo pipefail
SRC="./src/deploy.sh"
COV_ROOT="$(mktemp -d)/coverage"
trap 'rm -rf "$COV_ROOT"' EXIT
mkdir -p "$COV_ROOT"
PASS=0
FAIL=0
RUN_NUM=0
run_test() {
local name="$1" test_fn="$2"
local fixture
fixture=$(mktemp -d)
local cov_out="$COV_ROOT/run_$((++RUN_NUM))"
if (
trap 'rm -rf "$fixture"' EXIT
export FIXTURE="$fixture"
# Fake bin directory shadowing real tools
mkdir -p "$fixture/bin"
export PATH="$fixture/bin:$PATH"
"$test_fn" "$fixture"
); then
echo "PASS: $name"
(( PASS++ )) || true
else
echo "FAIL: $name"
(( FAIL++ )) || true
fi
}
# Example test function
test_happy_path() {
local fx="$1"
mkdir -p "$fx/dist"
echo 'app.js' > "$fx/dist/index.js"
# Would normally run: kcov "$cov_out" "$SRC" --env=staging "$fx"
echo "[test] happy path executed in $fx"
}
run_test 'happy_path' test_happy_path
echo "Results: $PASS passed, $FAIL failed"
(( FAIL == 0 ))Bilgi Denetimi: Sahte PATH Tekniği
Bash sınama fikstürlerinde kullanılan sahte PATH tekniğini ne kadar anladığınızı sınayın.
Özet: Fikstürler, Geçici Ortamlar ve Kapsam Ölçümü
Bu derste güvenilir ve yalıtılmış Bash sınaması için gereken araçların tamamını ele aldınız:
- Geçici dizinler —
mktemp -dile birlikte kullanılantrap ... EXIT, sınamanın nasıl sonlandığından bağımsız olarak otomatik temizlemeyi garanti eder. - Fikstür yapısı —
setup_fixture/teardown_fixtureçifti, gerçek betik girdelerini yansıtan en küçük dizin ağacını oluşturur ve yok eder. - Sahte PATH —
$FIXTURE/bin/içine sahte çalıştırılabilir dosyalar yerleştirin ve bunları$PATHdeğişkeninin başına ekleyerek sistem ikili dosyalarına dokunmadancurl,aws,dockerveya herhangi bir dış aracın çağrılarını araya girerek yakalayın. - Ortam kapsamını sınırlandırma — değiştirilen değişkenlerin sınama çalıştırıcısına geri sızmaması için sınanan betiği bir alt kabukta (
()veyaenv -i) çalıştırın. - Doğrulamalar — küçük yardımcı işlevler (
assert_eq,assert_file_exists,assert_contains) anlaşılır başarılı/başarısız çıktısı ve anlamlı hata iletileri üretir. - kcov kapsam ölçümü — kaynakta değişiklik yapmadan betiğin çalıştırılmasını sarar; satır ve dal kapsamı için HTML ve JSON raporları üretir.
- Birleştirme ve eşik — birden fazla kcov çalıştırmasının sonuçlarını
--mergeile birleştirin, JSON'u ayrıştırın ve kapsamınız en düşük değerin altına düşerse sürekli tümleştirmeyi başarısız kılın. - Dal kapsamı ve satır kapsamı — her zaman dal kapsamını hedefleyin; yalnızca satır kapsamı, koşullu yolların tamamını gözden kaçırabilir ve yanlış bir güven duygusu oluşturabilir.
Bu tekniklerle Bash sınamalarınız, derlenen herhangi bir dille yazılmış sınamalar kadar titiz olur.
Sıkça Sorulan Sorular
“Test Düzenekleri, Geçici Ortamlar ve Kapsam” dersi ücretsiz mi?
Evet — “Test Düzenekleri, Geçici Ortamlar ve Kapsam” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve DevOps Bootcamp kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DevOps Bootcamp kursu toplamda 4 dersten oluşur.
“Test Düzenekleri, Geçici Ortamlar ve Kapsam” dersinde ne öğreneceğim?
Yalıtılmış test düzenekleri oluşturun ve testlerinizin betiğin hangi dallarını gerçekten çalıştırdığını ölçün. DevOps Bootcamp ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
DevOps Bootcamp öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te DevOps Bootcamp, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Test Düzenekleri, Geçici Ortamlar ve Kapsam” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu DevOps Bootcamp dersinde kod yazıp çalıştırabilir miyim?
Evet. Her DevOps Bootcamp dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Bats-core ile Fonksiyonları Birim Testine Tabi Tutma
- Komutları Taklit Etme ve Dış Araçlar için Saplama Oluşturma
- Test Düzenekleri, Geçici Ortamlar ve Kapsam
- Kabuk Testlerini CI Pipeline'larında Çalıştırma