Python Unittest Modülü Giriş

Python_Unittest_Intro

Python unittest

  • Yazılım projeleri büyüdükçe geliştirme ve maintain(devamlılığı sağlamak) etmek zorlaşmaktadır. Bunun yanısıra projede herhangi bir değişiklik (refactoring, yeni modül, özellik(feature) ekleme vb.) yapıldıkça değişikliklerin var olan sistemi etkilemediğinden yani bozmadığından emin olmamız gerekmektedir. Binlerce satır kod yüzlerce fonksiyonun olduğu bir projeyi elle test etmek pek akıllıca değil. Zaman israfının yanında herhangi bir yeri unutmadığımızdan emin olmanın garantisi de yok. Sözü fazla uzatmadan yazılım projelerinde unit test yaparak zaman israfının ve "acaba ?"ların önüne geçebiliyoruz.
  • Yazılım projelerinde test konusuna yeni başladığım için ve öğretirken daha fazla öğrendiğime inandığım için bu makaleyi yazmayı istedim.
  • Şimdi aşağıdaki örnek ile başlayalım. dort_islem.py adında bir modül var elimizde.
  • Örnek projemiz bu basit modül olsun. Şimdi test_dort_islem.py adında bir dosya oluşturup aşağıdaki kodu ekleyelim.
  • Çalıştırmak için python 3.X versiyonunu kullanıyoruz.
  • Eğer python3 test_dort_islem.py yazarsanız terminalden herhangi bir şey göremeyeceksiniz.
  • python3 -m unittest test_dort_islem.py diyerek çalıştıralım. Sonuç aşağıdaki gibi bir çıktı ise tebrikler! ilk testinizi başarıyla yaptınız.
  • Yani bu basit kodu print(topla(44,46)) diyerek test ederdim, ne gerek var bu kadar şeye demeyin. Peki ne yaptık ki burada? Zaten durum belli, sonuç belli...
  • Senaryoyu şöyle düşünelim: "Topla metodundan daha büyük ve karmaşık yüzlerce binlerce metod arasından bir metodu refactoring yaptık veya bu metod şu datayı da versin gibi bir değişiklik yaptık.". Yapılan değişiklik sistemi etkilememiştir değil mi ? diye endişelenmemek için python3 -m unittest benim_guzel_projemin_guzel_modulu.py diyerek test ediyoruz ve rahatlıyoruz.
  • Hata verirse ne güzel işte! Yaptığımız değişiklik sonucunda sistemi etkileyen ve önceden doğru düzgün veriyi döndüren metod artık vermiyor, sebebi de budur diyen bir yardımcımız var. Hiç hata vermediyse zaten "on numara değişiklik yapmışsın helal!" derler(belki).

Test metodlarının isimleri test_method_adi gibi test kelimesi ile başlamalıdır. Yoksa unittest modülü testi çalıştırmayacaktır.

Daha fazla Test
  • Şimdi test_dort_islem.py dosyasını biraz daha geliştirelim.
  • Bu dosyayı python3 test_dort_islem.py diyerek çalıştırırsanız. Aşağıdaki gibi bir çıktı alacaksınız.
  • Dört nokta (. . . .), dört adet test metodu olduğunu gösteriyor ve hepsi başarıyla testi geçti.
Biraz da hata mesajı görelim
  • dort_islem.py içerisinde çarpma metodunu aşağıdaki gibi değiştirelim.
  • Sonuç
  • İşte böyledir dünya... diye edebiyat yapmaya başlamayalım. Elin oğlu veya siz gelip projede bir metodu değiştirdiniz. Yanarlı dönerli bir metod olacaktı ancak bir de bakıyorsunuz çarşı karışmış. Neyse ki unittest ile önceden test yazmıştınız da böyle sıkıntılar geliştirme(development) sürecinden gerçek projeye(production) geçmeden yakaladınız.
  • Hala elimle test ederdim diyorsanız siz bilirsiniz :)
Vay be unit test çok iyiymiş!
  • Diyecekken, "kul yapısı illaki eksik gedik olur" sözünü unutmuyoruz. Aşağıdaki durumu da göz önüne alalım. Önce dort_islem.py dosyasında aşağıdaki değişikliği yapalım.
  • Şimdi test_dort_islem.py dosyasında aşağıdaki senaryoları test edelim.
def test_bolme(self):
        self.assertEqual(dort_islem.bol(44, 2), 22)
        self.assertEqual(dort_islem.bol(44, -11), -4)
        self.assertEqual(dort_islem.bol(-44, -4), 11)
  • Değişiklik bu senaryolar için bir hata oluşturmadı ancak aşağıdaki satır eklenirse
  • self.assertEqual(dort_islem.bol(5, 2), 2.5) # yeni senaryo
  • Sonuç
adnan@ce:~/Desktop/blogpost/testce$ python3 test_dort_islem.py 
F...
======================================================================
FAIL: test_bolme (__main__.TestDortIslem)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dort_islem.py", line 25, in test_bolme
    self.assertEqual(dort_islem.bol(5, 2), 2.5) # yeni senaryo
AssertionError: 2 != 2.5 # İŞTE HATA BURADA

----------------------------------------------------------------------
Ran 4 tests in 0.001s

FAILED (failures=1)

  • Yukarıdaki durumdan çıkaracağımız ders: Olabildiğince kıyı köşede kalmış durumlar, beklenmeyen durumlar için de test senaryosu yazmak gereklidir
  • Yani her zaman kullanıcılardan bekleyeceğimiz senaryo ile test etmemek gerekli.

TRY TO HACK YOUR PROJECT! :D

Sona gelirken
  • hep assertEqual çalıştık. Yeni bir şey deneyelim. **Bölme metodunu eski haline return x/y döndürelim. Şimdi aşağıdaki senaryoyu deneyelim.
#test_dort_islem.py

 def test_bolme(self):
        self.assertEqual(dort_islem.bol(44, 2), 22)
        self.assertEqual(dort_islem.bol(44, -11), -4)
        self.assertEqual(dort_islem.bol(-44, -4), 11)
        self.assertEqual(dort_islem.bol(5, 2), 2.5) # yeni senaryo
        # Sıfıra bölünme hatası bekliyorum
        self.assertRaises(ValueError, dort_islem.bol, 44,0)
  • Çalıştıralım ve sonuç:
  • Sıfıra bölünmez tabii ki hata üretti. Biz de hata bekliyorduk beklediğimizi aldık ve test başarıyla geçildi.

Sonuç

Sağda solda Unit Testing, Yazılımda Test vb. sözlerini çok duyarız. Buna neden ihtiyacımız var diye merak etmeye kalmadan kendi web projemde gerçekten ihtiyaç olmaya başlayınca başlangıç seviyesinde bir giriş yaptım ve ben de testlerimi yazmaya başladım. Profesyonel yazılım projelerinde test olmazsa olmaz hale gelmiştir. Umarım önce bana sonra da sizlere faydası olur bu makalenin... Öğrendikçe paylaşmaya devam edeceğim inşallah.

Faydalı kaynaklar

Müthiş bir test eğitimi için lütfen sabırla izleyiniz:

 

 

 

Yorumlar