Using unittest For Test Driven Development

Python Testing Your Code

SU

Test-Driven Development (TDD) uchun unittest’dan Foydalanish

Python’da unittest moduli mavjud bo'lib, u sizga kodlaringiz uchun unit testlarini yozish imkonini beradi. Unit test — bu eng kichik kod bo'lagi bo'lib, qolgan qismdan ajratilgan holda sinovdan o‘tkaziladi. Avvalgi bo‘limdagi add() funksiyasini ko‘rib chiqsak, siz ikki musbat sonni qo‘shish yoki manfiy va musbat sonni qo‘shish testlarini yozishingiz mumkin. Ammo siz bu ikki holatni bir xil unit testda tekshirmaysiz.

Dasturlashda mashhur bir tushuncha mavjud bo‘lib, uni Test-Driven Development (TDD) deb ataladi. TDDning maqsadi shundaki, siz kod yozishni boshlashdan oldin testni yozasiz va uni xato bo‘lishiga qaratilgan holda boshlaysiz. Asosiy tushuncha shundan iboratki, siz dasturingizning amalga oshirilishi va uni qanday test qilishni o‘ylab, kod yozishni boshlaysiz.

TDD jarayoni haqida umumiy tushuncha:

  • Xato (Fail): Birinchi navbatda, oddiy test yozasiz va uni ishga tushirasiz. Bu test darhol xato bo‘lishi kerak, chunki hali funktsional kod yozilmagan.
  • O‘tish (Pass): Keyingi qadam — testni o‘tadigan kod yozish. Shundan so'ng, yuqoridan boshlanadi va yangi test yoziladi, u ham boshlanishida xato bo‘lishi kerak. Shunday qilib, testlarni yozish va ularni o‘tqazadigan kodni yozish jarayoni takrorlanadi.

TDDni amaliyotda o‘rganish uchun Code kata (kod kata)dan foydalanish mumkin. Code katar — bu aniq dasturlash tushunchasini chuqur o‘rganishga qaratilgan kodlash qiyinchiliklari.

Eng mashhur kod kata-lardan biri "FizzBuzz" deb ataladi. Bu dasturlash intervyularida ham mashhur savol hisoblanadi. FizzBuzz konsepti quyidagicha:

  • 1 dan 100 gacha sonlarni ekranga chiqaradigan dastur yozing.
  • Har bir son uchun, agar u 3 ga bo‘linadigan bo‘lsa, sonning o‘rniga "Fizz" chiqarilsin.
  • Har bir son uchun, agar u 5 ga bo‘linadigan bo‘lsa, sonning o‘rniga "Buzz" chiqarilsin.
  • Agar son 3 va 5 ga bir vaqtning o‘zida bo‘linadigan bo‘lsa, sonning o‘rniga "FizzBuzz" chiqarilsin.

Endi bu mashhur qiyinchilikni olib, Test-Driven Development (TDD)ni qo‘llab, yechim va testlarni yozamiz.

Fizz Test

Birinchi qadam — testlarni joylashtirish uchun papka yaratish. Buning uchun fizzbuzz nomli papka yaratib, kodni shu papkaga joylashtirasiz.

Ko‘pincha testlarni test yoki tests nomli kichik papkada saqlashadi va testlarni ishga tushiruvchi (test runner) dasturga yuqori darajadagi papkani sys.pathga qo‘shishni aytishadi, shunda testlar import qilinishi mumkin. Testlarni doimiy ravishda ishga tushiruvchi dasturni ishlatishni bu holatda o'tkazib yuborsak bo‘ladi.

Endi fizzbuzz papkasi ichida test_fizzbuzz.py nomli test faylini yaratib, unga quyidagilarni yozamiz:

import fizzbuzz
import unittest
 
class TestFizzBuzz(unittest.TestCase):
    def test_multiple_of_three(self):
        self.assertEqual(fizzbuzz.process(6), 'Fizz')
 
if __name__ == '__main__':
    unittest.main()

Bu yerda fizzbuzz modulini import qilasiz, bu kodni sinovdan o‘tkazasiz. So‘ngra Pythonning unittest modulini import qilasiz. unittestni ishlatish uchun siz unittest.TestCase()dan subclass yaratishingiz kerak. Shundan so'ng, siz bajarilishi kerak bo‘lgan testlarni ifodalovchi funksiyalarni yaratishingiz mumkin. Bu misolda, test_multiple_of_three() funksiyasini yaratib, assertEqual() yordamida fizzbuzz.process(6) chaqirig‘idan "Fizz" qaytishini test qilasiz.

Hozirda bu testni ishga tushirsangiz, ModuleNotFoundError xatosini olasiz, chunki fizzbuzz mavjud emas. Buni tuzatish uchun fizzbuzz.py nomli bo‘sh fayl yaratish kerak. Bu faqat ModuleNotFoundErrorni hal qiladi, lekin testni ishga tushirishingizga imkon beradi.

Testni quyidagicha ishga tushirishingiz mumkin:

python test_fizzbuzz.py

Testni ishga tushirganda quyidagi chiqish ko‘rsatiladi:

E
======================================================================
ERROR: test_multiple_of_three (__main__.TestFizzBuzz)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_fizzbuzz.py", line 7, in test_multiple_of_three
    self.assertEqual(fizzbuzz.process(6), 'Fizz')
AttributeError: module 'fizzbuzz' has no attribute 'process'
 
----------------------------------------------------------------------
Ran 1 test in 0.000s
 
FAILED (errors=1)

Bu xato fizzbuzz modulida process() funksiyasi yo‘qligini bildiradi. Bu xatoni tuzatish uchun fizzbuzz.py fayliga quyidagilarni qo‘shing:

def process(number):
    pass

Endi testni qayta ishga tushirsangiz, quyidagicha chiqish ko‘rsatiladi:

F
======================================================================
FAIL: test_multiple_of_three (__main__.TestFizzBuzz)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_fizzbuzz.py", line 7, in test_multiple_of_three
    self.assertEqual(fizzbuzz.process(6), 'Fizz')
AssertionError: None != 'Fizz'
 
----------------------------------------------------------------------
Ran 1 test in 0.000s
 
FAILED (failures=1)

Python default qiymat sifatida Noneni qaytaradi. Lekin bu funksiya Fizz qaytarishi kerak. Keling, kodni yangilab, quyidagi tarzda yozamiz:

def process(number):
    if number % 3 == 0:
        return 'Fizz'

Endi testni ishga tushirsangiz, quyidagi chiqish ko‘rsatiladi:

.
======================================================================
Ran 1 test in 0.000s
 
OK

Buzz Test

Ikkinchi test — bu 5 ning ko‘paytmalari uchun to‘g‘ri javobni tekshirishdir. Yangi test qo‘shish uchun, TestFizzBuzz() sinfida yangi metod yaratishingiz mumkin:

import fizzbuzz
import unittest
 
class TestFizzBuzz(unittest.TestCase):
    def test_multiple_of_three(self):
        self.assertEqual(fizzbuzz.process(6), 'Fizz')
 
    def test_multiple_of_five(self):
        self.assertEqual(fizzbuzz.process(20), 'Buzz')
 
if __name__ == '__main__':
    unittest.main()

Bu safar, test faqat 5 ga bo‘linadigan, ammo 3 ga bo‘linmaydigan sonni tekshirishi kerak. Ishlaydigan holatda, fizzbuzz.process() "Buzz"ni qaytarishi kerak. Agar hozirda testni ishga tushirsangiz, quyidagi chiqish ko‘rsatiladi:

F.
======================================================================
FAIL: test_multiple_of_five (__main__.TestFizzBuzz)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_fizzbuzz.py", line 10, in test_multiple_of_five
    self.assertEqual(fizzbuzz.process(20), 'Buzz')
AssertionError: None != 'Buzz'
 
----------------------------------------------------------------------
Ran 2 tests in 0.000s
 
FAILED (failures=1)

Bu kodni yangilash uchun process() funksiyasini quyidagicha o‘zgartiring:

def process(number):
    if number % 3 == 0:
        return 'Fizz'
    elif number % 5 == 0:
        return 'Buzz'

Endi testni qayta ishga tushirsangiz, quyidagi chiqish ko‘rsatiladi:

..
======================================================================
Ran 2 tests in 0.000s
 
OK

FizzBuzz Test

Uchinchi test esa, agar son 3 va 5 ga bir vaqtda bo‘linadigan bo‘lsa, "FizzBuzz"ni qaytarishini tekshirishdir. Bu testni qo‘shish uchun, TestFizzBuzz sinfiga yangi metod qo‘shing:

import fizzbuzz
import unittest
 
class TestFizzBuzz(unittest.TestCase):
    def test_multiple_of_three(self):
        self.assertEqual(fizzbuzz.process(6), 'Fizz')
 
    def test_multiple_of_five(self):
        self.assertEqual(fizzbuzz.process(20), 'Buzz')
 
    def test_fizzbuzz(self):
        self.assertEqual(fizzbuzz.process(15), 'FizzBuzz')
 
if __name__ == '__main__':
    unittest.main()

Testni ishga tushirganda:

...
======================================================================
Ran 3 tests in 0.000s
 
OK

Bunday tarzda siz, testlar orqali dasturga kiritilgan yangi funksiyalarni tekshirib borishingiz mumkin.

Xulosa

Endi siz Test-Driven Development (TDD) jarayonini to‘liq o‘rgandingiz. Har bir testdan keyin kodni yozish va testni muvaffaqiyatli bajarilishi uchun kodni o‘zgartirish qadamlarini amalga oshirdik. TDD dastur yozishda sifatni oshiradi va dasturdagi xatolarni erta aniqlashga yordam beradi.

Last updated on

On this page

Xato haqida xabar berish