19-bo‘lim
Testlar va nosozliklarni topish
Nega test kerak, o'z sinov vositangizni yozish, Arrange-Act-Assert, chegaraviy holatlar, xUnit bilan tanishuv va nosozlikni qidirish usullari.
Ushbu bo‘lim mundarijasi
Test - kodingiz kutilganidek ishlashini avtomatik tekshiradigan kod. U bir marta yoziladi va har o'zgarishdan keyin qayta ishlatiladi.
Nega kerak #
Qo'lda tekshirish ishlaydi, lekin faqat bir marta. Keyin kod o'zgaradi va siz hamma narsani qaytadan tekshirishga ulgurmaysiz.
| Qo'lda | Avtomatik test |
|---|---|
| Har safar vaqt ketadi | Bir soniyada ishlaydi |
| Charchaganda o'tkazib yuboriladi | Har doim bajariladi |
| Chegaraviy holatlar unutiladi | Yozib qo'yilgan |
| Nima tekshirilgani esda qolmaydi | Kod o'zi hujjat |
Eng oddiy sinov vositasi #
Kutubxona o'rnatmasdan ham boshlash mumkin:
Tekshir.Teng(4, Kvadrat(2), "2 ning kvadrati");
Tekshir.Teng(0, Kvadrat(0), "0 ning kvadrati");
Tekshir.Teng(9, Kvadrat(-3), "manfiy sonning kvadrati");
Tekshir.Rost(Kvadrat(5) > 0, "kvadrat musbat");
Tekshir.Yakun();
int Kvadrat(int son) => son * son;
static class Tekshir
{
private static int otdi;
private static int yiqildi;
public static void Teng<T>(T kutilgan, T haqiqiy, string nom)
{
if (Equals(kutilgan, haqiqiy))
{
otdi++;
Console.WriteLine($" OK {nom}");
}
else
{
yiqildi++;
Console.WriteLine(
$" XATO {nom}: kutilgan {kutilgan}, haqiqiy {haqiqiy}");
}
}
public static void Rost(bool shart, string nom) => Teng(true, shart, nom);
public static void Yakun()
{
Console.WriteLine($"\nO'tdi: {otdi}, yiqildi: {yiqildi}");
}
}
OK 2 ning kvadrati
OK 0 ning kvadrati
OK manfiy sonning kvadrati
OK kvadrat musbat
O'tdi: 4, yiqildi: 0
Test yiqilganda #
Tekshir.Teng(10, Qoshish(5, 5), "to'g'ri holat");
Tekshir.Teng(10, Qoshish(5, 4), "ataylab noto'g'ri");
Tekshir.Yakun();
int Qoshish(int a, int b) => a + b;
static class Tekshir
{
private static int otdi;
private static int yiqildi;
public static void Teng<T>(T kutilgan, T haqiqiy, string nom)
{
if (Equals(kutilgan, haqiqiy))
{
otdi++;
Console.WriteLine($" OK {nom}");
}
else
{
yiqildi++;
Console.WriteLine(
$" XATO {nom}: kutilgan {kutilgan}, haqiqiy {haqiqiy}");
}
}
public static void Yakun() =>
Console.WriteLine($"\nO'tdi: {otdi}, yiqildi: {yiqildi}");
}
OK to'g'ri holat
XATO ataylab noto'g'ri: kutilgan 10, haqiqiy 9
O'tdi: 1, yiqildi: 1
Yiqilgan test nima kutilgani va nima chiqqanini aytadi - shu tufayli muammoni topish oson.
Arrange - Act - Assert #
Har bir test uch qismdan iborat bo'lishi kerak:
// Arrange - shart-sharoit tayyorlanadi
var savat = new Savat();
savat.Qosh("Non", 4000);
savat.Qosh("Sut", 12000);
// Act - tekshiriladigan amal bajariladi
decimal jami = savat.Jami();
// Assert - natija tekshiriladi
Console.WriteLine(jami == 16000 ? "OK" : $"XATO: {jami}");
class Savat
{
private readonly List<decimal> narxlar = [];
public void Qosh(string nom, decimal narx) => narxlar.Add(narx);
public decimal Jami() => narxlar.Sum();
}
OK
Bu tuzilma testni o'qishni osonlashtiradi va uni bo'lib yuborishdan saqlaydi.
Nimani tekshirish kerak #
Eng ko'p xato chegaralarda bo'ladi:
Tekshir.Teng("", Qisqartir("", 5), "bo'sh satr");
Tekshir.Teng("salom", Qisqartir("salom", 5), "aynan chegarada");
Tekshir.Teng("salo...", Qisqartir("salomlar", 5), "chegaradan uzun");
Tekshir.Teng("a", Qisqartir("a", 5), "bitta belgi");
Tekshir.Yakun();
string Qisqartir(string matn, int uzunlik) =>
matn.Length <= uzunlik ? matn : matn[..uzunlik] + "...";
static class Tekshir
{
private static int otdi, yiqildi;
public static void Teng<T>(T kutilgan, T haqiqiy, string nom)
{
if (Equals(kutilgan, haqiqiy))
{
otdi++;
Console.WriteLine($" OK {nom}");
}
else
{
yiqildi++;
Console.WriteLine($" XATO {nom}: '{kutilgan}' != '{haqiqiy}'");
}
}
public static void Yakun() =>
Console.WriteLine($"\nO'tdi: {otdi}, yiqildi: {yiqildi}");
}
OK bo'sh satr
OK aynan chegarada
XATO chegaradan uzun: 'salo...' != 'salom...'
OK bitta belgi
O'tdi: 3, yiqildi: 1
Uchinchi test yiqildi - lekin ayb kodda emas, testda.
Qisqartir("salomlar", 5) birinchi 5 ta belgini oladi - bu salom -
va unga ... qo'shadi. Ya'ni to'g'ri natija salom..., men esa
salo... deb kutgan edim. Sanashda bir belgi adashdim.
Bu juda ko'p uchraydi. Test yiqilganda avval kutilgan qiymatni qayta hisoblang: xato ko'pincha o'sha yerda bo'ladi.
Diqqat qiling: bitta test yiqilgani bilan qolganlari bajarilishda davom etdi va yakuniy hisob chiqdi. Yaxshi sinov vositasi birinchi xatoda to'xtamaydi - u hamma muammoni bir yo'la ko'rsatadi.
To'g'rilangan variant:
Tekshir.Teng("", Qisqartir("", 5), "bo'sh satr");
Tekshir.Teng("salom", Qisqartir("salom", 5), "aynan chegarada");
Tekshir.Teng("salom...", Qisqartir("salomlar", 5), "chegaradan uzun");
Tekshir.Teng("a", Qisqartir("a", 5), "bitta belgi");
Tekshir.Yakun();
string Qisqartir(string matn, int uzunlik) =>
matn.Length <= uzunlik ? matn : matn[..uzunlik] + "...";
static class Tekshir
{
private static int otdi, yiqildi;
public static void Teng<T>(T kutilgan, T haqiqiy, string nom)
{
if (Equals(kutilgan, haqiqiy))
{
otdi++;
Console.WriteLine($" OK {nom}");
}
else
{
yiqildi++;
Console.WriteLine($" XATO {nom}: '{kutilgan}' != '{haqiqiy}'");
}
}
public static void Yakun() =>
Console.WriteLine($"\nO'tdi: {otdi}, yiqildi: {yiqildi}");
}
OK bo'sh satr
OK aynan chegarada
OK chegaradan uzun
OK bitta belgi
O'tdi: 4, yiqildi: 0
Chegaraviy holatlar ro'yxati #
| Tur | Tekshiriladigan holatlar |
|---|---|
| Sonlar | 0, manfiy, int.MaxValue, chegaradan bir kam va bir ko'p |
| Satrlar | Bo'sh, faqat bo'shliq, juda uzun, maxsus belgilar |
| To'plamlar | Bo'sh, bitta element, takrorlanuvchi elementlar |
| Havolalar | null |
| Sana | Kabisa yili, oy oxiri, yil chegarasi |
Istisno tashlanishini tekshirish #
Tekshir.IstisnoTashlaydi<ArgumentException>(
() => Bolish(10, 0), "nolga bo'lish");
Tekshir.IstisnoTashlaydi<ArgumentException>(
() => Bolish(10, 2), "oddiy bo'lish");
Tekshir.Yakun();
int Bolish(int a, int b) =>
b == 0 ? throw new ArgumentException("nolga bo'lib bo'lmaydi") : a / b;
static class Tekshir
{
private static int otdi, yiqildi;
public static void IstisnoTashlaydi<TIstisno>(Action amal, string nom)
where TIstisno : Exception
{
try
{
amal();
yiqildi++;
Console.WriteLine(
$" XATO {nom}: istisno kutilgan edi, tashlanmadi");
}
catch (TIstisno)
{
otdi++;
Console.WriteLine($" OK {nom}");
}
}
public static void Yakun() =>
Console.WriteLine($"\nO'tdi: {otdi}, yiqildi: {yiqildi}");
}
OK nolga bo'lish
XATO oddiy bo'lish: istisno kutilgan edi, tashlanmadi
O'tdi: 1, yiqildi: 1
Haqiqiy loyihada - xUnit #
Amalda o'z vositangizni yozmaysiz - tayyor kutubxona ishlatiladi. Eng keng tarqalgani xUnit:
dotnet new xunit -o MeningTestlarim
cd MeningTestlarim
dotnet add reference ../MeningLoyiham/MeningLoyiham.csproj
dotnet test
Test shunday ko'rinadi:
using Xunit;
public class KalkulyatorTestlari
{
[Fact]
public void Qoshish_IkkiMusbatSon_TogriNatija()
{
var k = new Kalkulyator();
int natija = k.Qoshish(2, 3);
Assert.Equal(5, natija);
}
[Theory]
[InlineData(0, 0, 0)]
[InlineData(1, 1, 2)]
[InlineData(-5, 5, 0)]
public void Qoshish_TurliQiymatlar(int a, int b, int kutilgan)
{
Assert.Equal(kutilgan, new Kalkulyator().Qoshish(a, b));
}
}
| Atribut | Nima qiladi |
|---|---|
[Fact] | Oddiy test - bir marta ishlaydi |
[Theory] + [InlineData] | Bir xil test, turli ma'lumot bilan |
Assert.Equal | Tenglikni tekshiradi |
Assert.Throws<T> | Istisno tashlanishini tekshiradi |
Metod_Sharoit_KutilganNatija ko'rinishida:
Qoshish_IkkiMusbatSon_TogriNatijaBolish_NolgaBolish_IstisnoTashlaydiQidir_RoyxatBosh_NullQaytaradi
Shunda test yiqilganda nomning o'zidan nima buzilganini tushunasiz - kodga qarash shart emas.
Nosozlikni qidirish #
Test yiqildi yoki dastur noto'g'ri ishlayapti. Endi nima qilish kerak?
| Usul | Qachon |
|---|---|
| To'xtash nuqtasi (breakpoint) | Eng kuchli usul - qiymatlarni ko'rish |
Console.WriteLine | Tez, oddiy, har joyda ishlaydi |
Debug.Assert | Shart buzilganda to'xtatadi |
| Stek izi (stack trace) | Istisno qayerdan boshlangani |
using System.Diagnostics;
int[] sonlar = [5, 3, 8];
int jami = 0;
foreach (int son in sonlar)
{
jami += son;
Debug.WriteLine($"[debug] son={son}, jami={jami}");
}
Debug.Assert(jami > 0, "yig'indi musbat bo'lishi kerak");
Console.WriteLine($"Yig'indi: {jami}");
Yig'indi: 16
Debug.WriteLine va Debug.Assert faqat Debug rejimida ishlaydi.
Release da ular kompilyatsiyadan butunlay chiqarib tashlanadi -
shuning uchun tayyor dasturni sekinlashtirmaydi.
19-bo'limdagi kompyuter savodxonligi qoidasi bu yerda ham ishlaydi:
- Xato xabarini to'liq o'qing - unda ko'pincha javob bor;
- Stek izining birinchi qatoriga qarang - u sizning kodingiz;
- Nima o'zgarganini eslang - oxirgi ishlagan holatdan beri;
- Muammoni kichraytiring - eng kichik takrorlanadigan misol yarating;
- Bir vaqtda bitta narsani o'zgartiring.
To'rtinchi qadam eng kuchlisi: muammoni o'n qatorgacha qisqartirsangiz, sabab odatda o'z-o'zidan ko'rinadi.
Tekshirsinfini yozing va uchta testdan o'tkazing.- Ataylab noto'g'ri test yozib, xabarni ko'ring.
- Arrange-Act-Assert tuzilmasida test yozing.
Qisqartirmetodi uchun chegaraviy holatlarni tekshiring.- Bo'sh to'plam va
nulluchun testlar qo'shing. IstisnoTashlaydibilan istisno tashlanishini tekshiring.dotnet new xunitbilan test loyihasini yarating.[Theory]va[InlineData]bilan bir nechta holatni sinang.Debug.WriteLinebilan sikl ichidagi qiymatlarni kuzating.- Bir muammoni eng kichik takrorlanadigan misolgacha qisqartiring.
Xulosa #
- Test bir marta yoziladi, har o'zgarishdan keyin ishlaydi.
- Har bir test Arrange - Act - Assert tuzilmasida bo'lsin.
- Eng ko'p xato chegaralarda: bo'sh, nol, bitta element,
null, eng katta qiymat. - Test yiqilsa, avval kutilgan qiymatni qayta tekshiring - xato testda bo'lishi mumkin.
- Haqiqiy loyihada xUnit:
[Fact],[Theory],Assert.Equal. - Test nomi
Metod_Sharoit_KutilganNatijako'rinishida bo'lsin. Debug.WriteLinevaDebug.Assertfaqat Debug rejimida ishlaydi.- Nosozlikni topishda muammoni kichraytirish eng samarali usul.
Keyingi va oxirgi bo'limda hamma o'rganganimizni bitta loyihada birlashtiramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.