Legacy kodni testlar bilan qoplash: xarakterlovchi testlar va choklar
Chuqur3 daqInnovialabs tahririyati
Qisqacha
Avval joriy xatti-harakatni xarakterlovchi yoki snapshot testlar bilan qayd eting, so‘ng choklar orqali baza, tarmoq va vaqtni ajrating va shundan keyingina kodni kichik tekshirilgan qadamlarda o‘zgartiring.
Asosiy g‘oya
Legacy kodda darhol «qanday bo‘lishi kerak» degan testlarni yozib bo‘lmaydi: qanday bo‘lishi kerakligini hech kim aniq bilmaydi, kod esa allaqachon foydalanuvchilarda ishlayapti. Shuning uchun tartib boshqacha:
- Joriy xatti-harakatni qayd etish — hatto g‘alati bo‘lsa ham.
- Kodni baza, tarmoq, vaqt va fayllardan ajratish uchun choklarni topish.
- Kodni kichik qadamlarda o‘zgartirish, har biridan keyin testlarni ishga tushirish.
Birinchi testlarning maqsadi to‘g‘rilikni isbotlash emas, signalizatsiya o‘rnatish: xatti-harakat o‘zgarsa, buni darhol bilasiz.
Xarakterlovchi testlar
Xarakterlovchi test (characterization test) kod hozir nima qilayotganini tasvirlaydi. Usul oddiy:
- Funksiyani real kirish ma’lumotlari bilan chaqiring.
- Ataylab noto‘g‘ri kutilgan qiymat bilan tekshiruv yozing.
- Testni ishga tushiring, haqiqiy natijani ko‘ring va uni kutilgan qiymatga qo‘ying.
Agar natija xatoga o‘xshasa, uni darhol tuzatmang. Testni qoldiring, izoh qo‘shing va vazifa oching: xatoni tuzatish — alohida, ongli o‘zgarish.
Turli tarmoqlardan o‘tadigan kirishlarni tanlang. Qamrov hisoboti (coverage) qaysi tarmoqlar hali tegilmaganini ko‘rsatadi.
Snapshot va approval testing
Natija katta bo‘lsa — HTML, JSON, hisobot, matn ko‘rinishidagi PDF — kutilgan qiymatlarni qo‘lda yozish uzoq davom etadi. Bu yerda yordam beradi:
- Snapshot testlar — Jest
toMatchSnapshot, Python’da masalan syrupy. Birinchi ishga tushirish natijani saqlaydi, keyingilari u bilan solishtiradi. - Approval testing — ApprovalTests oilasidagi kutubxonalar. Natija
receivedfayliga yoziladi, siz diff’ni ko‘rib chiqasiz va uni «tasdiqlab»,approvedga aylantirasiz. - Golden master — ko‘plab kirishlarni (masalan, shaxsiy ma’lumotlardan tozalangan real ma’lumotlar eksportini) ishga tushirish va barcha chiqishlarni saqlash.
Snapshot’ga o‘zgaruvchan ma’lumotlar tushmasligini kuzating: joriy vaqt, tasodifiy ID’lar, kalitlar tartibi. Ularni almashtirish yoki normallashtirish kerak, aks holda testlar «miltillaydi».
Choklar va bog‘liqliklarni uzish
Chok (seam) — kodni aynan o‘sha joyda tahrirlamasdan uning xatti-harakatini o‘zgartirish mumkin bo‘lgan joy. Asosiy turlari:
| Chok | Qanday ko‘rinadi |
|---|---|
| Obyektli | konstruktor yoki funksiyaga boshqa obyekt uzatish |
| Modulli | importni almashtirish: jest.mock, pytest’dagi monkeypatch |
| Konfiguratsion | testlar uchun boshqa baza URL’i yoki muhit bayrog‘i |
Odatiy legacy kod bog‘liqliklarni o‘zi tortib oladi:
def send_reminders():
for inv in db.query_unpaid():
if inv.due_date < datetime.now() - timedelta(days=7):
mailer.send(inv.email, render(inv))
Xavfsiz usul — parametrlarni ajratib olish va chaqiruvchi kodga tegmaslik uchun eski funksiyani o‘ram sifatida qoldirish:
def send_reminders_core(invoices, now, send):
for inv in invoices:
if inv.due_date < now - timedelta(days=7):
send(inv.email, render(inv))
def send_reminders():
send_reminders_core(db.query_unpaid(), datetime.now(), mailer.send)
Endi send_reminders_core ni xotiradagi ro‘yxat, qat’iy sana va soxta yuborish funksiyasi bilan testlash mumkin. Bunday mexanik qadamlarni IDE vositalari bilan bajaring — avtomatik refaktoringda xato ehtimoli kamroq.
Yana ikki foydali usul:
- Sprout method — yangi mantiqni testlari bor alohida funksiyada yozing va uni eski koddan chaqiring.
- Wrap method — eski funksiyani undan oldin yoki keyin xatti-harakat qo‘shadigan yangi funksiya bilan o‘rang.
Kichik qadamlarda refaktoring
- Bitta o‘zgarish — bitta test ishga tushirish — bitta commit.
- Refaktoring va xatti-harakat o‘zgarishini bitta commit’da aralashtirmang.
- Test yiqilsa va sababi tushunarsiz bo‘lsa, oldinga tuzatmang, orqaga qayting.
- Kod tushunarliroq bo‘lgani sari snapshot’larni mazmunli tekshiruvli aniq unit-testlar bilan almashtiring.
- Butun loyihadan emas, eng ko‘p o‘zgaradigan yoki buziladigan qismlardan boshlang.
Keng tarqalgan xatolar
- Testlar paydo bo‘lishidan oldin «yo‘l-yo‘lakay» katta refaktoring.
- Ko‘rib chiqilmasdan yangilanadigan snapshot’lar — ular hech narsani himoya qilmaydi.
- Har bir chaqiruv uchun mock’lar, natijada test implementatsiyani takrorlaydi va har qanday tahrirdan buziladi.