12-bo‘lim

Testlash asoslari

Test piramidasi, modul va integratsiya testlari, soxta obyektlar, qoplama va yaxshi test yozish qoidalari.

🕑 18 daqiqa o‘qish 📄 1 027 so‘z 👁 7 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Nima uchun test kerak?
  2. Test piramidasi
  3. Modul testi
  4. AAA tuzilishi
  5. Yaxshi test qanday bo'ladi?
  6. Nomlash
  7. Parametrlangan testlar
  8. Soxta obyektlar
  9. Fake - ko'pincha eng yaxshi tanlov
  10. Integratsiya testi
  11. API testi
  12. E2E testi
  13. Qoplama
  14. Nimani testlash kerak?
  15. Testlarni tashkil qilish
  16. Xulosa

Test - kodingiz haqiqatan ishlashining yagona ishonchli dalili. "Menda ishlaydi" - dalil emas.

Nima uchun test kerak? #

Testsiz loyihada nima bo'ladi? Testsiz • Har o'zgarishdan qo'rquv • Qo'lda tekshirish - soatlab • Xato foydalanuvchi topadi • Refaktoring imkonsiz • "Tegmang, ishlayapti" Vaqt o'tishi bilan sekinlashadi Testlar bilan • Ishonch bilan o'zgartirish • Tekshirish - soniyalarda • Xato CI da topiladi • Refaktoring xavfsiz • Testlar - jonli hujjat Vaqt o'tishi bilan tezlashadi Testlar tezlikni sekinlashtirmaydi - ular uni saqlaydi
Test yozish vaqti nosozlik qidirish vaqtidan kam
Testlarning to'rt vazifasi
  1. Xatolarni topish - eng aniq vazifa
  2. Hujjat - test kodning qanday ishlatilishini ko'rsatadi
  3. Dizaynni yaxshilash - testlab bo'lmaydigan kod odatda yomon loyihalangan
  4. Ishonch berish - refaktoring va o'zgartirish qo'rqinchli bo'lmaydi

Test piramidasi #

Test piramidasi E2E 5-10% Integratsiya 15-25% Modul testlari 65-80% Sekin (daqiqalar) Qimmat Beqaror O'rtacha (soniyalar) Baza va tashqi tizimlar Tez (millisoniya) Arzon Barqaror Butun tizim Bir necha komponenta Bitta klass Pastdagi testlar ko'p va tez, yuqoridagilar kam va sekin
Piramida shaklini saqlang - teskari bo'lsa muammo
"Muzqaymoq" anti-naqshi

Ko'p jamoalarda piramida teskari bo'ladi: ko'p E2E test, kam modul test.

Natija:

  • Test to'plami soatlab ishlaydi
  • Testlar beqaror - goh o'tadi, goh o'tmaydi
  • Xato qayerda ekanini aniqlash qiyin
  • Jamoa testlarga ishonmay qo'yadi va ularni e'tiborsiz qoldiradi

Bu holatga tushmaslik uchun modul testlaridan boshlang.

Modul testi #

Bitta klass yoki funksiyani izolyatsiyada tekshiradi.

PHP
// Tekshiriladigan kod
final class Savat
{
    private array $elementlar = [];

    public function qoshing(int $mahsulotId, Pul $narx, int $soni): void
    {
        if ($soni < 1) {
            throw new InvalidArgumentException('Soni kamida 1 bo\'lishi kerak');
        }

        if (isset($this->elementlar[$mahsulotId])) {
            $this->elementlar[$mahsulotId]['soni'] += $soni;
            return;
        }

        $this->elementlar[$mahsulotId] = ['narx' => $narx, 'soni' => $soni];
    }

    public function ochiring(int $mahsulotId): void
    {
        unset($this->elementlar[$mahsulotId]);
    }

    public function jami(): Pul
    {
        $yigindi = Pul::nol();

        foreach ($this->elementlar as $element) {
            $yigindi = $yigindi->qoshing($element['narx']->kopaytiring($element['soni']));
        }

        return $yigindi;
    }

    public function boshmi(): bool
    {
        return $this->elementlar === [];
    }
}
PHP
use PHPUnit\Framework\TestCase;

final class SavatTest extends TestCase
{
    public function test_yangi_savat_bosh_boladi(): void
    {
        $savat = new Savat();

        $this->assertTrue($savat->boshmi());
        $this->assertEquals(0, $savat->jami()->tiyin);
    }

    public function test_mahsulot_qoshilganda_jami_hisoblanadi(): void
    {
        $savat = new Savat();
        $savat->qoshing(1, Pul::somdan(100_000), 2);

        $this->assertFalse($savat->boshmi());
        $this->assertEquals(200_000, $savat->jami()->som());
    }

    public function test_bir_xil_mahsulot_soni_qoshiladi(): void
    {
        $savat = new Savat();
        $savat->qoshing(1, Pul::somdan(50_000), 2);
        $savat->qoshing(1, Pul::somdan(50_000), 3);

        $this->assertEquals(250_000, $savat->jami()->som());
    }

    public function test_manfiy_soni_xato_beradi(): void
    {
        $savat = new Savat();

        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Soni kamida 1');

        $savat->qoshing(1, Pul::somdan(50_000), -1);
    }

    public function test_ochirilgan_mahsulot_jamiga_kirmaydi(): void
    {
        $savat = new Savat();
        $savat->qoshing(1, Pul::somdan(100_000), 1);
        $savat->qoshing(2, Pul::somdan(200_000), 1);

        $savat->ochiring(1);

        $this->assertEquals(200_000, $savat->jami()->som());
    }
}
Terminal
vendor/bin/phpunit tests/SavatTest.php
Natija
PHPUnit 11.2.0 by Sebastian Bergmann and contributors.

.....                                                     5 / 5 (100%)

Time: 00:00.024, Memory: 6.00 MB

OK (5 tests, 8 assertions)

AAA tuzilishi #

PHP
public function test_chegirma_qollanadi(): void
{
    // Arrange - tayyorlash
    $savat = new Savat();
    $savat->qoshing(1, Pul::somdan(100_000), 5);
    $chegirma = new FoizChegirmasi(10);

    // Act - amal
    $jami = $chegirma->qollang($savat->jami());

    // Assert - tekshirish
    $this->assertEquals(450_000, $jami->som());
}
Har bir testda uchta bosqich
  1. Arrange - boshlang'ich holatni tayyorlash
  2. Act - tekshiriladigan amalni bajarish
  3. Assert - natijani tekshirish

Gherkin dagi Given-When-Then bilan bir xil g'oya.

Agar testda ikkita "Act" bo'lsa - ehtimol uni ikkita testga bo'lish kerak.

Yaxshi test qanday bo'ladi? #

FIRST prinsiplari
HarfMa'nosiIzoh
FFastTez - millisoniyalarda
IIndependentMustaqil - tartibga bog'liq emas
RRepeatableTakrorlanuvchi - har doim bir xil natija
SSelf-validatingO'zi baholaydi - o'tdi yoki o'tmadi
TTimelyO'z vaqtida - kod bilan birga yoziladi
PHP
// YOMON: mustaqil emas
private static array $malumot = [];

public function test_birinchi(): void
{
    self::$malumot[] = 'a';
    $this->assertCount(1, self::$malumot);
}

public function test_ikkinchi(): void
{
    self::$malumot[] = 'b';
    $this->assertCount(2, self::$malumot);   // birinchi testga bog'liq!
}
PHP
// YOMON: takrorlanmaydigan
public function test_chegirma(): void
{
    $chegirma = new BayramChegirmasi();

    // Bugun bayram bo'lsa o'tadi, aks holda o'tmaydi
    $this->assertEquals(10, $chegirma->foiz());
}

// YAXSHI: vaqt kiritiladi
public function test_navroz_kunida_chegirma_beriladi(): void
{
    $chegirma = new BayramChegirmasi(new DateTimeImmutable('2026-03-21'));

    $this->assertEquals(10, $chegirma->foiz());
}
Testda tasodifiy qiymat ishlatmang
PHP
$narx = rand(1000, 100000);      // test goh o'tadi, goh o'tmaydi

Agar test bugun o'tib, ertaga o'tmasa - uni tuzatish deyarli imkonsiz.

Aniq qiymatlarni ishlating yoki seed o'rnating.

Nomlash #

PHP
// YOMON
public function test1(): void { }
public function testSavat(): void { }
public function testJami(): void { }

// YAXSHI - nom nima tekshirilayotganini aytadi
public function test_bosh_savatda_jami_nolga_teng(): void { }
public function test_bir_xil_mahsulot_ikki_marta_qoshilsa_soni_yigiladi(): void { }
public function test_manfiy_soni_berilganda_istisno_tashlanadi(): void { }
public function test_zaxira_yetmasa_buyurtma_yaratilmaydi(): void { }
Nom shabloni
Natija
test_<shart>_<kutilgan natija>

Test o'tmaganda uning nomi muammoni tushuntirishi kerak - kodga qarash shart bo'lmasin.

Parametrlangan testlar #

PHP
/**
 * @dataProvider chegirmaHolatlari
 */
public function test_chegirma_togri_hisoblanadi(
    int $jami,
    string $daraja,
    int $kutilgan,
): void {
    $hisoblagich = new ChegirmaHisoblagichi();

    $natija = $hisoblagich->hisoblang(Pul::somdan($jami), $daraja);

    $this->assertEquals($kutilgan, $natija->som());
}

public static function chegirmaHolatlari(): array
{
    return [
        'oddiy mijoz chegirmasiz'   => [100_000, 'oddiy',  0],
        'kumush 5 foiz'             => [100_000, 'kumush', 5_000],
        'oltin 10 foiz'             => [100_000, 'oltin',  10_000],
        'nol summa'                 => [0,       'oltin',  0],
        'katta summa'               => [10_000_000, 'oltin', 1_000_000],
    ];
}
Natija
OK (5 tests, 5 assertions)
Nomlangan holatlar

Massiv kalitlari test nomiga qo'shiladi:

Natija
Failed: test_chegirma_togri_hisoblanadi with data set "oltin 10 foiz"

Bu qaysi holat buzilganini darhol ko'rsatadi.

Soxta obyektlar #

Test dublyorlari turlari Dummy Faqat parametr to'ldirish uchun, ishlatilmaydi Stub Oldindan belgilangan javob qaytaradi Fake Ishlaydigan soddalashtirilgan versiya Mock Chaqirilganini tekshiradi Spy Chaqiruvlarni yozib boradi Haqiqiy obyekt Imkon bo'lsa - eng yaxshi tanlov Amalda ko'pincha Stub va Fake yetarli Mock ni kam ishlating - u testni kod tuzilishiga bog'lab qo'yadi
Soxta obyekt - tashqi bog'liqlikni almashtiruvchi
PHP
final class BuyurtmaServisi
{
    public function __construct(
        private BuyurtmaRepozitoriyi $repozitoriy,
        private OmborServisi $ombor,
        private XabarnomaInterfeysi $xabarnoma,
    ) {}

    public function yarating(int $mijozId, array $elementlar): Buyurtma
    {
        foreach ($elementlar as $element) {
            if (!$this->ombor->yetarlimi($element['id'], $element['soni'])) {
                throw new ZaxiraYetarliEmas($element['id']);
            }
        }

        $buyurtma = $this->repozitoriy->saqlang(
            Buyurtma::yangi($mijozId, $elementlar)
        );

        $this->xabarnoma->buyurtmaYaratildi($buyurtma);

        return $buyurtma;
    }
}
PHP
final class BuyurtmaServisiTest extends TestCase
{
    public function test_zaxira_yetmasa_istisno_tashlanadi(): void
    {
        // Stub - belgilangan javob qaytaradi
        $ombor = $this->createStub(OmborServisi::class);
        $ombor->method('yetarlimi')->willReturn(false);

        $servis = new BuyurtmaServisi(
            $this->createStub(BuyurtmaRepozitoriyi::class),
            $ombor,
            $this->createStub(XabarnomaInterfeysi::class),
        );

        $this->expectException(ZaxiraYetarliEmas::class);

        $servis->yarating(1, [['id' => 42, 'soni' => 5]]);
    }

    public function test_buyurtma_yaratilganda_xabar_yuboriladi(): void
    {
        $ombor = $this->createStub(OmborServisi::class);
        $ombor->method('yetarlimi')->willReturn(true);

        $repozitoriy = $this->createStub(BuyurtmaRepozitoriyi::class);
        $repozitoriy->method('saqlang')->willReturnArgument(0);

        // Mock - chaqirilganini tekshiradi
        $xabarnoma = $this->createMock(XabarnomaInterfeysi::class);
        $xabarnoma->expects($this->once())
                  ->method('buyurtmaYaratildi');

        $servis = new BuyurtmaServisi($repozitoriy, $ombor, $xabarnoma);

        $servis->yarating(1, [['id' => 42, 'soni' => 2]]);
    }
}

Fake - ko'pincha eng yaxshi tanlov #

PHP
final class XotiradaBuyurtmaRepozitoriyi implements BuyurtmaRepozitoriyi
{
    private array $buyurtmalar = [];
    private int $keyingiId = 1;

    public function saqlang(Buyurtma $buyurtma): Buyurtma
    {
        $id = $buyurtma->id ?? $this->keyingiId++;
        $saqlangan = $buyurtma->idBilan($id);
        $this->buyurtmalar[$id] = $saqlangan;

        return $saqlangan;
    }

    public function toping(int $id): ?Buyurtma
    {
        return $this->buyurtmalar[$id] ?? null;
    }

    public function mijozBoyicha(int $mijozId): array
    {
        return array_values(array_filter(
            $this->buyurtmalar,
            fn (Buyurtma $b) => $b->mijozId === $mijozId,
        ));
    }
}
Fake - Mock dan yaxshiroq
MockFake
SozlashHar testdaBir marta yoziladi
Test o'qilishiSozlash bilan to'lganToza
RefaktoringdaBuziladiIshlayveradi
Haqiqiy xatti-harakatYo'qHa

Ko'p testda ishlatiladigan bog'liqlik uchun Fake yozing.

Mock ni haddan tashqari ishlatmang
PHP
// Bu test nimani tekshiryapti?
$a = $this->createMock(A::class);
$b = $this->createMock(B::class);
$c = $this->createMock(C::class);
$a->method('x')->willReturn($b);
$b->method('y')->willReturn($c);
$c->method('z')->willReturn(42);

$this->assertEquals(42, $servis->hisobla());

Bu test kod tuzilishini tekshiradi, xatti-harakatni emas. Refaktoring qilsangiz - test buziladi, garchi kod to'g'ri ishlasa ham.

Bunday test foydadan ko'ra zarar keltiradi.

Integratsiya testi #

PHP
final class BuyurtmaRepozitoriyiTest extends TestCase
{
    private PDO $pdo;
    private MysqlBuyurtmaRepozitoriyi $repozitoriy;

    protected function setUp(): void
    {
        $this->pdo = new PDO('sqlite::memory:');
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->exec(file_get_contents(__DIR__ . '/../database/sxema.sql'));

        $this->repozitoriy = new MysqlBuyurtmaRepozitoriyi($this->pdo);
    }

    public function test_saqlangan_buyurtma_topiladi(): void
    {
        $buyurtma = Buyurtma::yangi(mijozId: 1);
        $buyurtma->elementQoshing(new Mahsulot(42, 'Klaviatura', Pul::somdan(250_000)), 2);

        $saqlangan = $this->repozitoriy->saqlang($buyurtma);
        $topilgan = $this->repozitoriy->toping($saqlangan->id);

        $this->assertNotNull($topilgan);
        $this->assertEquals(500_000, $topilgan->jami()->som());
        $this->assertCount(1, $topilgan->elementlar());
    }

    public function test_mavjud_bolmagan_buyurtma_null_qaytaradi(): void
    {
        $this->assertNull($this->repozitoriy->toping(99999));
    }
}
Har bir test toza bazadan boshlansin

Uchta yondashuv:

  1. Xotiradagi SQLite - eng tez, lekin MySQL dan farq qiladi
  2. Tranzaksiya - har testdan keyin rollBack()
  3. Docker konteyner - haqiqiy MySQL, sekinroq

Ishlab chiqarishda MySQL ishlatsangiz, integratsiya testlarida ham MySQL ishlatish yaxshiroq - SQLite ba'zi farqlarni yashiradi.

API testi #

PHP
final class BuyurtmaApiTest extends TestCase
{
    public function test_buyurtma_yaratish_201_qaytaradi(): void
    {
        $javob = $this->post('/api/v1/buyurtmalar', [
            'elementlar' => [['mahsulot_id' => 42, 'soni' => 2]],
            'manzil_id'  => 5,
        ], ['Authorization' => 'Bearer ' . $this->token()]);

        $this->assertEquals(201, $javob->kod());
        $this->assertArrayHasKey('id', $javob->json()['malumot']);
        $this->assertEquals('yangi', $javob->json()['malumot']['holat']);
    }

    public function test_avtorizatsiyasiz_401_qaytaradi(): void
    {
        $javob = $this->post('/api/v1/buyurtmalar', []);

        $this->assertEquals(401, $javob->kod());
    }

    public function test_notogri_malumot_422_qaytaradi(): void
    {
        $javob = $this->post('/api/v1/buyurtmalar', [
            'elementlar' => [['mahsulot_id' => 42, 'soni' => -5]],
        ], ['Authorization' => 'Bearer ' . $this->token()]);

        $this->assertEquals(422, $javob->kod());
        $this->assertEquals('validatsiya_xatosi', $javob->json()['xato']['kod']);
    }
}

E2E testi #

JavaScript
// tests/e2e/buyurtma.spec.js
import { test, expect } from '@playwright/test';

test('foydalanuvchi buyurtma bera oladi', async ({ page }) => {
    await page.goto('/kirish');
    await page.fill('[name="email"]', '[email protected]');
    await page.fill('[name="parol"]', 'sinovParoli123');
    await page.click('button[type="submit"]');

    await page.goto('/katalog');
    await page.click('[data-test="mahsulot-42"] [data-test="savatga-qoshish"]');

    await expect(page.locator('[data-test="savat-soni"]')).toHaveText('1');

    await page.goto('/savat');
    await page.click('[data-test="buyurtma-berish"]');

    await page.selectOption('[name="manzil_id"]', '5');
    await page.click('[data-test="tasdiqlash"]');

    await expect(page.locator('[data-test="muvaffaqiyat"]')).toBeVisible();
    await expect(page).toHaveURL(/\/buyurtmalar\/\d+/);
});
data-test atributlarini ishlating
HTML
<button class="btn btn-primary" data-test="savatga-qoshish">Savatga</button>

CSS klasslar dizayn o'zgarganda o'zgaradi. data-test esa faqat testlar uchun - u barqaror qoladi.

E2E testlar beqaror bo'lishi mumkin

Sabablari: tarmoq kechikishi, animatsiya, asinxron yuklash.

Yechimlar:

JavaScript
// YOMON: qat'iy kutish
await page.waitForTimeout(2000);

// YAXSHI: shartni kutish
await expect(page.locator('[data-test="natija"]')).toBeVisible();

Doimiy beqaror testni o'chiring - u jamoaning testlarga ishonchini yo'qotadi.

Qoplama #

Terminal
vendor/bin/phpunit --coverage-html hisobot/
vendor/bin/phpunit --coverage-text
Natija
Code Coverage Report:

 Summary:
  Classes: 68.42% (13/19)
  Methods: 81.25% (78/96)
  Lines:   84.31% (612/726)

App\Domen\Savat
  Methods: 100.00% ( 8/ 8)   Lines: 100.00% ( 42/ 42)
App\Servislar\BuyurtmaServisi
  Methods:  85.71% ( 6/ 7)   Lines:  91.30% ( 63/ 69)
App\Infratuzilma\EmailYuboruvchi
  Methods:   0.00% ( 0/ 4)   Lines:   0.00% (  0/ 31)
Qoplama - foydali, lekin yetarli emas
PHP
public function bolish(int $a, int $b): float
{
    return $a / $b;
}

public function test_bolish(): void
{
    $this->assertEquals(5, $this->hisoblagich->bolish(10, 2));
}

100% qoplama - lekin nolga bo'lish tekshirilmagan.

Qoplama nimaning testlanmaganini ko'rsatadi, lekin testlanganning yaxshi testlanganini kafolatlamaydi.

Amaliy maqsad
QismMaqsad
Biznes mantiq (domen, servislar)90%+
Kontrollerlar70%+
Infratuzilma (adapterlar)50%+
Umumiy70-80%

100% ga intilish - vaqtni behuda sarflash. Muhim qismlarga diqqat qiling.

Nimani testlash kerak? #

Ustuvorlik tartibi
  1. Biznes qoidalari - eng muhim
  2. Chekka holatlar: bo'sh, nol, manfiy, juda katta
  3. Xato yo'llari - istisnolar to'g'ri tashlanadimi
  4. Tuzatilgan xatolar - qaytmasligi uchun
  5. Murakkab algoritmlar
  6. Integratsiyalar - tashqi tizimlar bilan
Nimani testlamaslik kerak
  • Getter va setter lar
  • Freymvork kodi (u allaqachon testlangan)
  • Tashqi kutubxonalar
  • Oddiy konfiguratsiya
  • Faqat return qiladigan metodlar

Bunday testlar vaqt oladi, lekin hech nima kafolatlamaydi.

Testlarni tashkil qilish #

Natija
tests/
├── Modul/
│   ├── Domen/
│   │   ├── SavatTest.php
│   │   ├── PulTest.php
│   │   └── BuyurtmaTest.php
│   └── Servislar/
│       └── BuyurtmaServisiTest.php
├── Integratsiya/
│   ├── Repozitoriylar/
│   └── Api/
├── E2E/
├── Yordamchilar/
│   ├── XotiradaBuyurtmaRepozitoriyi.php
│   └── BuyurtmaQuruvchi.php
└── bootstrap.php
PHP
// Test ma'lumotlarini yaratish uchun quruvchi
final class BuyurtmaQuruvchi
{
    private int $mijozId = 1;
    private BuyurtmaHolati $holat = BuyurtmaHolati::Yangi;
    private array $elementlar = [];

    public static function yangi(): self
    {
        return new self();
    }

    public function mijoz(int $id): self
    {
        $this->mijozId = $id;
        return $this;
    }

    public function holat(BuyurtmaHolati $holat): self
    {
        $this->holat = $holat;
        return $this;
    }

    public function element(int $mahsulotId, int $narx, int $soni = 1): self
    {
        $this->elementlar[] = compact('mahsulotId', 'narx', 'soni');
        return $this;
    }

    public function quring(): Buyurtma
    {
        // ...
    }
}
PHP
public function test_tolangan_buyurtmani_bekor_qilish_mumkin(): void
{
    $buyurtma = BuyurtmaQuruvchi::yangi()
        ->holat(BuyurtmaHolati::Tolangan)
        ->element(42, 250_000, 2)
        ->quring();

    $buyurtma->bekorQiling('Mijoz so\'radi');

    $this->assertEquals(BuyurtmaHolati::Bekor, $buyurtma->holat());
}
Test ma'lumotlari quruvchisi

Testda faqat muhim ma'lumotni ko'rsating, qolganini standart qiymatlar to'ldirsin.

Test o'qiganda "bu yerda holat muhim" ekani darhol ko'rinadi.

Amaliy topshiriq
  1. Savat klassini yozing va unga 8 ta modul testi yozing.
  2. AAA tuzilishiga rioya qiling.
  3. Chekka holatlarni testlang: bo'sh savat, nol soni, manfiy soni.
  4. Parametrlangan test yozing (dataProvider bilan).
  5. Tashqi bog'liqlik uchun Stub yarating.
  6. Xotiradagi Fake repozitoriy yozing.
  7. Baza bilan integratsiya testi yozing.
  8. API endpoint uchun test yozing (200, 401, 422 holatlari).
  9. Qoplama hisobotini yarating va testlanmagan qismlarni toping.
  10. Test ma'lumotlari quruvchisini yozing.

Xulosa #

  • Test - kod ishlashining yagona ishonchli dalili.
  • Test piramidasi: ko'p modul, kam integratsiya, juda kam E2E.
  • Teskari piramida ("muzqaymoq") - sekin va beqaror testlarga olib keladi.
  • AAA: Arrange, Act, Assert.
  • FIRST: tez, mustaqil, takrorlanuvchi, o'zi baholaydigan, o'z vaqtida.
  • Test nomi nima tekshirilayotganini aytsin.
  • dataProvider bilan bir xil mantiqni ko'p holatda tekshiring.
  • Fake ko'pincha Mock dan yaxshiroq - test refaktoringda buzilmaydi.
  • Mock ni haddan tashqari ishlatish testni kod tuzilishiga bog'laydi.
  • E2E testlarda data-test atributlarini ishlating.
  • Qoplama nimaning testlanmaganini ko'rsatadi, sifatni emas.
  • Getter, freymvork va kutubxona kodini testlamang.

Keyingi bo'limda TDD yondashuvini o'rganamiz.

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.