Gömülü Sistemlerde Unit Test Uygulaması (Keil uVision / C ve C++)

Serbay Özkan
6 min readMay 11, 2020

--

Not: Linkedin üzerinden daha önceden yayınladığım bu yazı yazılarımın hepsinin aynı yerde bulunması amacıyla buraya taşınmıştır.

Unit Test (Birim Testi) yazılım alanında çalışan ve bu alanda profesyonel yaklaşım kazanmak için okuyan, araştıran ve kendini geliştiren her yazılımcının eninde sonunda karşılaşacağı ve bu neymiş bir bakayım deyip sonrasında da müptelası olacağı bir yazılım test metodolojisidir.

Türkiye’de gömülü sistemler alanında çalışanların büyük çoğunluğunu Elektrik-Elektronik mühendisliği bölümünden mezun meslektaşlarım oluşturmaktadır. Bu yüzden yazılım mimarileri, veri yapıları ve algoritmalar gibi yazılımın kalbinde bulunan başlıklara daha geç merhaba denilmektedir. Bu gibi dezavantajlara rağmen kişinin eksikliklerini bilerek profesyonel yazılım geliştirme için gerekli teorik ve pratik prensiplerin öğrenilip uygulanmasıyla birlikte bu eksikliklerin kapatılabileceğine inanıyorum. Zaman zaman duyduğumuz elektronikçiden yazılımcı olmaz ön yargısının tamamen yıkılması yönünde çalışan ve kendini geliştiren birisi olarak bu alanda çalışan ve yazılım geliştirmeyi bir zevk olarak gören herkesin bu ön yargıyı kıracağına inanıyorum.

Gömülü sistemlerde kullanılan ve açık kaynak olarak yayınlanan bir çok Unit Test çerçevesi bulunmaktadır. Unity ve Cpputest çerçeveleri gömülü sistemlerde en yaygın kullanılan unit test ortamlarındandır. Bu yazımda hem C hem de C++ dillerine destek verdiği için Cpputest çerçevesini Keil uVision 5 IDE’sine entegre ederek STM32F7 ailesinden bir işlemci üzerinde koşan bir örnek gerçekleştireceğim.

Cpputest açık kaynak olarak yayınlanan temel yapısı Micheal Feathers tarafından, güncel geliştirmeleri de James Grenning ve Bas Vodde tarafından gerçekleştirilen bir çerçevedir. James Grenning gömülü yazılım alanında benim gözümde sanat eseri sayılan “Test-Driven Development for Embedded C” kitabının da yazarıdır. Kitabında Cpputest ve Unity çerçeveleri referans alınmaktadır. Cpputest çerçevesi ile alakalı daha detaylı bilgi almak için yazımın sonunda referanslar kısmındaki linklerden faydalanabilirsiniz.

Keil uVision 5 IDE’sine Cpputest çerçevesini ekleyip uygulama gerçekleştirmek için gerekli adımları ve dikkat edilmesi gereken önemli noktaları sırasıyla anlatmaya çalışacağım.

1) Elinizde bulunan herhangi bir geliştirme kitinde veya cihazınızın üzerinde bulunan işlemci ailesine uygun olarak STM32CubeMX programında sadece clock ve JTAG ayarları yapılmış bir workspace oluşturulmalıdır. Keil uVision ile geliştirme yaptığınız başka firmaların işlemcilerine de aynı adımları uygulamanız mümkündür. Burada dikkat edilmesi gereken en önemli noktalardan biri Unit Test çıktılarını debug(printf) ekranında gözlemlenebilmesi için işlemci clock hızının kaç MHz’e ayarlandığından ve cihazınıza uygun JTAG konfigürasyonunun doğru yapıldığından emin olunmalıdır. Ben örnek uygulama için STM32F746ZGTX serisi işlemci üzerinde sadece clock ve JTAG ayarı yapılmış boş bir workspace oluşturdum.

2) Hem C hem de C++ dillerini birim testlerinde kullanabilmemiz için öncelikle kullanılan derleyecinin iki farklı programlama dilinde yazılmış source dosyalarını derleyebilmesi gerekmektedir. Bunun için öncelikle Keil Uvision 5 IDE sürümünüzü en güncel haline getirmenizi öneririm. IDE güncellemesi yapıldıktan sonra Options -> Target sekmesine gelerek aşağıda belirtilen ARM Compiler versiyonu V6.12 olarak seçilmelidir.

3) Daha sonra Options -> C/C++(AC6) sekmesine gelerek Language/Code Generation bölümünden Language C ve Language C++ ayarları aşağıdaki gibi yapılmalıdır.

4) Workspace ilk olusturulduğunda C++ Exception Handling özelliği her zaman varsayılan olarak devre dışı bırakılır. Unit Test çerçevesinin derlenebilmesi için Misc Controls alanına -fexceptions anahtar kelimesi yazılarak C++ Exception Handling özelliği aktif edilmelidir.

5) Unit Test sonuçlarını görebilmemiz için gerekli olan Debug/Trace ayarlarının yapılması gerekmektedir. Bunun için kullandığınız debugger türü seçilerek Settings bölümüne geçilmelidir.

6) Unit Test çıktılarının görülebilmesi için Debug sekmesinde Adapter ayarlarında Port ayarı SW olarak seçilmelidir. Daha sonrasında Trace sekmesine gelinerek Enable tick’i işaretlenmelidir. Workspace yaratırken işlemci clock hızı kaç MHz’e ayarlandıysa tam değeri Core Clock kutusuna girilmelidir. Clock hızı yanlış girilir ise debug çıktılarını ekranda hiç göremeyebilir ya da anlamsız karakterler olarak gözlemleyebilirsiniz. En son olarak da ITM Stimulus Port ayarları Port 0'a çekilmelidir.

7) Unit Test çerçevesinin tüm source ve header dosyalarını referanslar kısmında linkini paylaştığım github demo projemde Middlewares\Third_Party\CPPUTEST altında topladım. Tüm source dosyalarını projenize “Add Group…” ile alt klasör olusturarak bu alt klasöre taşıyınız. Ben demo örneğinde CPPUTest Lib. adı ile bir alt klasör oluşturdum. Taşıdıktan sonra dikkat etmeniz gereken nokta ise derleyicinin header dosyalarını görebilmesi için kütüphane dosya yolunu Options -> C/C++(AC6) sekmesinde Include Paths’e eklemeniz gerekmektedir.

8) UtestPlatform.cpp dosyası platform-specific bir dosyadır. Keil dışında herhangi bir IDE ile çalışmak isteniliyor ise cpputest github sayfasından kullanılan platforma özel dosya indirilip UtestPlatform.cpp dosyası güncellenmelidir.

İlgili adımlar tamamlandıktan sonra proje derlenerek uygulama için hazır hale getirilmelidir. ARM Microlib kütüphanesini kapatmadığımız için compiler aşağıdaki gibi bir uyarı verecektir ama bu uyarının projenin çalışmasında herhangi bir etkisi bulunmamaktadır.

*** Warning: You are compiling one or more files of source type C++ and have selected ‘use MicroLIB’. MicroLIB does not support C++!

MicroLIB ARM’ın geliştirdiği ve normal standart kütüphanelere göre daha az kod alanı ve hafıza kullanımı sağlayan bir kütüphanedir. Kendim de MicroLIB kütüphane desteği açıkken ve kapalıyken olmak üzere iki farklı senaryo ile yakın zamanda kod ve hafıza testleri gerçekleştirdim ve gerçekten MicroLIB kullanmanın çok önemli avantajlar sağladığını söyleyebilirim.

9) Proje başarılı bir şekilde derlendikten sonra artık ilk Unit Test uygulamasını gerçekleştirmek için yazılım cihaza yüklenerek debug moduna geçilmelidir. UnitTest.cpp dosyasında 3 tane test fonksiyonu oluşturdum. API1 birim testi FAIL fonksiyonu ile her zaman testten kalmaktadır. API2 birim testi iki tane string değişkeni karşılaştırmaktadır ve stringlerin aynı olması durumunda test geçmektedir. En son yazdığım API3 birim testi ise basit bir toplama fonksiyonunu test etmektedir. Beklenilen değerin ve hesaplanan değerin aynı olması durumunda test başarılı olmakta aksi takdirde test kalmaktadır.

Örnek bir uygulama olduğu için Production ve Unit Test kodunu aynı dosyanın (UnitTest.cpp) içerisine yazdım ve class tanımlamasını header dosyası yerine source dosyasında gerçekleştirdim. Doğru yaklaşım hem Production hem Unit Test kodunu farklı dosyalarda tutmak ve tüm class tanımlamalarını da ilgili header dosyasında yapmaktır.

10) Proje debug moduna alınmalıdır. Kodu koşturmadan önce debug çıktılarının gözlemlenmesi için View -> Serial Windows -> Debug (printf Viewer) açılmalıdır. Kod koşturulduğu zaman main.cpp dosyasında super loop öncesinde CommandLineTestRunner::RunAllTests fonksiyonu ile sistemde bulunan tüm birim test fonksiyonları çalıştırılmaktadır. İlgili fonksiyon çağrıldıktan sonra Debug Viewer ekranında aşağıda paylaştığım birim test sonuçları gözükecektir.

Görüldüğü gibi oluşturulan API1 ve API3 ilgili birim testinden kalmış olarak gözükmektedir sadece API2 testten geçebilmiştir. API1 zaten her zaman testten kalacak şekilde tasarlandı. API3 için oluşturulan testte de beklenen değer ile hesaplanan değer uyuşmamaktadır çünkü beklenen değer üzerinde sapma gerçekleştirildi. Bu yüzden de ilgili API’nin birim testten kaldığı gözükmektedir. Test sonucu olarak da beklenen değerin 310 olduğu ancak fonksiyonun hesapladığı değerin 300 olduğu bu yüzden testten kaldığı gözlemlenebilmektedir.

Bu yazımda Cpputest çerçevesi ve Keil IDE’si ile birim testi gerçekleştirmek için gerekli tüm adımları izah etmeye çalıştım. Birim testleri ve TDD (Test-Driven Development) konuları ile ilgili detaylı bilgi vermek için ayrı bir yazı serisi ele almak gerekiyor. Burada sadece IDE ve unit test framework kullanımı ile ilgili bilgi verilmiştir. Umarım gömülü yazılım alanında çalışan arkadaşlarım için faydalı olur. Sağlıcakla kalın.

Referanslar

--

--

No responses yet