Test Case Geliştirme İpuçları ve Püf Noktaları

Ozi's
Colendi
Published in
9 min readFeb 2, 2024

Bu makalede test case oluşturmanın püf noktaları nelerdir, yazarken nelerden kaçınılmalı, koşarken nelere dikkat edilmeli gibi soruların cevaplarını kendi deneyimim doğrultusunda sizlere aktaracağım. Keyifli okumalar 😊

Öncelikle biraz terminolojiden bahsetmek istiyorum, kavramlar kafamızda netleştikten sonra örnekler ile adım adım konuyu detaylandıracağım. İlk başlığımız ile başlayalım.

Test Case, Test Senaryo ve Test Script

Test senaryoları, kullanıcı bakış açısı ile tetiklenebilecek fonksiyonlar dikkate alınarak oluşturulur. Bu sebeple biçim açısından use caselere benzetilebilir. Bir uygulamadaki giriş yapma ekranının fonksiyonları için hazırlanabilecek test senaryolarına örnek verelim:

  • Geçerli e-mail ve geçerli şifre ile sisteme giriş yapıldığında sistemin davranışının kontrol edilmesi.
  • Geçersiz e-mail ve geçerli şifre ile sisteme giriş yapıldığında sistemin davranışının kontrol edilmesi.

Ek olarak, iş planlandığı zaman eforu hesaplamak, işe daha geniş çerçeveden bakabilmek ya da steakholderlara test kapsamını göstermek gibi ihtiyaçlar doğduğunda test senaryolarından faydalanılabilir.

Test caseler ise ürünün belli bir fonksiyonunu ya da özelliğini test etmek için oluşturulur. Test senaryolarından farklı olarak test caseler daha detaylı şekilde hazırlanır ve daha küçük kapsamları ifade eder. Her bir case başlığı ayrı bir bütün olarak ele alınır. Her başlığın -bütünün- içinde case’in stepleri, steplerin beklenen çıktısı, step’te ihtiyaç duyulan test datası gibi alanlar bulunmaktadır.

Test case ve test senaryosu konuşma dili ile oluşturulurken test scriptleri otomasyon testlerini koşmak için kullanılan kodlama dilleri ile oluşturulur. Kaliteli test scriptleri yazabilmek için teknik bilginin yanında kaliteli test caseler oluşturabiliyor olmak elzemdir. Çünkü testin yöntemi ne olursa olsun amaç en doğru kapsamı belirlemektir.

Test scriptleri hakkında daha fazla bilgi edinmek isterseniz Postman’de API Test Scripti Yazmak başlıklı yazıma göz atabilirsiniz.

Bu üç kavram hakkında daha fazla bilgi edinmek isterseniz ise Test Case Vs Test Script ve How to Write Test Cases with Examples başlıklı makalelere göz atabilirsiniz.

Test Case Nasıl Hazırlanır?

Aşağıdaki görselde bir test case örneği görmektesiniz.

Test Case Template

Bu görseldeki alanları açıklayarak ilerleyelim:

  • Created by — Reviewed by: Testi oluşturan ve review eden kişileri ifade eder. Reviewed by alanı case güncellendikten sonra da kullanılabilir.
  • Test Case Description: Test case’inin başlığı, kısa açıklamasıdır.
  • Test Data Requirement: Case’de kullanılan, ihtiyaç duyulan data’yı eklemek için kullanılan alandır.
  • Prerequisities: Testi koşmak için ihtiyaç duyulan ön koşulları ifade eder.
  • Step Details: Her bir adımın açıklamasının yapıldığı alandır.
  • Expected Results: Step’in beklenen sonucu ifade eder.
  • Actual Results: Step’i koştuktan sonra alınan sonucu ifade eder.
  • Pass/ Fail/ Not executed / Suspended: Step’in son durumunu ifade eder.
  • Test case (Pass/Fail/ Not executed): Test case’inin son durumunu ifade eder.

Test Case Geliştirmede Dikkat Edilmesi Gereken Noktalar

Temel kavramlara ve terminolojiye değindiğimize göre test case geliştirme süreçlerinde dikkat edilmesi gereken noktalara maddeler halinde cevap vermeye başlayalım.

Senaryoları iş kapsamı netleştiğinde yazmaya başlamak

Bu maddenin kaliteli ve kapsamı doğru belirlenmiş caseler oluşturmadaki en önemli unsur olduğunu düşünüyorum. Scrum çalışma mantığından örnek vererek gidelim. Groominglerde, tüm ekip birlikteyken ve iş detayları yeni öğrenilirken hazırlanan caseler tüm paydaşların fikirleri ölçüsünde şekillenmiş olur. Bunun yanında biz test mühendislerinin aktif katılımcı olması, işin kalite ve güvencesinin (Quality Assurance) iş ekibe indirildiği andan itibaren yapılmasına olanak sağlar. Bu da olası hataların ya da yanlışların önüne geçmenin en etkili yollarından biridir. (bkz. shift left testing) Son olarak case oluşturmak iş geliştirme sürecine yayılmış olduğu için iş teste geldiğinde birkaç ufak güncelleme ile execute etmeye hazır olur. Böylelikle işin ‘test ediliyor’ durumunda kalma süresi fark yaratacak düzeyde kısalmış olur.

Test caseleri ve raporlamayı tüm paydaşların anlayacağı şekilde yazmak

Test caseler, işe hakim olmayan ya da teknik bilgisi kısıtlı olan herhangi birisi baktığında kafasında bir şeylerin canlanabileceği şekilde yazılmalıdır. Bunu sağlayabilmek için case’in başlığını, steplerini, ön koşullarını kısaca her bir parçasını sade ve anlaşılır şekilde yazmak önemlidir. Bunun yanında her bir adım; adıma ait ekran görüntüsü, test datası gibi kanıtlar ile desteklenmelidir. İş temposunun yoğun olduğu zamanlarda bile mümkün oldukça bu noktalara riayet edilmelidir. Çünkü bu şekilde hem geriye dönük olarak caselerin anlaşılırlığı sağlanır hem de ileriye dönük olarak kullanılabilirliği arttırılmış olur.

Bazı durumlarda caselerin içeriği yapılmak istenen işin detayını anlamak için yeterli olmayabilir. Örneğin A servisi hata caselerinde HTTP status’ü 200 dönüyor diyelim. Bunun sebebi de A servisinin beslediği B servisinin yalnızca 200 status kodlu bir cevap aldığında çalışması olsun. A servisin test caselerine bakan birisi servisin hata durumlarında HTTP status’ü 200 dönmesinin sebebini bilmediğinden dolayı neden bu şekilde testten geçtiğini anlamayabilir. Bunun gibi case içeriğinde açıklanamayan durumları test tamamlanırken yazılan raporlama kısmında açıklamamız gerekir.

Bir test dökümanın hedefini net bir şekilde tanımlayan bir cümle paylaşmak istiyorum:

Test dokümanı, en iyi test kapsamını sağlamalı, mükemmel okunabilirlik sunmalı ve baştan sona tek bir standart formata uymalıdır.

Test edilecek iş için hazırlanmış görsel ve metinsel dökümanlardan destek almak

Use case ve geliştirici notları gibi dökümanlardan yararlanmak test caseleri olgunlaştırabilmek için gerekli kaynaklardır. Eğer bu konuda eksiklik var ise caseleri kaliteli şekilde yazabilmek için ekipten ihtiyaç duyulan dökümanları talep etmek gerekir.

Bunun yanında, use case ve geliştirici notlarına bağlı kalmayıp bir test uzmanı gözü ile döküman oluşturmak, ileriye dönük ihtiyaçları karşılamak açısından faydalı olacaktır. Basit bir örnek vermek gerekirse, bir kargo takip uygulamasında kargonun; hazırlanıyor, şubeye ulaştı, kurye yola çıktı gibi bir çok statüsü bulunuyor diyelim. Vaktinde tüm statülerin bulunduğu bir döküman hazır ettiysek statüleri etkileyen bir geliştirme teste geldiğinde elimiz rahat olacaktır. Çünkü takdir edersiniz ki hazır dökümandan destek alıp caseleri oluşturmak her bir statüyü hatırlayıp oluşturmaktan çok daha verimli bir yoldur.

Caseleri, kırılma noktalarını göz önüne alarak oluşturmak

Bir e-ticaret sitesinin satın alma akışı test edeceğimizi varsayalım. Kullanıcı satın al butonuna bastığında çalışan satın alma servisi ilk olarak satın almayı gerçekleştiren provider’ın servisine istek atıyor. Ordan gelen cevaba göre de satın alma bizim sistemimizde tamamlandı durumuna geçiyor. Akışın daha net oturması için aşağıdaki görseli inceleyebilirsiniz:

Görselde iki tane kırmızı renkli çizgi bulunmakta. Bu çizgiler başlıkta bahsettiğim kırılma noktalarını ifade etmekte. Görüldüğü üzere bu çizgiler, akışta bağımlı fakat işleyiş olarak birbirinden bağımsız servislerin arasındaki iletişim noktalarının üzerine çekilmiş. Eğer bu noktalarda gerçekleşen iletişimde sorun meydana gelirse tüm akış bozulur. Bu sebeple caseleri bu noktalar üzerine yoğunlaştırmak gerekir.

Kırılma noktaları için hazırlanacak caseler aşağıda bulunan örneklerdeki gibi çeşitlendirilebilir.

İlk kırılma noktasına gelince test edilecek bazı caseler:

  • Satın alma servisinin provider’ın servisine başarılı şekilde istek göndermesi.
  • Satın alma servisine dolayısı ile provider’ın servisine paralel istek atılması.
  • Satın alma servisinin provider’ın servisine istek gönderirken hata vermesi.

İkinci kırılma noktası ile üçüncü kırılma noktası arasında test edilebilecek bazı caseler:

  • Provider servisinden başarılı istek gelmesi.
  • Provider servisinden hata alınması.
  • Provider servisinden timed out alınması.
  • Provider servisinden cevap dönmemesine rağmen işlemin başarı ile tamamlanması.

Üçüncü kırılma noktasının ardından test edilebilecek bazı test caseleri:

  • Provider servisinden gelen başarılı response ile satın alma işleminin başarı ile tamamlanması.
  • Provider servisinden gelen başarısız response ile satın alma işlemi tamamlanırken hata oluşması.

Ekip arkadaşları ile case review yapmak

Özellikle kritik ve karmaşık işlerin test edileceği zamanlar test ekibindeki diğer arkadaşlarımızın deneyiminden ve bakış açısından faydalanmak kapsamı oluştururken bize fayda sağlayabilir. Hatta işi az bilen bir kişi, sürekli işin içinde olmaktan dolayı göz ardı edebileceğimiz caseleri bulmakta bize destek olabilir. Ek olarak test kapsamı konusunda developer ve product ownerlardan destek alınabilir. Bunun da en güzel yolu daha önce bahsettiğim gibi grooming vb. ritüellere aktif katılım sağlamaktır.

Riskli olabilecek yerleri belirleyip caseleri oraya yoğunlaştırmak

Riskten kastım kodda hataya eğilimli yerleri tahmin etmek; domain’in kritik, hataya açık yerlerini belirlemek ve caseleri oralara yoğunlaştırmaktır. Takdir edileceği üzere bu, zamanla ve deneyim ile kazanılacak bir beceridir. İş yürütme süreçlerindeki her bir detayı derinlemesine inceleyip çıkarımda bulunmak bu edinimi kazanmakta kritik rol oynayacaktır.

Caseleri önceliğe göre oluşturmak

Önceliklendirme, hangi test caselerinin koşulacağını işin önemine, işlevlerine ve yazılım üzerindeki potansiyel etkilerine göre belirlemek anlamına gelir. Örneğin, Borsa İstanbul hisseleriyle ilgili işlem yapabileceğimiz bir uygulamamız olsun. Ve uygulamanın hisse alış/satış ekranındaki test caseleri için önceliklendirme yapacağız diyelim. Bu caseler arasında hisse satın alma, hisse satma ve işlem iptali gibi işlemler ile ilgili olan caseler, satın alma butonunun fontu, rengi ve boyutu gibi görsel özellikleri için hazırlanacak test caselerinden daha önceliklidir. Çünkü bir kullanıcının para akışında yaşayacağı sorunun somut etkisi görsel bir soruna göre çok daha büyük olacaktır. Bunun yanında önceliklendirme yaparken developarlar ve stakeholderlar ile işbirliği yapmak önceliklendirmeyi kolaylaştırır.

Önceliklendirme hakkında daha fazla detay öğrenmek isterseniz şu linkteki makaleye göz atabilirsiniz.

Mevcut senaryolardan faydalanmak

Test senaryoları test eforunu gösteren dokümantasyon görevi görür. Elimizde böyle bir dökümantasyon varken bundan yararlanmak akıllıca olacaktır.

Yine bir örnek üzerinden gidelim. Daha öncesinde e-ticaret sitemize A bankasının alışveriş kredisi seçeneğini entegre etmiş olalım. Yeni işimiz ise B bankasının alışveriş kredisi sistemini entegre etmek olsun. Bu sefer işimiz ilkine göre çok daha kolay olacaktır çünkü bi önceki işten elimize örnek caseler kalmıştır. Halihazırdaki caseleri B bankasının entegrasyon işinin senaryolarına göre revize edersek hızlı bir şekilde test kapsamını oluşturmuş oluruz.

Postman üzerinden test scripti oluşturmak

Bir kaç farklı servisi bulunduran ve test esnasında bu servisler arasında sık sık dolaşmayı gerektiren bir iş önünüze geldi diyelim. Hazırlık aşamasında ilgili iş için bir Postman collection hazırlayıp ona executionları hızlandıracak birkaç script eklemek hayat kurtarıcı olacaktır. Hazırlanacak collection sayesinde o id’yi bu servise yapıştır, bu response’taki şu veriyi kopyala gibi basit görünen ama execution’ı hatırı sayılır düzeyde yavaşlandıran işlemleri ortadan kaldırmış oluruz.

Script yazmak ve Postman ile test otomasyonu hakkında daha fazla bilgi edinmek isterseniz Postman’de API Test Scripti Yazmak başlıklı yazıma göz atabilirsiniz.

Test Case Geliştirmenin Yanlışları

Doğrulara değindik şimdi de nelerden kaçınmamız gerektiğine maddeler halinde bakalım.

Caseleri fazla basit ya da fazla kompleks tutmak

Test caseler spesifik bir hedefe sahip olmalı, bu hedef sade ve açık bir dile açıklanmalı, açıklanırken geniş zaman ve üçüncü şahıs dili kullanılmalıdır. Casele adımlarına birkaç örnek verelim:

Case’in içeriği gibi başlığı da anlaşılır ve insanın kafasında içeriğe dair ışık yakacak şekilde olmalıdır. Başlığa bakan birisi case’in neyi amaçladığını net bir şekilde anlayabilmelidir.

Caselerin birbirine bağımlılığı belli bir düzeyde olmalıdır. Bir case’in bütünlüğünün öncesindeki ve sonrasındaki caselere bağımlı olmasından olabildiğince kaçınılmalıdır. Çünkü bağımlılık sağlayan koşulların fazla olması kompleks caselere yol açar. Bu da anlaşılırlığı zorlaştırır.

Caseleri koşarken bağımlılıklara fazla takılı kalmak

Bağımlılık, geliştirilen feature’un çalışırken başka sistemlere bağımlı olma durumudur. Bu gibi featureları test ederken feature’u bağımlılıklardan ayrıştırarak caseleri oluşturmak ve case’i bağımlılıktan dolayı bloklamamak gereklidir. Çünkü boş yere konan bir blok execution süresini gereksiz uzatır dolayısıyla zamanı verimsiz kullanmış oluruz.

Yine bir örnek üzerinden gidelim. Bir cron test etmemiz gereken servisi tetikliyor diyelim. Testlerimiz esnasında da cron’da bir problem oluştuğunu gözlemledik. Bu durumda cron çalışmıyor diye testleri bloklamak yerine cron düzelene kadar servise başka yöntemler ile istek atarak caseleri koşmak zaman yönetimi bakımından çok daha verimli olacaktır. Elbette cron düzeldikten sonra akışı olması gereken hali ile test etmeyi unutmamak şartı ile.

Caseler koşulurken aynı veri setini kullanmak

Sürekli aynı veri seti ile caseleri koşmak olası hataların bir kısmını kaçırmaya sebep olur. Örneğin hem tam hem de ondalıklı sayı kabul etmesi beklenen ‘tutar’ adında key’i bulunan bir servisimiz olsun. Bu servisin testini sadece tam sayı bulunan veri seti ile gerçekleştirdik diyelim. Ardından canlı ortamda bu servisi çağıran özellik kullanılmaya başlanıyor. Kullanıcılar tarafından fark ediliyor ki ‘tutar’ parametresi ondalıklı sayı kabul etmiyor. Hata bu şekilde ortaya çıktığı zaman olumsuz bir kullanıcı deneyimine sebebiyet vermiş oluruz. Bu gibi durumları yaşamamak için tüm olası caseleri kapsama dahil etmemiz gerekmektedir.

Sürekli aynı veri setini kullanmak tüm olası durumları kaçırmanın yanında yazılım testinin 7 ilkesinden antibiyotik direnci denen duruma yol açacaktır. Sürekli aynı veri seti ve aynı caseler koşulursa test edilen sistem kullanılan caselere ve veri setine bağışıklık kazanacaktır. Bunun önüne geçmek için belirli aralıklar ile veri setini ve caseleri değiştirmek gerekir.

Olası durumları belirlerken aralığı, servisin beklenen sınırları baz alarak (sınır değer analizi yaparak) belirlemek en mantıklısı olacaktır. Diyelim ki yukarıdaki servisin tutar parametresinin alabileceği en yüksek değer 100, en düşük değer ise 0. O zaman veri setini üst sınırlar 99.99/100/100.01, alt sınırlar 0.01/0/0.01 olacak şekilde belirlemek en verimlisi olacaktır.

Eğer API testleri yapıyorsanız Postman’in random variable üreten kütüphanesi işinize yarayabilir. Bu kütüphane bir çok farklı türde (Ad soyad, adres, uuid, sayı…) veri generate ediyor ve değişken olarak kullanımımıza sunuyor.

Birleştirilmiş stepler, birleştirilmiş caseler

Bir uygulamanın ödeme önizlemesi ve ödeme yapma ekranını test edeceğiz diyelim. Bu ekranda iki servisimiz bulunmakta, ödeme önizlemesi servisi ve ödeme servisi. Caseleri yazarken iki servis de aynı ekranda kullanılıyor diye servislerin aksiyonlarını bir stepte gösterirsek üstünkörü bir case dökümanı hazırlamış oluruz. Servislerin her bir aksiyonu için ayrı step hatta ihtiyaç halinde ayrı case kullanılmalıdır.

Aynı örnekten devam edelim. Bakiye yetersizken ödeme yapmak ve bakiye yeterliyken ödeme yapmak iki ayrı case başlığıdır. Bunları birleştirip ‘Önce yetersiz bakiye ile ödeme yapmaya çalışılır sonra yeterli bakiye ile ödeme yapılır’ gibi bir case hazırlamak case’i fazla komplike yapar. Bunun yerine bunları iki ayrı case olarak ele almak daha doğru olacaktır.

Diyelim ki bu sefer ödeme sonrasında işlem listeleme sayfasını test edeceğiz. Yine ödeme önizlemesi ve ödeme yapma servislerini detaylı şekilde açıklamak mı gerekir? Açıkçası bu sefer bu akışları bir stepte ya da ön koşul olarak göstermenin daha doğru olacağını düşünüyorum. Çünkü test kapsamında olmayan bu stepleri uzun uzun anlatmak caseleri gereksiz komplike hale getirecektir.

--

--