RxSwift’e Küçük Bir Başlangıç Bölüm 3: RxTest ve RxBlocking

Ayşe Nur Bakırcı
Delivery Hero Tech Hub
4 min readJan 3, 2022
Image from raywenderlich.com

Herkese tekrar merhaba. Önceki yazılarımda RxSwift ve RxCocoa ile reaktif kod yazdık. Sıra bu kodları test edebilmemiz için oluşturulmuş yapıları incelemeye geldi. :) Bunlar RxTest ve RxBlocking! Bu yazımda reactive kodların nasıl test edileceğini anlatacağım.

— RxBlocking

RxBlocking, bir observable’ı BlockingObservable’a dönüştürerek bize sonuç verir. Bu yüzden RxBlocking kullanmadan önce BlockingObservable’ın ne olduğunu anlamamız, bu yapıyı kullanmamızı da kolaylaştıracaktır.

  • BlockingObservable: BlockingObservable, dizi tamamlanana kadar veya zaman aşımı oluşana kadar observable’ın çalıştığı iş parçacığını bloke eden yapıdır. Bu da asenkron işlemlerin testlerini daha kolay hale getirir. BlockingObservable’ları yalnızca testte değil kodun diğer kısımlarında da kullanabiliriz ancak bu durum asenkron çalışmaya uygun olmadığı için doğru bir yaklaşım olmaz.

Bir observable’ı, BlockingObservable’a dönüştürmek için toBlocking() operatörünü kullanmamız yeterlidir.

Observable’ları blocking ile test ederken operatörleri de kullanabiliriz. Burada kod test edilirken kullanılan 3 farklı operatörden bahsedeceğim.

  • toArray: toArray observable’ın yaydığı tüm ögeleri bir dizi olarak almamızı sağlar. Bir observable’a gelen tüm ögelerin test edilmesi gerektiğinde bu yapıyı kullanabiliriz.
  • first: Observable’ın yaydığı ilk ögeyi almamızı sağlar. Bu yapıyı observable’ın öge yaymaya başlayıp başlamadığını test etmek istediğimizde kullanabiliriz.
  • last: Observable’ın yaydığı son ögeyi almamızı sağlar. Observable’ın tamamlanıp tamamlanmadığının kontrolünü last operatörü ile birlikte test edebiliriz.

toArray, first veya last operatörü kullanılırken bu operatörler herhangi bir öge bulamazsa NoSuchElementException hatasını, eğer ögeleri alabiliyorsak istediğimiz sonucu döndürür. Bu yüzden try ile birlikte kullanmamız gerekir.

RxBlocking kullanımı asenkron işlemlerin testlerini oldukça kolaylaştırır. Ancak bu yapının da bazı dezavantajları vardır.

  • Sonsuz observable’ları bekletemeyeceğimizden RxBlocking yapısını yalnızca sonlu observable’lar ile kullanabiliriz.
  • Observable’ları duraklattığımız için uzun sürede gerçekleşecek işlemler beklendiği için testlerin tamamlanma süresi de uzar.

— RxTest

Asenkron işlemleri test edebilmemizi sağlayan bir diğer kütüphane RxTest kütüphanesidir. RxBlocking kullanırken observable’ın bulunduğu zamanlayıcıyı dondurarak observable’ın ögelerini yaymasını bekliyorduk. Artık RxTest ile testleri de asenkron olarak ilerletmeye başlayabiliriz. Bu kütüphane içerisinde temel olarak kullanacağımız üç yapı mevcuttur.

  • Test Scheduler

TestScheduler ile asenkron dizilerin hangi zamanlarda hangi olayları yaydığını takip edebilir, bu olayların istediğimiz gibi yayılıp yayılmadığını kontrol edebiliriz.

Yukarıdaki örnekleri inceleyecek olursak;

  1. TestScheduler oluştururken kullandığımız initalClock’ın anlamı test scheduler’in başlangıç zamanıdır. Burada inital clock’ı sıfıra eşitlememiz test scheduler’ı testin başlangıç saatinde başlatmak istediğimizi gösterir.
  2. Scheduler üzerinde çalışacak bir observer oluşturabiliriz. Bu observer ile test etmek istediğimiz observer’ı birbirine bağlarsak (bind operatörü ile) test ettiğimiz observer’ın yaydığı tüm ögeleri, ögelerin yayıldığı zamanla birlikte kaydedebilmemizi sağlar.
  3. Scheduler üzerinde observable oluşturabiliriz. Bu observable istediğimiz zamanlarda, istediğimiz ögeleri yaymamızı sağlar. Bu sayede hangi olayın ne zaman yayılacağını söyleyip, buna uygun tepkiler alıp almadığımızı kontrol edebiliriz.
  4. Bir test scheduler oluşturduğumuzda, bu scheduler’ı kullanabilmek için her testte scheduler’ı başlatmamız gerekir. TestScheduler başlatılmadan olay yayamaz veya olayları takip edemeyiz.
  • Cold Observable ve Hot Observable

Asenkron testler yazılırken istediğimiz zamanlarda, istediğimiz ögeleri yayabilmek için observable oluşturduğumuzu söylemiştik. Bu observable’ları ihtiyacımıza göre iki farklı şekilde oluşturabiliriz.

Bunlardan ilki Cold Observable’dır. Cold observable’lar kullandığımız diğer observable’lar gibi olayları yayabilmek veya olayları takip edebilmek için aboneliğe ihtiyaç duyarlar. Asenkron işlemlerle, HTTP veya TCP bağlantıları gibi işlemler gerçekleştirilirken kullanılabilir.

İkinci observable ile Hot Observable’dır. Hot observable’lar öge yaymak veya ögeleri takip edebilmek için aboneliğe ihtiyaç duymazlar. Variable, property, constant, dokunma veya mouse koordinatları, UI kontrol değerleri vb. yapılarla kullanılabilir.

Şimdi de RxTest ile ilgili bir örnek zamanı. 🙂

Yukarıda, veriler yüklenirken gösterilen bir activity indicator’e bağlı loading observable’ının testi yapılmıştır. Bu testi adım adım inceleyelim.

  1. Test edeceğimiz loading observable yalnızca activity indicator’ın gösterilip gösterilmeyeceğini takip eder. Bu yüzden bool olarak tanımlanmıştır. Burada tipi bool olan bir observable’ı test edeceğimiz için yine bool tipinde bir observer tanımlarız.
  2. Kod içerisinde kullandığımız ve test edeceğimiz loading observable ile test scheduler üzerinde oluşturduğumuz observer’ı birbirine bağlarız. Bu işlem sonucunda loading’in aldığı olayları oluşturduğumuz observer’ı kullanarak zamanları ile birlikte takip edebiliriz.
  3. Kod içerisindeki loadData bizim verilerimizi yüklemek için kullandığımız tetikleyicidir. Void tipindedir ve her olay aldığında öncelikle loading observable’ına true değer gönderilir, sonrasında veriler alınır ve verilerin tamamı alındıktan sonra loading observable’ına false değer gönderilir. Burada scheduler üzerinde oluşturduğumuz observable’a 50. ve 100. zamanlarda iki farklı olay gönderip sonrasında bu olayların loading’i doğru şekilde etkileyip etkilemediğini kontrol edebiliriz.
  4. Biz observer ve observable’ımızı bir zamanlayıcı üzerinde tanımladık ve olayları bu zamanlayıcı üzerinden takip edeceğiz. Ancak ögeleri alıp almadığımızı kontrol etmeden önce olayların gerçekleşmesi ve bu olayları takip edebilmemiz için kullanacağımız scheduler’ı başlatmamız gerekir.
  5. Son olarak test etme kısmına geldik. Öncelikle son adımda gördüğünüz gibi loading’in beş olay almasını bekliyoruz. Bu beş olayın ilki loading’in başlangıç değeridir. Loading oluşturulurken verdiğimiz ilk değer false olduğu için 0. zamanda loading false değerini alır. Sonrasında 3. adımda oluşturduğumuz cold observable ile 50. zamanda bir olay gönderdiğimizi görüyoruz. Bu olay loadData’nın tetiklenmesini, dolayısıyla yükleme başladığı için loading’in true değer almasını sağlar. Bu sayede loading’in aldığı ikinci değerin 50. zamanda true olduğunu söyleyebiliriz. Yine aynı zamanda yükleme bittikten sonra loading false olacağı için üçüncü olay da 50. zamanda false olur. Bu işlemin aynısını testteki 100. zaman için de uygulanır. Burada next durumlarını test ettiğimiz gibi complete ve error durumlarını da test edebiliriz.

Bu yazımla birlikte RxSwift macerasını sonlandırmış bulunuyorum. 🙂 Bundan sonrası RxSwift ile kodlar yazıp RxTest ile test ederek bu konuları iyice anlamak diyebilirim.

Okuduğunuz için teşekkür ederim, herhangi bir fikriniz veya yorumunuz olursa benimle paylaşabilirsiniz. 🙂

--

--