Mock Kavramı ve GoogleMock (gMock) Nedir/Nasıl Kullanılır?

Birim (Unit) testleri yazarken sadece kendi içerisinde statik olarak uygulanan algoritmalarla çalışmayız, hatta çoğu zaman bu şekilde çalışmayız. Onun yerine diğer objelerle sürekli etkileşimde olan, gerçek zamanlı (real time) olarak işlemler gerçekleştiren şekilde tasarımlar yaparız. Benzer sistem tasarımlarının testlerini yazarken de her zaman gerçek objeler üzerinde çalışamayız. İşte tam olarak burada karşımıza kurtarıcı niteliğinde bir kavram çıkıyor, Mocking.

Mock kavramı anlamı itibarı ile taklit objeler oluşturmamıza izin vermektedir. Gerçek zamanlı testlerde karşılaşacağımız objelerin taklit edilen hallerini oluşturarak testimize dahil etmemize yarar. Bu yazıda üzerinde işlem gerçekleştireceğimiz Mock framework‘ü ise GoogleMock (gMock) olacak. Yazı içerisindeki anlatımların bir çoğunu YouTube kanalımda anlattığım GoogleTest video serisi içerisinden de ulaşabilirsiniz (Henüz yayınlanmadı).

Mock objeleri ile diğer diller üzerinde çalışırken sizin için işin bir kısmını otomatikleştiren araçlar olduğunu görebilirsiniz. GoogleMock (gMock) da C++ dili özelinde bu işi yapan bir araç olarak Google tarafından tasarlanmıştır. Kullanılacak olan komponentin arayüz üzerindeki davranışlarını tespit etmek için kullanılırlar.


GoogleMock Nasıl Kullanılır?

Bu konudaki en özenle hazırlanmış ve detaylı kaynak olarak Google‘ın kendi dokümantasyonunu örnek verebiliriz. İlgili linklere “Kaynaklar” kısmında ulaşabilirsiniz.

Bir örnek üzerinden anlatmaya çalışacağım ancak öncesinde bilmemiz gerekenlerden kısaca bahsetmek istiyorum. Mock nesneleri içerisinde MOCK_METHOD fonksiyonu ile tanımlamalar yapacağız. Fonksiyonun aldığı parametreler:

  • MOCK_METHOD(void, FonksiyonAdi_1, (), (override));
  • MOCK_METHOD(void, FonksiyonAdi_2, (int parameter_1, int param_2), (override));
  • MOCK_METHOD(int, FonksiyonAdi_3, (), (const, override));

Böyle bir yazımda şunu ifade etmektedir; ilk parametre sizin taklit objeniz üzerinde test etmek için oluşturduğunuz fonksiyonunuzun geri dönüt tipi, ikinci parametre fonksiyon adınız, 3. parametre eğer fonksiyonumuz içerisine bir parametre gönderiyorsak o parametrelerin verilmesi gerekiyor, eğer girilmiyor ise boş gönderilebilir. 4. parametrede ise fonksiyonunuz sabit metot ile kullanılıyorsa belirtilmesi gerekir. Eski versiyon kullanımlarda MOCK_METHOD yerine tercih edilen bir diğer kullanım daha vardır:

  • MOCK_METHOD0(FonksiyonAdi_1)
  • MOCK_METHOD1(FonksiyonAdi_2, void(int parameter_1)) // sadece bir parametre aldığı zaman kullanılır
  • MOCK_METHOD2(FonksiyonAdi_2, void(int parameter_1, int parameter_2)) // sadece iki parametre aldığı zaman kullanılır
  • MOCK_CONST_METHOD1(FonksiyonAdi_2, void(int parameter_1)) // const metodu içerdiği zaman kullanılır

5 parametre alan bir fonksiyon için MOCK_METHOD5 makrosu kullanılmalıydı yani kaç parametre varsa sondaki sayı onunla değişmeliydi ancak eğer 10+ parametre alan bir fonksiyonumuz varsa yalnızca MOCK_METHOD10 makrosu kullanılırdı. Yazının ilerleyen bölümlerinde yeni makroyu kullanacağım.

Mock kullanımı esnasında karşımıza ON_CALL ve EXPECT_CALL makroları çıkıyor. ON_CALL makrosu bir testin kaç kez yapıldığı sizin için önemli değilse kullanabileceğiniz bir makro ancak prototip ve kullanım itibari ile EXPECT_CALL ile aynı yapıya sahiptir, EXCEPT_CALL’dan farklı olarak sadece With() ve WillByDefault() fonksiyonları ile birlikte kullanılabilir.

EXPECT_CALL tanımlaması kullanacağımız mock testlerinin vazgeçilmezidir. Ve:

  • With(multi-argument-matchers)
  • Times(cardinality)
  • InSequence(sequences)
  • After(expectations)
  • WillOnce(action)
  • WillRepeatedly(action)
  • RetiresOnSaturation();

fonksiyonları ile birlikte kullanılır. Tanımlamasını yaptığımız fonksiyon çağırıldığında nasıl tepki vereceğini belirtmemizi ister. Yani aşağıdaki gibi bir kullanım yaptığımız zaman;

EXPECT_CALL(obje_adi, getValueFromObject())
    .Times(10)
    .WillOnce(Return(130))
    .WillOnce(Return(140))
    .WillOnce(Return(150))
    .WillRepeatedly(Return(200));

getValueFromObject() fonksyionunu 10 kez çağıracak, ilk çağırmada 130, ikincisinde 130, üçüncüsünde 150 ve sonrasında her seferinde 200 değerini döndürmesini bekliyoruz. Ana hatları ile kullanılacak olan fonksiyonların ne yaptığına bakacak olursak;

  • With(): içerisine girilecek parametre fonksiyonu da yapılacak işleme dahil eder
  • Times(): çalışması beklenen fonksiyonun kaç kez çalıştırılacağını belirtir
  • InSequence(): belirtilen çağrıların istediğiniz sıraya göre yapılmasını istiyorsanız bir sekans oluşturup ardından fonksiyon içerisinde belirtmeniz gerekmektedir
  • After(): çalışma sonrasında beklenen çıktı için kullanılır
  • WillOnce(): 1 kez çalışması sonucunda ortaya çıkacak çıktıyı belirtir
  • WillRepeatedly(): sürekli çalışması sonucunda ortaya çıkacak çıktıyı belirtir
  • RetiresOnSaturation(): istenilen çıktı oluşmadı ancak fonksiyon çalışabileceği en maksimum noktaya kadar çalıştıysa – saturasyon noktası – fonksiyonu sonlandırır

Burada yazılanlar GoogleMock sisteminin ana yapısını oluştursa da bir miktar havada kaldığının farkındayım. Onun için bu özelliklerin birkaç tanesini bir örnek üzerinde kullanarak daha rahat anlamanızı sağlamaya çalışacağım.

Örnek üzerinde GoogleMock

Aşağıda yer alan örnekte basit bir UserInterface sınıfı oluşturarak onun üzerindeki get/set fonksiyonlarını test edecek bir taklit sınıfı oluşturduk. Bu sayede bir arayüze ihtiyac duymadan otomatik olarak testlerimizi gerçekleştirmiş olduk.

Kodlara bakacak olursak ilk olarak test edilmesini istediğimiz sınıfımızı oluşturduk, daha sonra da bu sınıftan türemiş bir mock sınıfı oluşturduk. Ardından get/set fonksiyonlarımızın nasıl çalıştığını görmek için bir DataReminder sınıfı oluşturduk ve bunlara bağlı testlerimizi yazmaya başladık.

EXPECT_CALL içerisinde çağırdığımız fonksiyonlarımız sayesinde DataReminder içerisinde tutulmasını beklediğimiz veriyi oluşturmuş olduk. Son olarak da kontrollerimizi yaparak testin başarıyla tamamlandığını görmüş olduk.

Kaynaklar

https://github.com/google/googletest/blob/master/googlemock/docs/for_dummies.md

https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md

http://donsoft.io/gmock-presentation

Richard Wells – Test-Driven Development in C++/ https://www.linkedin.com/learning/test-driven-development-in-c-plus-plus/add-items-add-item-prices-and-calculate-the-current-total

Kapak Görseli: C++ Unit Testing: Google Test and Google Mock / Udemy – https://www.udemy.com/course/cplusplus-unit-testing-google-test-and-google-mock/

2020 sen nasıl başladın?

Çok uzun zamandır bloguma ne kişisel ne de uğraştığım şeylerle ilgili içerik girmiyordum. Ancak artık bloguma biraz daha önem verip içerikler oluşturmaya karar verdim. Yeni içerikler için de başlangıç olarak hepimizin muzdarip olduğu konuyu kendi özelimde ele almak istedim.

2020 hepimiz için ‘mutluluk’ getirecek bir sene olarak başlamış gibi görünüyordu ama çok geçmeden foyası ortaya çıktı. Depremler, savaşlar, salgın hastalıklar derken herkes için hayat farklı bir hal almaya başladı. Bunun sosyolojik ve ekonomik etkileri içinde bulunduğumuz virüs salgınından kurtulduktan sonra hızlı bir şekilde ortaya çıkacaktır. Sosyologlar konu üzerine onlarca tez yazacaklardır, sosyal medya ekonomistleri ise kimsenin ciddiye alıp dinlemeyeceği yüzlerce methiyeler düzeceklerdir – millet haksız da sayılmaz bu dinlememe konusunda.

Ben geçtiğimiz sene Haziran ayında mezun olduktan sonra Eskişehir’de bir yazılım şirketinde Gömülü Yazılım Mühendisi olarak işe başlamıştım. Ancak bu süreçte başvurusu devam eden de bir TÜBİTAK projemiz vardı, 1512 kapsamında bir girişimcilik programına başvurmuştuk. Aradan geçen birkaç ay içerisinde çalıştığım yerdeki işleri toparlamaya başlamıştık ve TÜBİTAK’a yaptığımız sunumdan da güzel dersler çıkartarak geri döndük. Onaylanması halinde 1 Şubat 2020’de başlayacak 200.000 TL’lik bir destek verilmiş olacaktı. Şimdi düşünüyorum da eğer onaylansaydı ve biz bir yola girdikten sonra böyle bir salgın olayı sebebiyle karantinaya girseydik acaba nasıl bir çıkış yolu arıyor olurduk? İlk defa tecrübe edeceğiniz bir işe atılıyorsunuz – bir şirket yönetiminden bahsediyorum – ve daha ilk ayınızda, belki henüz destek paraları bile yatmamışken karantinaya çekilip evden çalışmaya devam ediyorsunuz. Oldukça didaktik bir durum olabilirdi belki.

Aylar içerisinde artık çalıştığım yerdeki işimden zevk almadığımı fark ettim. Bazıları diyebilir ki “Yeni mezun adamsın, ne zevkinden bahsediyorsun, kazandığın tecrübeye bak sen.” (ki böyle diyen çok adamla karşılaştım) Ama işler bazen o şekilde yürümüyor. Kendime hiçbir şey katamadığım bir ortamda daha fazla kalmak istemedim ve 2020 Şubat ayı başında işimden ayrılarak Eskişehir’deki evimi kapattım. Henüz bir iş bulmadan ayrılmam belki çok doğru değildi ancak ayrılmaya karar verdikten sonraki süreçte hem çalışıp hem de iş aramanın etik olmayacağını düşündüm ve aynı zamanda iş arama esnasında şirkete olan katkımın da düşeceğine emindim ve o yüzden karşı tarafı da mağdur etmemek adına ayrıldım.

Tabii evdeki hesabın çarşıya pek uyduğu söylenemez. Şirketlerle görüşmelerimi yaptım, haber bekleme durumuna geçtim ancak 1 aydır neredeyse hepsi ya uzaktan çalışıyor ya da ücretsiz izindeler. Bu yüzden bu süreçte nasıl geri dönüşler gerçekleşir emin değilim. Karantinadan sonra da ekonomik sebepler baş gösterecektir, bu durumda da çalışan ihtiyacı duyulur mu bilmiyorum.

Ben de ‘işsiz’ hayatımda yaklaşık iki yıldır freelance olarak çalıştığım ajansla birlikte daha fazla iş yapmaya başladım. Özellikle herkesin eve kapandığı bu dönemde firmalar internet sitelerine ve online alışverişe çok önem verir hale geldiler, bu yüzden o tarafta çok büyük bir iş yükü var. Ideasoft altyapısı ile çalışan e-ticaret siteleri için tema geliştirmeye başladık, bu benim yeni tecrübe ettiğim bir olgu oluyor burada.

Aynı zamanda da kendi alanımla ilgili kendimi geliştirmeye de devam ediyorum. Aldığım öneriler neticesinde okuduğum kitaplar ufkumu açtı ve olaylara – mesleki olaylara – farklı bir bakış açısıyla baktığımı hisseder hale geldim. Öğrendiğim yeni şeyleri de öğrendikçe, öğrendiğim kadarıyla YouTube üzerinden anlatmak istedim. Bunun için varolan YouTube kanalımda yeni içerikler üretmeye başladım. Bunlardan ilki yazılımda test tekniklerini öğrendiğim bir içerik serisi haline geldi. C ve C++ uygulamalarımızı test etmek için geliştirilmiş olan GoogleTest framework’unu en basit haliyle anlatmaya çalışıyorum. Hazırda birkaç videom daha var ancak periyodik olarak ekliyorum hepsini. (YouTube’un periyodik video ekleyen kanalları sevdiğini okumuştum bir yerde :)) Zamanla bu seri içerisinde veri yapıları tanımlayıp test etme işlemlerini yapacağınız ve ardından da gömülü sistemlerde nasıl bu tekniği kullanabiliriz onu anlatmaya çalışacağım.

Karantina içerisinde “Hızlı Okuma” tekniklerini öğrenmeye karar verdik. Bunun için Gülseren Şenyüzü – Anlayarak Hızlı Okuma kitabını okuyarak, içerisinde anlatmış olduğu teknikleri her gün pratik yaparak çalışmalara başlamıştım. Yaptığım araştırmalar sonucunda bilgisayar üzerinde göz antrenmanlarını yapabileceğimiz 1-2 programa denk geldim ve onları da kullanmaya başladım. Bugün sanırım 7-8. gün, henüz net bir sonuç elde edemeyeceğimin farkındayım ve bu zinciri kırmadan devam etmeye çalışıyorum.

Aynı zamanda geçtiğimiz 15-16 günlük süreçte

  • Kozmos – Carl Sagan
  • Sherlock Türkiye’de
  • Bir Bilim Adamının Romanı – Oğuz Atay (Mustafa İnan hakkında)

kitaplarını okudum. Özellikle Mustafa İnan’ın hayatı hakkında bilgi edinmek çok güzel oldu. Eski dönem bilim insanlarının hayatını okudukça, 1940-1950 yıllarından böyle kaliteli insanlarımız varken şu an hala bazı şeyleri neden aşamadığımızı düşünüyorum.

Görsel Kaynağı: https://d.neoldu.com/news/71603.jpg