Test sınıfları ve yöntemleri
Pytest, test işlevleri yazmanın yanı sıra sınıfları kullanmanıza da olanak tanır. Daha önce de belirttiğimiz gibi devralma gerekmez ve test sınıfları birkaç basit kurala uyar. Sınıfların kullanılması size daha fazla esneklik ve yeniden kullanılabilirlik sağlar. Daha sonra gördüğünüz gibi, Pytest engelden uzak durur ve sizi belirli bir şekilde test yazmaya zorlamaktan kaçınıyor.
İşlevlerde olduğu gibi deyimini assert kullanarak onaylar da yazabilirsiniz.
Test sınıfı oluşturma
Şimdi test sınıflarının nasıl yardımcı olabileceğini görmek için gerçek dünya senaryolarını kullanalım. Aşağıdaki işlev, belirli bir dosyanın içeriğinde "evet" olup olmadığını denetler. Bu durumda döndürür True. Dosya yoksa veya içeriğinde "hayır" varsa döndürür False. Bu senaryo, tamamlanma durumunu belirtmek için dosya sistemini kullanan zaman uyumsuz görevlerde yaygındır.
İşlev şöyle görünür:
import os
def is_done(path):
if not os.path.exists(path):
return False
with open(path) as _f:
contents = _f.read()
if "yes" in contents.lower():
return True
elif "no" in contents.lower():
return False
Şimdi, test_files.py adlı bir dosyada iki test içeren bir sınıfın (her koşul için bir tane) nasıl göründüğü aşağıda verilmiştir:
class TestIsDone:
def test_yes(self):
with open("/tmp/test_file", "w") as _f:
_f.write("yes")
assert is_done("/tmp/test_file") is True
def test_no(self):
with open("/tmp/test_file", "w") as _f:
_f.write("no")
assert is_done("/tmp/test_file") is False
Dikkat
Örnek için kullanımı daha kolay olduğundan test yöntemleri geçici bir test dosyası için /tmp yolunu kullanır. Ancak, geçici dosyaları kullanmanız gerekiyorsa, sizin için güvenli bir şekilde oluşturabilecek (ve kaldırabilen) gibi tempfile bir kitaplık kullanmayı göz önünde bulundurun. Her sistemin bir /tmp dizini yoktur ve bu konum işletim sistemine bağlı olarak geçici olmayabilir.
Ayrıntılılığı artırmak için testleri bayrağıyla -v çalıştırmak testlerin geçtiğini gösterir:
pytest -v test_files.py
============================= test session starts ==============================
Python 3.9.6, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
cachedir: .pytest_cache
rootdir: /private/
collected 2 items
test_files.py::TestIsDone::test_yes PASSED [ 50%]
test_files.py::TestIsDone::test_no PASSED [100%]
============================== 2 passed in 0.00s ===============================
Testler geçse de tekrarlı görünür ve ayrıca test tamamlandıktan sonra dosya bırakırlar. Bunları nasıl geliştirebileceğimizi görmeden önce, sonraki bölümde yardımcı yöntemleri ele alalım.
Yardımcı yöntemler
Bir test sınıfında, test yürütmesini ayarlamak ve yok etmek için kullanabileceğiniz birkaç yöntem vardır. Pytest, tanımlandıkları takdirde bunları otomatik olarak yürütür. Bu yöntemleri kullanmak için belirli bir düzen ve davranışa sahip olduklarını bilmeniz gerekir.
-
setup: Bir sınıftaki her test öncesinde bir kez yürütür. -
teardown: Bir sınıftaki her test sonrasında bir kez yürütülür. -
setup_class: Bir sınıftaki tüm testlerden önce bir kez yürütür. -
teardown_class: Bir sınıftaki tüm testlerden sonra bir kez çalıştırılır.
Testlerin çalışması için benzer (veya aynı) kaynaklar gerektiğinde, kurulum yöntemlerini yazmak yararlı olur. İdeal olarak, bir test tamamlandığında kaynak bırakmamalıdır, bu nedenle yırtma yöntemleri bu durumlarda test temizlemeye yardımcı olabilir.
Temizleme
Şimdi her test sonrasında dosyaları temizleyen güncelleştirilmiş bir test sınıfına bakalım:
class TestIsDone:
def teardown(self):
if os.path.exists("/tmp/test_file"):
os.remove("/tmp/test_file")
def test_yes(self):
with open("/tmp/test_file", "w") as _f:
_f.write("yes")
assert is_done("/tmp/test_file") is True
def test_no(self):
with open("/tmp/test_file", "w") as _f:
_f.write("no")
assert is_done("/tmp/test_file") is False
yöntemini kullandığımızdan teardown() , bu test sınıfı artık geride bir /tmp/test_file bırakmıyor.
Ayarlama
Bu sınıfta gerçekleştirebileceğimiz bir diğer geliştirme de dosyaya işaret eden bir değişken eklemektir. Dosya artık altı yerde bildirildiğinden, yolda yapılan tüm değişiklikler bu noktaların tamamında değiştirilecek anlamına gelir. Bu örnek, sınıfın yol değişkenini bildiren ek setup() bir yöntemle nasıl göründüğünü gösterir:
class TestIsDone:
def setup(self):
self.tmp_file = "/tmp/test_file"
def teardown(self):
if os.path.exists(self.tmp_file):
os.remove(self.tmp_file)
def test_yes(self):
with open(self.tmp_file, "w") as _f:
_f.write("yes")
assert is_done(self.tmp_file) is True
def test_no(self):
with open(self.tmp_file, "w") as _f:
_f.write("no")
assert is_done(self.tmp_file) is False
Özel yardımcı yöntemleri
Bir sınıfta özel yardımcı yöntemler oluşturabilirsiniz. Bu yöntemlerin adı test ön eklenmemelidir ve kurulum veya temizleme yöntemleri olarak adlandırılamaz.
TestIsDone sınıfında, özel bir yardımcıda geçici dosya oluşturmayı otomatikleştirebiliriz. Bu özel yardımcı yöntemi şu örneğe benzer olabilir:
def write_tmp_file(self, content):
with open(self.tmp_file, "w") as _f:
_f.write(content)
Pytest yöntemi otomatik olarak yürütmez write_tmp_file() ve diğer yöntemler bir dosyaya yazma gibi yinelenen görevleri kaydetmek için doğrudan çağırabilir.
Özel yardımcıyı kullanmak için test yöntemlerini güncelleştirdikten sonra sınıfın tamamı şu örneğe benzer:
class TestIsDone:
def setup(self):
self.tmp_file = "/tmp/test_file"
def teardown(self):
if os.path.exists(self.tmp_file):
os.remove(self.tmp_file)
def write_tmp_file(self, content):
with open(self.tmp_file, "w") as _f:
_f.write(content)
def test_yes(self):
self.write_tmp_file("yes")
assert is_done(self.tmp_file) is True
def test_no(self):
self.write_tmp_file("no")
assert is_done(self.tmp_file) is False
İşlev yerine bir sınıf ne zaman kullanılır?
bir işlev yerine bir sınıfın ne zaman kullanılacağına dair kesin bir kural yoktur. Çalışmakta olduğunuz mevcut projelerde ve ekiplerde yer alan kuralları izlemek her zaman iyi bir fikirdir. Bir sınıfı ne zaman kullanacağınızı belirlemenize yardımcı olabilecek bazı genel sorular şunlardır:
- Testlerinizin benzer kurulum veya temizleme yardımcı koduna ihtiyacı var mı?
- Testlerinizi birlikte gruplandırma mantıklı mı?
- Test paketinizde en az birkaç test var mı?
- Testleriniz ortak bir yardımcı işlev kümesinden yararlanabilir mi?