28 Nisan 2020

Kaliteli Test Kodu Geliştirmek ve Test Smell Oluşumunu Engellemek

Önceki makalelerde (1,2) test smell konusuna bir giriş yapmış ve bunların türlerinden örnekler vererek bahsetmiştik. Bu makalede nasıl kaliteli test kodu yazılır ve test smell oluşumu engellenir konularından bahsedeceğiz.

Önceki makalelerde (1,2) test smell konusuna bir giriş yapmış ve bunların türlerinden örnekler vererek bahsetmiştik. Bu makalede nasıl kaliteli test kodu yazılır ve test smell oluşumu engellenir konularından bahsedeceğiz.

Aşağıda birim testi geliştirme prensipleri, test kodlarının okunabilirliği, sürdürülebilirliği ve güvenilirliği ile ilgili öneriler verilmiştir. Ayrıca test smell oluşumunu engellemek için stratejiler ve tavsiyeler verilmektedir.

Birim testi geliştirirken dikkat edilmesi gereken temel prensiplerden en önemlileri aşağıda listelenmiştir.

  1. Yazdığınız testin amacını, neyi test ettiğini net bir şekilde belirleyin.
    1. Bu çok basit bir ilke gibi gözükse de her zaman uygulanması o kadar basit değil.
    2. Bu tip test kodları genellikle uzun, anlaşılması zor ve birden fazla durumu test eden kodlar oluyor (Assertion Roulette, Eager Test).
    3. Birçok durumu test eden kodlar aynı test metodu içerisinde bulunuyor ve bu o metodun karmaşık (complex test) ve kırılgan (fragile/indeterministic test) olmasına sebep oluyor.
    4. Eğer bir geliştirici test metodunu isimlendirmekte zorlanıyorsa, bu o test metodunun amacının tam net olmadığını gösterir.
    5. Her senaryo için bir test metodu yazmak o metodu daha okunabilir hale getirir ve bir test geçmemişse bunun sebebini anlamak ve sorunu çözmek uzun ve karmaşık bir metoda göre daha kolay olacaktır.
  2. İyi bir birim testi dış bağımlılıklardan izole edilmiş testtir.
    1. Bir test olabildiğince, ortam ayarları, yazmaç değerleri, veri tabanları gibi dış etkilerden bağımsız olmalıdır.
  3. Testler kararlı (deterministic) davranmalı.
    1. Örneğin aşağıdaki test metodu farklı bilgisayar donanımları ve farklı işletim sistemlerinde aynı sonucu üretmeyebilir. Test bazen başarılı, bazen başarısız olabilir.

                                                                    

  1. Test metodunu isimlendirirken metot isimlendirme kurallarına uyulmalı, anlaşılır bir isim verilmeli. Bu                        sayede test kaldığında, o testin ne amaçla yazıldığını ve problemin sebebini ilk bakışta anlayabiliriz.
    1. Örneğin aşağıda iki sayının bölme işlemleri için 3 farklı metoda isimlendirme yapılmış. İlk test metodunun isminden sıfır ile bölme işleminin test edildiğini hemen anlayabiliyoruz.

             

Test Smell Oluşum Yaşam Döngüsü

Testlerin mantığının olabildiğince basit olması ve içerisindeki karar yapılarının (if, switch-case, vs.) mümkün olduğunca az olması, aynı işlemi ya da kodu tekrarlayan (duplitation, redundancy) test kodlarından kaçınılması, testlerin olabildiğince kısa tutulması ve test kodlarına gözden geçirme yapılması gerekir. Ayrıca, gerçek (actual) ve beklenen (expected) değerlerin karşılaştırıldığı “assertion” satırlarının        karmaşık olmaması, bunların aynı satırda bulunması, beklenen değer için değişken kullanılmaması ve karmaşık test kodlarından da kaçınılması gerekmektedir.

Okunabilirlik ile ilgili öneriler;

  • Factory metotları kullanmak,
  • Bir testte sadece bir şeyi test etmek,
  • Anlamlı ve tutarlı isimlendirme yapmak,
  • Assertion için anlaşılır mesajlar yazmak,
  • Assertion yapılan satırda herhangi bir işlemi, “magic string”leri bulundurmamak veya bir değeri girdi olarak bu satırda almamak; bunları ayrı adımlarda yapmak,
  • Birbirleri ile ilişkili testleri bulmayı kolay hale getirmek.

 Sürdürülebilirlik (maintainability) ile ilgili öneriler;

  • Testler birbirinden izole ve tekrar edilebilir olmalı,
  • Testler herkese açık, ulaşılabilir olmalı,
  • Mock işlemi mümkün olduğunca dikkatli ve anlaşılır yapılmalı.

 Testin güvenilirliği ile ilgili öneriler;

  • Testler koşul ya da dinamik değerler içermemeli,
  • Test verileri değiştirilerek kapsam (coverage) kontrolü yapılmalı,
  • Test verileri sabit değerler olmalı,
  • Assertion satırlarında beklenen değerler dinamik olarak oluşturulan değerler olmamalı.

 Genel olarak çalışmalarda yapılan gözlem ve bulgulara göre test smell oluşumunu engellemek için aşağıdaki stratejiler ve tavsiyeler verilmiştir:

  • Test Sınıflarını içerisindeki test metot sayısını azaltarak olabildiğinde küçük tutmaya çalışın.
  • Miras (İnheritance) yapılarını düzgün tutmaya çalışın ve süper class’ların amacını sınırlamaya çalışın (diğer tüm base Test Sınıfları için fonksiyonellik sağlayan bir Süper Sınıf oluşturmaya çalışmayın).
  • Test sınıflarına yardımcı fonksiyonellik (Helper Functions) katmak için Kalıtım yerine Birleşim (Composition Over Inheritance) kullanın.
  • Test girdileri sağlamak için veri sağlayan sınıflar oluşturun (Sadece tek bir test için kullanılacak alan-field tanımlaması yaparak test sınıflarına aşırı yüklenmeyi engellemek için). Bu hem testin performansını hem de okunabilirliği artıracaktır.
  • Test Sınıfı header bölümünde field tanımlaması yapmak test performansını ve okunabilirliğini etkileyecektir. Bu konuya dikkat etmeye çalışın.
  • Eğer bir test sınıfı içerisindeki metotlar, test edilen sistemin (System Under Test) çeşitli durum ve konfigürasyonlarını kullanması gerekiyorsa her bir sınıf için Tek Test Sınıfı (one test class per class) düzenini göz önünde bulundurun.
  • Seçtiğiniz Fixture stratejisinin sonuçları ve bu kararın projeye etkisini de hesaba katın. Genellikle strateji değişimi pek mümkün olmamaktadır.

 Proven Test Hizmetleri Ekipleri; Entegre Test Yönetimi Yaklaşımı, Bağımsız Test ve Dış Kaynak Hizmetleri ile müşterilerinin yazılım ve bilişim alanındaki ürün ve hizmetlerinin kalitesini arttırmak için alternatif çözümler sağlamaktadır. Konuyla ilgili sorularınız için bkucuk@proven.com.tr adresine e-posta atarak ulaşabilirsiniz.

Barış KÜÇÜK

Daha fazla bilgi edinebileceğiniz kaynaklar;

The Art Of Unit Testing

In Ruby, Java & .NET By Roy Osherove - Official Book Site

http://artofunittesting.com/

The Tao of Testing

http://jasonpolites.github.io/tao-of-testing/ch4-1.1.html#chapter-4-how-to-write-tests

Improving Generation of Object-Oriented Test Suites by Avoiding Redundant Tests

https://www.researchgate.net/publication/2913308_Improving_Generation_of_Object-Oriented_Test_Suites_by_Avoiding_Redundant_Tests

Strategies for Avoiding Text Fixture Smells during Software Evolution

https://www.researchgate.net/publication/261480205_Strategies_for_avoiding_text_fixture_smells_during_software_evolution

 

Kaynaklar

[1]   V. Garousi B. Küçük "Smells in software test code: A survey of knowledge in industry and academia" Journal of Systems and Software vol. 138 2018. 

[2]   V. Garousi and B. Küçük, "The Entire Classification of Test Smells" in https://goo.gl/1ZrL65, Last accessed: Sept. 2018